Added player tracing tools, fixed some bugs
This commit is contained in:
BIN
core/assets-raw/sprites/ui/icons/icon-zoom-small.png
Normal file
BIN
core/assets-raw/sprites/ui/icons/icon-zoom-small.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 228 B |
@@ -38,6 +38,15 @@ text.server.refreshing=Refreshing server
|
||||
text.hosts.none=[lightgray]No LAN games found!
|
||||
text.host.invalid=[scarlet]Can't connect to host.
|
||||
text.server.friendlyfire=Friendly Fire
|
||||
text.trace=Trace Player
|
||||
text.trace.playername=Player name: [accent]{0}
|
||||
text.trace.ip=IP: [accent]{0}
|
||||
text.trace.modclient=Modded Client: [accent]{0}
|
||||
text.trace.totalblocksbroken=Total blocks broken: [accent]{0}
|
||||
text.trace.structureblocksbroken=Structure blocks broken: [accent]{0}
|
||||
text.trace.lastblockbroken=Last block broken: [accent]{0}
|
||||
text.trace.totalblocksplaced=Total blocks placed: [accent]{0}
|
||||
text.trace.lastblockplaced=Last block placed: [accent]{0}
|
||||
text.server.bans=Bans
|
||||
text.server.bans.none=No banned players found!
|
||||
text.server.admins=Admins
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 81 KiB |
@@ -1,7 +1,7 @@
|
||||
#Autogenerated file. Do not modify.
|
||||
#Mon Feb 26 10:05:40 EST 2018
|
||||
#Mon Feb 26 17:17:34 EST 2018
|
||||
version=release
|
||||
androidBuildCode=290
|
||||
androidBuildCode=291
|
||||
name=Mindustry
|
||||
code=3.3
|
||||
build=custom build
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
{}
|
||||
@@ -13,6 +13,7 @@ import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.net.NetEvents;
|
||||
import io.anuke.mindustry.net.Packets.ChatPacket;
|
||||
import io.anuke.mindustry.net.Packets.KickReason;
|
||||
import io.anuke.mindustry.net.TraceInfo;
|
||||
import io.anuke.mindustry.ui.fragments.DebugFragment;
|
||||
import io.anuke.mindustry.world.Map;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
@@ -335,8 +336,6 @@ public class ServerControl extends Module {
|
||||
}
|
||||
});
|
||||
|
||||
//assadsad
|
||||
|
||||
handler.register("admin", "<username>", "Make a user admin", arg -> {
|
||||
if(!state.is(State.playing)) {
|
||||
err("Open the server first.");
|
||||
@@ -458,7 +457,7 @@ public class ServerControl extends Module {
|
||||
info(DebugFragment.debugInfo());
|
||||
});
|
||||
|
||||
handler.register("trace", "<x> <y>", "Prints debug info about a block", arg -> {
|
||||
handler.register("traceblock", "<x> <y>", "Prints debug info about a block", arg -> {
|
||||
try{
|
||||
int x = Integer.parseInt(arg[0]);
|
||||
int y = Integer.parseInt(arg[1]);
|
||||
@@ -484,6 +483,39 @@ public class ServerControl extends Module {
|
||||
Log.err("Invalid coordinates passed.");
|
||||
}
|
||||
});
|
||||
|
||||
handler.register("trace", "<username>", "Trace a player's actions", arg -> {
|
||||
if(!state.is(State.playing)) {
|
||||
err("Open the server first.");
|
||||
return;
|
||||
}
|
||||
|
||||
Player target = null;
|
||||
|
||||
for(Player player : playerGroup.all()){
|
||||
if(player.name.equalsIgnoreCase(arg[0])){
|
||||
target = player;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(target != null){
|
||||
TraceInfo info = netServer.admins.getTrace(Net.getConnection(target.clientid).address);
|
||||
Log.info("&lcTrace info for player '{0}':", target.name);
|
||||
Log.info(" &lyEntity ID: {0}", info. playerid);
|
||||
Log.info(" &lyIP: {0}", info.ip);
|
||||
Log.info(" &lymodded client: {0}", info.modclient);
|
||||
Log.info("");
|
||||
Log.info(" &lytotal blocks broken: {0}", info.totalBlocksBroken);
|
||||
Log.info(" &lystructure blocks broken: {0}", info.structureBlocksBroken);
|
||||
Log.info(" &lylast block broken: {0}", info.lastBlockBroken);
|
||||
Log.info("");
|
||||
Log.info(" &lytotal blocks placed: {0}", info.totalBlocksPlaced);
|
||||
Log.info(" &lylast block placed: {0}", info.lastBlockPlaced);
|
||||
}else{
|
||||
info("Nobody with that name could be found.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void readCommands(){
|
||||
|
||||
Reference in New Issue
Block a user