Added player tracing tools, fixed some bugs
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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(){
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ public class Registrator {
|
||||
NetErrorPacket.class,
|
||||
PlayerAdminPacket.class,
|
||||
AdministerRequestPacket.class,
|
||||
TracePacket.class,
|
||||
};
|
||||
private static ObjectIntMap<Class<?>> ids = new ObjectIntMap<>();
|
||||
|
||||
|
||||
21
core/src/io/anuke/mindustry/net/TraceInfo.java
Normal file
21
core/src/io/anuke/mindustry/net/TraceInfo.java
Normal 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;
|
||||
}
|
||||
}
|
||||
53
core/src/io/anuke/mindustry/ui/dialogs/TraceDialog.java
Normal file
53
core/src/io/anuke/mindustry/ui/dialogs/TraceDialog.java
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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){
|
||||
|
||||
Reference in New Issue
Block a user