Added player tracing tools, fixed some bugs

This commit is contained in:
Anuken
2018-02-26 17:20:05 -05:00
parent c90395ee2b
commit 32791b4baa
20 changed files with 464 additions and 250 deletions

View File

@@ -162,9 +162,6 @@ public class NetClient extends Module {
state.wavetime = packet.countdown;
state.wave = packet.wave;
//removed: messing with time isn't necessary anymore
//Timers.resetTime(packet.time + (float) (TimeUtils.timeSinceMillis(packet.timestamp) / 1000.0 * 60.0));
ui.hudfrag.updateItems();
});
@@ -343,6 +340,11 @@ public class NetClient extends Module {
player.isAdmin = packet.admin;
ui.listfrag.rebuild();
});
Net.handleClient(TracePacket.class, packet -> {
Player player = playerGroup.getByID(packet.info.playerid);
ui.traces.show(player, packet.info);
});
}
@Override

View File

@@ -64,19 +64,19 @@ public class NetServer extends Module{
if(Net.getConnection(id) == null ||
admins.isBanned(Net.getConnection(id).address)) return;
admins.setKnownName(Net.getConnection(id).address, packet.name);
String ip = Net.getConnection(id).address;
if(packet.version != Version.build && Version.build != -1){
if(packet.version == -1){
admins.banPlayer(Net.getConnection(id).address);
Net.kickConnection(id, KickReason.banned);
}else {
Net.kickConnection(id, packet.version > Version.build ? KickReason.serverOutdated : KickReason.clientOutdated);
}
admins.setKnownName(ip, packet.name);
if(packet.version != Version.build && Version.build != -1 && packet.version != -1){
Net.kickConnection(id, packet.version > Version.build ? KickReason.serverOutdated : KickReason.clientOutdated);
return;
}
if(packet.version == -1){
admins.getTrace(ip).modclient = true;
}
Log.info("Sending data to player '{0}' / {1}", packet.name, id);
Player player = new Player();
@@ -90,6 +90,8 @@ public class NetServer extends Module{
player.color.set(packet.color);
connections.put(id, player);
admins.getTrace(ip).playerid = player.id;
if(world.getMap().custom){
ByteArrayOutputStream stream = new ByteArrayOutputStream();
NetworkIO.writeMap(world.getMap(), stream);
@@ -164,15 +166,20 @@ public class NetServer extends Module{
Net.handleServer(PlacePacket.class, (id, packet) -> {
packet.playerid = connections.get(id).id;
if(!Placement.validPlace(packet.x, packet.y, Block.getByID(packet.block))) return;
Block block = Block.getByID(packet.block);
Recipe recipe = Recipes.getByResult(Block.getByID(packet.block));
if(!Placement.validPlace(packet.x, packet.y, block)) return;
Recipe recipe = Recipes.getByResult(block);
if(recipe == null) return;
state.inventory.removeItems(recipe.requirements);
Placement.placeBlock(packet.x, packet.y, Block.getByID(packet.block), packet.rotation, true, false);
Placement.placeBlock(packet.x, packet.y, block, packet.rotation, true, false);
admins.getTrace(Net.getConnection(id).address).lastBlockPlaced = block;
admins.getTrace(Net.getConnection(id).address).totalBlocksPlaced ++;
Net.send(packet, SendMode.tcp);
});
@@ -182,7 +189,14 @@ public class NetServer extends Module{
if(!Placement.validBreak(packet.x, packet.y)) return;
Placement.breakBlock(packet.x, packet.y, true, false);
Block block = Placement.breakBlock(packet.x, packet.y, true, false);
if(block != null) {
admins.getTrace(Net.getConnection(id).address).lastBlockBroken = block;
admins.getTrace(Net.getConnection(id).address).totalBlocksBroken++;
if (block.update || block.destructible)
admins.getTrace(Net.getConnection(id).address).structureBlocksBroken++;
}
Net.send(packet, SendMode.tcp);
});
@@ -252,18 +266,25 @@ public class NetServer extends Module{
Player other = playerGroup.getByID(packet.id);
if(other == null){
Log.err("{0} attempted to perform admin action on nonexistant player.", player.name);
if(other == null || other.isAdmin){
Log.err("{0} attempted to perform admin action on nonexistant or admin player.", player.name);
return;
}
String ip = Net.getConnection(other.clientid).address;
if(packet.action == AdminAction.ban){
admins.banPlayer(Net.getConnection(other.clientid).address);
admins.banPlayer(ip);
Net.kickConnection(other.clientid, KickReason.banned);
Log.info("&lc{0} has banned {1}.", player.name, other.name);
}else if(packet.action == AdminAction.kick){
Net.kickConnection(other.clientid, KickReason.kick);
Log.info("&lc{0} has kicked {1}.", player.name, other.name);
}else if(packet.action == AdminAction.trace){
TracePacket trace = new TracePacket();
trace.info = admins.getTrace(ip);
Net.sendTo(other.clientid, trace, SendMode.tcp);
Log.info("&lc{0} has requested trace info of {1}.", player.name, other.name);
}
});
}
@@ -287,6 +308,7 @@ public class NetServer extends Module{
public void reset(){
weapons.clear();
admins.clearTraces();
}
void sync(){

View File

@@ -47,6 +47,7 @@ public class UI extends SceneModule{
public LanguageDialog language;
public BansDialog bans;
public AdminsDialog admins;
public TraceDialog traces;
public final MenuFragment menufrag = new MenuFragment();
public final ToolFragment toolfrag = new ToolFragment();
@@ -154,6 +155,7 @@ public class UI extends SceneModule{
host = new HostDialog();
bans = new BansDialog();
admins = new AdminsDialog();
traces = new TraceDialog();
build.begin(scene);

View File

@@ -85,7 +85,8 @@ public class EnemyType {
if(isCalculating(enemy)){
Draw.color(Color.SKY);
Lines.polySeg(20, 0, 5, enemy.x, enemy.y, 11f, Timers.time() * 2f + enemy.id*52153f);
Lines.polySeg(20, 0, 4, enemy.x, enemy.y, 11f, Timers.time() * 2f + enemy.id*52f);
Lines.polySeg(20, 0, 4, enemy.x, enemy.y, 11f, Timers.time() * 2f + enemy.id*52f + 180f);
Draw.color();
}

View File

@@ -56,4 +56,9 @@ public class TargetType extends EnemyType {
new Enemy(EnemyTypes.target).set(enemy.x, enemy.y).add();
});
}
@Override
public boolean isCalculating(Enemy enemy){
return false;
}
}

View File

@@ -10,6 +10,7 @@ public class Administration {
private Array<String> bannedIPS = new Array<>();
private Array<String> admins = new Array<>();
private ObjectMap<String, String> known = new ObjectMap<>();
private ObjectMap<String, TraceInfo> traces = new ObjectMap<>();
public Administration(){
Settings.defaultList(
@@ -21,6 +22,16 @@ public class Administration {
load();
}
public TraceInfo getTrace(String ip){
if(!traces.containsKey(ip)) traces.put(ip, new TraceInfo(ip));
return traces.get(ip);
}
public void clearTraces(){
traces.clear();
}
/**Sets last known name for an IP.*/
public void setKnownName(String ip, String name){
known.put(ip, name);

View File

@@ -13,7 +13,7 @@ import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.entities.Entity;
import static io.anuke.mindustry.Vars.netCommon;
import static io.anuke.mindustry.Vars.*;
public class NetEvents {
@@ -165,4 +165,12 @@ public class NetEvents {
packet.action = action;
Net.send(packet, SendMode.tcp);
}
public static void handleTraceRequest(Player target){
if(Net.client()) {
handleAdministerRequest(target, AdminAction.trace);
}else{
ui.traces.show(target, netServer.admins.getTrace(Net.getConnection(target.clientid).address));
}
}
}

View File

@@ -8,6 +8,7 @@ import io.anuke.mindustry.io.Version;
import io.anuke.mindustry.net.Packet.ImportantPacket;
import io.anuke.mindustry.net.Packet.UnimportantPacket;
import io.anuke.mindustry.resource.Item;
import io.anuke.mindustry.world.Block;
import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.entities.EntityGroup;
@@ -612,6 +613,43 @@ public class Packets {
}
public enum AdminAction{
kick, ban
kick, ban, trace
}
public static class TracePacket implements Packet{
public TraceInfo info;
@Override
public void write(ByteBuffer buffer) {
buffer.putInt(info.playerid);
buffer.putShort((short)info.ip.getBytes().length);
buffer.put(info.ip.getBytes());
buffer.put(info.modclient ? (byte)1 : 0);
buffer.putInt(info.totalBlocksBroken);
buffer.putInt(info.structureBlocksBroken);
buffer.putInt(info.lastBlockBroken.id);
buffer.putInt(info.totalBlocksPlaced);
buffer.putInt(info.lastBlockPlaced.id);
}
@Override
public void read(ByteBuffer buffer) {
int id = buffer.getInt();
short iplen = buffer.getShort();
byte[] ipb = new byte[iplen];
buffer.get(ipb);
info = new TraceInfo(new String(ipb));
info.playerid = id;
info.modclient = buffer.get() == 1;
info.totalBlocksBroken = buffer.getInt();
info.structureBlocksBroken = buffer.getInt();
info.lastBlockBroken = Block.getByID(buffer.getInt());
info.totalBlocksPlaced = buffer.getInt();
info.lastBlockPlaced = Block.getByID(buffer.getInt());
}
}
}

View File

@@ -44,6 +44,7 @@ public class Registrator {
NetErrorPacket.class,
PlayerAdminPacket.class,
AdministerRequestPacket.class,
TracePacket.class,
};
private static ObjectIntMap<Class<?>> ids = new ObjectIntMap<>();

View File

@@ -0,0 +1,21 @@
package io.anuke.mindustry.net;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.blocks.Blocks;
public class TraceInfo {
public int playerid;
public String ip;
public boolean modclient;
public int totalBlocksBroken;
public int structureBlocksBroken;
public Block lastBlockBroken = Blocks.air;
public int totalBlocksPlaced;
public Block lastBlockPlaced = Blocks.air;
public TraceInfo(String ip){
this.ip = ip;
}
}

View File

@@ -0,0 +1,53 @@
package io.anuke.mindustry.ui.dialogs;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.net.TraceInfo;
import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.ucore.util.Bundles;
public class TraceDialog extends FloatingDialog {
public TraceDialog(){
super("$text.trace");
addCloseButton();
}
public void show(Player player, TraceInfo info){
content().clear();
Table table = new Table("button");
table.margin(14);
table.defaults().pad(1);
table.defaults().left();
table.add(Bundles.format("text.trace.playername", player.name));
table.row();
table.add(Bundles.format("text.trace.ip", info.ip));
table.row();
table.add(Bundles.format("text.trace.modclient", info.modclient));
table.row();
table.add().pad(5);
table.row();
table.add(Bundles.format("text.trace.totalblocksbroken", info.totalBlocksBroken));
table.row();
table.add(Bundles.format("text.trace.structureblocksbroken", info.structureBlocksBroken));
table.row();
table.add(Bundles.format("text.trace.lastblockbroken", info.lastBlockBroken));
table.row();
table.add().pad(5);
table.row();
table.add(Bundles.format("text.trace.totalblocksplaced", info.totalBlocksPlaced));
table.row();
table.add(Bundles.format("text.trace.lastblockplaced", info.lastBlockPlaced));
table.row();
content().add(table);
show();
}
}

View File

@@ -117,7 +117,7 @@ public class PlayerListFragment implements Fragment{
button.addImage("icon-admin").size(14*2).visible(() -> player.isAdmin && !(!player.isLocal && Net.server())).padRight(5);
if((Net.server() || Vars.player.isAdmin) && !player.isLocal && !player.isAdmin){
if((Net.server() || Vars.player.isAdmin) && !player.isLocal && (!player.isAdmin || Net.server())){
button.add().growY();
float bs = (h + 14)/2f;
@@ -163,8 +163,8 @@ public class PlayerListFragment implements Fragment{
}).update(b -> b.setChecked(connection != null && netServer.admins.isAdmin(connection.address)))
.disabled(Net.client());
//TODO unused?
t.addImageButton("icon-cancel", 14*2, () -> {});
//TODO trace info for player
t.addImageButton("icon-zoom-small", 14*2, () -> NetEvents.handleTraceRequest(player));
}).padRight(12).padTop(-5).padLeft(0).padBottom(-10).size(bs + 10f, bs);

View File

@@ -21,10 +21,11 @@ import static io.anuke.mindustry.Vars.*;
public class Placement {
private static final Rectangle rect = new Rectangle();
public static void breakBlock(int x, int y, boolean effect, boolean sound){
/**Returns block type that was broken, or null if unsuccesful.*/
public static Block breakBlock(int x, int y, boolean effect, boolean sound){
Tile tile = world.tile(x, y);
if(tile == null) return;
if(tile == null) return null;
Block block = tile.isLinked() ? tile.getLinked().block() : tile.block();
Recipe result = Recipes.getByResult(block);
@@ -53,6 +54,8 @@ public class Placement {
if(effect) Effects.effect(Fx.breakBlock, toremove.worldx(), toremove.worldy());
}
}
return block;
}
public static void placeBlock(int x, int y, Block result, int rotation, boolean effects, boolean sound){