Added configurable anti-grief
This commit is contained in:
@@ -14,6 +14,7 @@ import io.anuke.mindustry.net.Packets.*;
|
|||||||
import io.anuke.mindustry.resource.*;
|
import io.anuke.mindustry.resource.*;
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
import io.anuke.mindustry.world.Placement;
|
import io.anuke.mindustry.world.Placement;
|
||||||
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.ucore.core.Events;
|
import io.anuke.ucore.core.Events;
|
||||||
import io.anuke.ucore.core.Timers;
|
import io.anuke.ucore.core.Timers;
|
||||||
import io.anuke.ucore.entities.Entities;
|
import io.anuke.ucore.entities.Entities;
|
||||||
@@ -199,6 +200,14 @@ public class NetServer extends Module{
|
|||||||
|
|
||||||
if(recipe == null) return;
|
if(recipe == null) return;
|
||||||
|
|
||||||
|
Tile tile = world.tile(packet.x, packet.y);
|
||||||
|
if(tile.synthetic() && !admins.validateBreak(admins.getTrace(Net.getConnection(id).address).uuid, Net.getConnection(id).address)){
|
||||||
|
if(Timers.get("break-message-" + id, 120)){
|
||||||
|
sendMessageTo(id, "[scarlet]Anti-grief: you are replacing blocks too quickly. wait until replacing again.");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
state.inventory.removeItems(recipe.requirements);
|
state.inventory.removeItems(recipe.requirements);
|
||||||
|
|
||||||
Placement.placeBlock(packet.x, packet.y, block, packet.rotation, true, false);
|
Placement.placeBlock(packet.x, packet.y, block, packet.rotation, true, false);
|
||||||
@@ -215,6 +224,15 @@ public class NetServer extends Module{
|
|||||||
|
|
||||||
if(!Placement.validBreak(packet.x, packet.y)) return;
|
if(!Placement.validBreak(packet.x, packet.y)) return;
|
||||||
|
|
||||||
|
Tile tile = world.tile(packet.x, packet.y);
|
||||||
|
|
||||||
|
if(tile.synthetic() && !admins.validateBreak(admins.getTrace(Net.getConnection(id).address).uuid, Net.getConnection(id).address)){
|
||||||
|
if(Timers.get("break-message-" + id, 120)){
|
||||||
|
sendMessageTo(id, "[scarlet]Anti-grief: you are breaking blocks too quickly. wait until breaking again.");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Block block = Placement.breakBlock(packet.x, packet.y, true, false);
|
Block block = Placement.breakBlock(packet.x, packet.y, true, false);
|
||||||
|
|
||||||
if(block != null) {
|
if(block != null) {
|
||||||
@@ -376,6 +394,12 @@ public class NetServer extends Module{
|
|||||||
admins.save();
|
admins.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sendMessageTo(int id, String message){
|
||||||
|
ChatPacket packet = new ChatPacket();
|
||||||
|
packet.text = message;
|
||||||
|
Net.sendTo(id, packet, SendMode.tcp);
|
||||||
|
}
|
||||||
|
|
||||||
void sync(){
|
void sync(){
|
||||||
|
|
||||||
if(timer.get(timerEntitySync, serverSyncTime)){
|
if(timer.get(timerEntitySync, serverSyncTime)){
|
||||||
|
|||||||
@@ -3,9 +3,13 @@ package io.anuke.mindustry.net;
|
|||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
import com.badlogic.gdx.utils.Json;
|
import com.badlogic.gdx.utils.Json;
|
||||||
import com.badlogic.gdx.utils.ObjectMap;
|
import com.badlogic.gdx.utils.ObjectMap;
|
||||||
|
import com.badlogic.gdx.utils.TimeUtils;
|
||||||
import io.anuke.ucore.core.Settings;
|
import io.anuke.ucore.core.Settings;
|
||||||
|
|
||||||
public class Administration {
|
public class Administration {
|
||||||
|
public static final int defaultMaxBrokenBlocks = 15;
|
||||||
|
public static final int defaultBreakCooldown = 1000*15;
|
||||||
|
|
||||||
private Json json = new Json();
|
private Json json = new Json();
|
||||||
/**All player info. Maps UUIDs to info. This persists throughout restarts.*/
|
/**All player info. Maps UUIDs to info. This persists throughout restarts.*/
|
||||||
private ObjectMap<String, PlayerInfo> playerInfo = new ObjectMap<>();
|
private ObjectMap<String, PlayerInfo> playerInfo = new ObjectMap<>();
|
||||||
@@ -14,12 +18,68 @@ public class Administration {
|
|||||||
private Array<String> bannedIPs = new Array<>();
|
private Array<String> bannedIPs = new Array<>();
|
||||||
|
|
||||||
public Administration(){
|
public Administration(){
|
||||||
Settings.defaults("playerInfo", "{}");
|
Settings.defaultList(
|
||||||
Settings.defaults("bannedIPs", "{}");
|
"playerInfo", "{}",
|
||||||
|
"bannedIPs", "{}",
|
||||||
|
"antigrief", false,
|
||||||
|
"antigrief-max", defaultMaxBrokenBlocks,
|
||||||
|
"antigrief-cooldown", defaultBreakCooldown
|
||||||
|
);
|
||||||
|
|
||||||
load();
|
load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAntiGrief(){
|
||||||
|
return Settings.getBool("antigrief");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAntiGrief(boolean antiGrief){
|
||||||
|
Settings.putBool("antigrief", antiGrief);
|
||||||
|
Settings.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAntiGriefParams(int maxBreak, int cooldown){
|
||||||
|
Settings.putInt("antigrief-max", maxBreak);
|
||||||
|
Settings.putInt("antigrief-cooldown", cooldown);
|
||||||
|
Settings.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean validateBreak(String id, String ip){
|
||||||
|
if(!isAntiGrief() || isAdmin(id, ip)) return true;
|
||||||
|
|
||||||
|
PlayerInfo info = getCreateInfo(id);
|
||||||
|
|
||||||
|
if(info.lastBroken == null || info.lastBroken.length != Settings.getInt("antigrief-max")){
|
||||||
|
info.lastBroken = new long[Settings.getInt("antigrief-max")];
|
||||||
|
}
|
||||||
|
|
||||||
|
long[] breaks = info.lastBroken;
|
||||||
|
|
||||||
|
int shiftBy = 0;
|
||||||
|
for(int i = 0; i < breaks.length && breaks[i] != 0; i ++){
|
||||||
|
if(TimeUtils.timeSinceMillis(breaks[i]) >= Settings.getInt("antigrief-cooldown")){
|
||||||
|
shiftBy = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < breaks.length; i++) {
|
||||||
|
breaks[i] = (i + shiftBy >= breaks.length) ? 0 : breaks[i + shiftBy];
|
||||||
|
}
|
||||||
|
|
||||||
|
int remaining = 0;
|
||||||
|
for(int i = 0; i < breaks.length; i ++){
|
||||||
|
if(breaks[i] == 0){
|
||||||
|
remaining = breaks.length - i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(remaining == 0) return false;
|
||||||
|
|
||||||
|
breaks[breaks.length - remaining] = TimeUtils.millis();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**Call when a player joins to update their information here.*/
|
/**Call when a player joins to update their information here.*/
|
||||||
public void updatePlayerJoined(String id, String ip, String name){
|
public void updatePlayerJoined(String id, String ip, String name){
|
||||||
PlayerInfo info = getCreateInfo(id);
|
PlayerInfo info = getCreateInfo(id);
|
||||||
@@ -248,6 +308,8 @@ public class Administration {
|
|||||||
public boolean banned, admin;
|
public boolean banned, admin;
|
||||||
public long lastKicked; //last kicked timestamp
|
public long lastKicked; //last kicked timestamp
|
||||||
|
|
||||||
|
public long[] lastBroken;
|
||||||
|
|
||||||
PlayerInfo(String id){
|
PlayerInfo(String id){
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,6 +181,11 @@ public class Tile{
|
|||||||
return isLinked() || !((floor.solid && (block == Blocks.air || block.solidifes)) || (block.solid && (!block.destructible && !block.update)));
|
return isLinked() || !((floor.solid && (block == Blocks.air || block.solidifes)) || (block.solid && (!block.destructible && !block.update)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean synthetic(){
|
||||||
|
Block block = block();
|
||||||
|
return block.update || block.destructible;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean solid(){
|
public boolean solid(){
|
||||||
Block block = block();
|
Block block = block();
|
||||||
Block floor = floor();
|
Block floor = floor();
|
||||||
|
|||||||
@@ -10,13 +10,10 @@ import io.anuke.mindustry.game.EventType.GameOverEvent;
|
|||||||
import io.anuke.mindustry.game.GameMode;
|
import io.anuke.mindustry.game.GameMode;
|
||||||
import io.anuke.mindustry.io.SaveIO;
|
import io.anuke.mindustry.io.SaveIO;
|
||||||
import io.anuke.mindustry.io.Version;
|
import io.anuke.mindustry.io.Version;
|
||||||
|
import io.anuke.mindustry.net.*;
|
||||||
import io.anuke.mindustry.net.Administration.PlayerInfo;
|
import io.anuke.mindustry.net.Administration.PlayerInfo;
|
||||||
import io.anuke.mindustry.net.Net;
|
|
||||||
import io.anuke.mindustry.net.NetConnection;
|
|
||||||
import io.anuke.mindustry.net.NetEvents;
|
|
||||||
import io.anuke.mindustry.net.Packets.ChatPacket;
|
import io.anuke.mindustry.net.Packets.ChatPacket;
|
||||||
import io.anuke.mindustry.net.Packets.KickReason;
|
import io.anuke.mindustry.net.Packets.KickReason;
|
||||||
import io.anuke.mindustry.net.TraceInfo;
|
|
||||||
import io.anuke.mindustry.ui.fragments.DebugFragment;
|
import io.anuke.mindustry.ui.fragments.DebugFragment;
|
||||||
import io.anuke.mindustry.world.Map;
|
import io.anuke.mindustry.world.Map;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
@@ -254,7 +251,7 @@ public class ServerControl extends Module {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.register("friendlyfire", "<on/off>", "Enable or disable friendly fire", arg -> {
|
handler.register("friendlyfire", "<on/off>", "Enable or disable friendly fire.", arg -> {
|
||||||
String s = arg[0];
|
String s = arg[0];
|
||||||
if(s.equalsIgnoreCase("on")){
|
if(s.equalsIgnoreCase("on")){
|
||||||
NetEvents.handleFriendlyFireChange(true);
|
NetEvents.handleFriendlyFireChange(true);
|
||||||
@@ -269,6 +266,35 @@ public class ServerControl extends Module {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
handler.register("antigrief", "[on/off] [max-break] [cooldown-in-ms]", "Enable or disable anti-grief.", arg -> {
|
||||||
|
if(arg.length == 0){
|
||||||
|
info("Anti-grief is currently &lc{0}.", netServer.admins.isAntiGrief() ? "on" : "off");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String s = arg[0];
|
||||||
|
if(s.equalsIgnoreCase("on")){
|
||||||
|
netServer.admins.setAntiGrief(true);
|
||||||
|
info("Anti-grief enabled.");
|
||||||
|
}else if(s.equalsIgnoreCase("off")){
|
||||||
|
netServer.admins.setAntiGrief(false);
|
||||||
|
info("Anti-grief disabled.");
|
||||||
|
}else{
|
||||||
|
err("Incorrect command usage.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(arg.length >= 2) {
|
||||||
|
try {
|
||||||
|
int maxbreak = Integer.parseInt(arg[1]);
|
||||||
|
int cooldown = (arg.length >= 3 ? Integer.parseInt(arg[2]) : Administration.defaultBreakCooldown);
|
||||||
|
netServer.admins.setAntiGriefParams(maxbreak, cooldown);
|
||||||
|
info("Anti-grief parameters set.");
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
err("Invalid number format.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
handler.register("shuffle", "<normal/custom/both/off>", "Set map shuffling.", arg -> {
|
handler.register("shuffle", "<normal/custom/both/off>", "Set map shuffling.", arg -> {
|
||||||
|
|
||||||
try{
|
try{
|
||||||
|
|||||||
Reference in New Issue
Block a user