summaryrefslogtreecommitdiff
path: root/enigma-server/src/main/java
diff options
context:
space:
mode:
authorGravatar 2xsaiko2021-07-08 16:30:39 +0200
committerGravatar GitHub2021-07-08 16:30:39 +0200
commit8efb62490ec153246d467a1a72c513781db887bf (patch)
tree0f2eedd97d9c0d95544ff7d24f2b479cf10271fe /enigma-server/src/main/java
parentAdd --single-class-tree argument that puts all classes into deobf panel & hid... (diff)
downloadenigma-fork-8efb62490ec153246d467a1a72c513781db887bf.tar.gz
enigma-fork-8efb62490ec153246d467a1a72c513781db887bf.tar.xz
enigma-fork-8efb62490ec153246d467a1a72c513781db887bf.zip
Entry Changes (#364)
* Initial refactor: Allow EntryMapping to have null targetName, add EntryChange in favor of entry changing methods in GuiController * Fix resetting name not actually removing it, and renaming a class causing name collisions with itself Closes #246. * Use name proposer for setting default deobf name Closes #314 * Make network protocol use EntryChange directly * Handle writing other data correctly when the deobf name is null * b * Add some new abstraction stuff * Use pattern matching instanceof * Move classes out of newabstraction package * Make EntryChange final * Regenerate equals and hashCode * Convert EntryMapping to record * Make TristateChange final * Safety guard null accessModifier initialization
Diffstat (limited to 'enigma-server/src/main/java')
-rw-r--r--enigma-server/src/main/java/cuchaz/enigma/network/ClientPacketHandler.java12
-rw-r--r--enigma-server/src/main/java/cuchaz/enigma/network/EnigmaServer.java9
-rw-r--r--enigma-server/src/main/java/cuchaz/enigma/network/packet/ChangeDocsC2SPacket.java64
-rw-r--r--enigma-server/src/main/java/cuchaz/enigma/network/packet/ChangeDocsS2CPacket.java51
-rw-r--r--enigma-server/src/main/java/cuchaz/enigma/network/packet/EntryChangeC2SPacket.java66
-rw-r--r--enigma-server/src/main/java/cuchaz/enigma/network/packet/EntryChangeS2CPacket.java42
-rw-r--r--enigma-server/src/main/java/cuchaz/enigma/network/packet/MarkDeobfuscatedC2SPacket.java56
-rw-r--r--enigma-server/src/main/java/cuchaz/enigma/network/packet/MarkDeobfuscatedS2CPacket.java47
-rw-r--r--enigma-server/src/main/java/cuchaz/enigma/network/packet/PacketHelper.java130
-rw-r--r--enigma-server/src/main/java/cuchaz/enigma/network/packet/PacketRegistry.java16
-rw-r--r--enigma-server/src/main/java/cuchaz/enigma/network/packet/RemoveMappingC2SPacket.java56
-rw-r--r--enigma-server/src/main/java/cuchaz/enigma/network/packet/RemoveMappingS2CPacket.java47
-rw-r--r--enigma-server/src/main/java/cuchaz/enigma/network/packet/RenameC2SPacket.java66
-rw-r--r--enigma-server/src/main/java/cuchaz/enigma/network/packet/RenameS2CPacket.java55
-rw-r--r--enigma-server/src/main/java/cuchaz/enigma/network/packet/SyncMappingsS2CPacket.java41
15 files changed, 232 insertions, 526 deletions
diff --git a/enigma-server/src/main/java/cuchaz/enigma/network/ClientPacketHandler.java b/enigma-server/src/main/java/cuchaz/enigma/network/ClientPacketHandler.java
index 1b0191b..a651fe8 100644
--- a/enigma-server/src/main/java/cuchaz/enigma/network/ClientPacketHandler.java
+++ b/enigma-server/src/main/java/cuchaz/enigma/network/ClientPacketHandler.java
@@ -1,24 +1,16 @@
1package cuchaz.enigma.network; 1package cuchaz.enigma.network;
2 2
3import cuchaz.enigma.analysis.EntryReference; 3import cuchaz.enigma.translation.mapping.EntryChange;
4import cuchaz.enigma.translation.mapping.EntryMapping; 4import cuchaz.enigma.translation.mapping.EntryMapping;
5import cuchaz.enigma.translation.mapping.tree.EntryTree; 5import cuchaz.enigma.translation.mapping.tree.EntryTree;
6import cuchaz.enigma.network.packet.Packet; 6import cuchaz.enigma.network.packet.Packet;
7import cuchaz.enigma.translation.representation.entry.Entry;
8import cuchaz.enigma.utils.validation.ValidationContext;
9 7
10import java.util.List; 8import java.util.List;
11 9
12public interface ClientPacketHandler { 10public interface ClientPacketHandler {
13 void openMappings(EntryTree<EntryMapping> mappings); 11 void openMappings(EntryTree<EntryMapping> mappings);
14 12
15 void rename(ValidationContext vc, EntryReference<Entry<?>, Entry<?>> reference, String newName, boolean refreshClassTree); 13 boolean applyChangeFromServer(EntryChange<?> change);
16
17 void removeMapping(ValidationContext vc, EntryReference<Entry<?>, Entry<?>> reference);
18
19 void changeDocs(ValidationContext vc, EntryReference<Entry<?>, Entry<?>> reference, String updatedDocs);
20
21 void markAsDeobfuscated(ValidationContext vc, EntryReference<Entry<?>, Entry<?>> reference);
22 14
23 void disconnectIfConnected(String reason); 15 void disconnectIfConnected(String reason);
24 16
diff --git a/enigma-server/src/main/java/cuchaz/enigma/network/EnigmaServer.java b/enigma-server/src/main/java/cuchaz/enigma/network/EnigmaServer.java
index 75981c3..1ce359b 100644
--- a/enigma-server/src/main/java/cuchaz/enigma/network/EnigmaServer.java
+++ b/enigma-server/src/main/java/cuchaz/enigma/network/EnigmaServer.java
@@ -8,6 +8,7 @@ import java.util.*;
8import java.util.concurrent.CopyOnWriteArrayList; 8import java.util.concurrent.CopyOnWriteArrayList;
9 9
10import cuchaz.enigma.network.packet.*; 10import cuchaz.enigma.network.packet.*;
11import cuchaz.enigma.translation.mapping.EntryChange;
11import cuchaz.enigma.translation.mapping.EntryMapping; 12import cuchaz.enigma.translation.mapping.EntryMapping;
12import cuchaz.enigma.translation.mapping.EntryRemapper; 13import cuchaz.enigma.translation.mapping.EntryRemapper;
13import cuchaz.enigma.translation.representation.entry.Entry; 14import cuchaz.enigma.translation.representation.entry.Entry;
@@ -16,7 +17,7 @@ public abstract class EnigmaServer {
16 17
17 // https://discordapp.com/channels/507304429255393322/566418023372816394/700292322918793347 18 // https://discordapp.com/channels/507304429255393322/566418023372816394/700292322918793347
18 public static final int DEFAULT_PORT = 34712; 19 public static final int DEFAULT_PORT = 34712;
19 public static final int PROTOCOL_VERSION = 0; 20 public static final int PROTOCOL_VERSION = 1;
20 public static final int CHECKSUM_SIZE = 20; 21 public static final int CHECKSUM_SIZE = 20;
21 public static final int MAX_PASSWORD_LENGTH = 255; // length is written as a byte in the login packet 22 public static final int MAX_PASSWORD_LENGTH = 255; // length is written as a byte in the login packet
22 23
@@ -234,11 +235,11 @@ public abstract class EnigmaServer {
234 235
235 public void sendCorrectMapping(Socket client, Entry<?> entry, boolean refreshClassTree) { 236 public void sendCorrectMapping(Socket client, Entry<?> entry, boolean refreshClassTree) {
236 EntryMapping oldMapping = mappings.getDeobfMapping(entry); 237 EntryMapping oldMapping = mappings.getDeobfMapping(entry);
237 String oldName = oldMapping == null ? null : oldMapping.getTargetName(); 238 String oldName = oldMapping.targetName();
238 if (oldName == null) { 239 if (oldName == null) {
239 sendPacket(client, new RemoveMappingS2CPacket(DUMMY_SYNC_ID, entry)); 240 sendPacket(client, new EntryChangeS2CPacket(DUMMY_SYNC_ID, EntryChange.modify(entry).clearDeobfName()));
240 } else { 241 } else {
241 sendPacket(client, new RenameS2CPacket(0, entry, oldName, refreshClassTree)); 242 sendPacket(client, new EntryChangeS2CPacket(0, EntryChange.modify(entry).withDeobfName(oldName)));
242 } 243 }
243 } 244 }
244 245
diff --git a/enigma-server/src/main/java/cuchaz/enigma/network/packet/ChangeDocsC2SPacket.java b/enigma-server/src/main/java/cuchaz/enigma/network/packet/ChangeDocsC2SPacket.java
deleted file mode 100644
index f3e07c2..0000000
--- a/enigma-server/src/main/java/cuchaz/enigma/network/packet/ChangeDocsC2SPacket.java
+++ /dev/null
@@ -1,64 +0,0 @@
1package cuchaz.enigma.network.packet;
2
3import java.io.DataInput;
4import java.io.DataOutput;
5import java.io.IOException;
6
7import cuchaz.enigma.translation.mapping.EntryMapping;
8import cuchaz.enigma.network.EnigmaServer;
9import cuchaz.enigma.network.Message;
10import cuchaz.enigma.network.ServerPacketHandler;
11import cuchaz.enigma.translation.representation.entry.Entry;
12import cuchaz.enigma.utils.validation.PrintValidatable;
13import cuchaz.enigma.utils.validation.ValidationContext;
14
15public class ChangeDocsC2SPacket implements Packet<ServerPacketHandler> {
16 private Entry<?> entry;
17 private String newDocs;
18
19 ChangeDocsC2SPacket() {
20 }
21
22 public ChangeDocsC2SPacket(Entry<?> entry, String newDocs) {
23 this.entry = entry;
24 this.newDocs = newDocs;
25 }
26
27 @Override
28 public void read(DataInput input) throws IOException {
29 this.entry = PacketHelper.readEntry(input);
30 this.newDocs = PacketHelper.readString(input);
31 }
32
33 @Override
34 public void write(DataOutput output) throws IOException {
35 PacketHelper.writeEntry(output, entry);
36 PacketHelper.writeString(output, newDocs);
37 }
38
39 @Override
40 public void handle(ServerPacketHandler handler) {
41 ValidationContext vc = new ValidationContext();
42 vc.setActiveElement(PrintValidatable.INSTANCE);
43
44 EntryMapping mapping = handler.getServer().getMappings().getDeobfMapping(entry);
45
46 boolean valid = handler.getServer().canModifyEntry(handler.getClient(), entry);
47 if (!valid) {
48 String oldDocs = mapping == null ? null : mapping.getJavadoc();
49 handler.getServer().sendPacket(handler.getClient(), new ChangeDocsS2CPacket(EnigmaServer.DUMMY_SYNC_ID, entry, oldDocs == null ? "" : oldDocs));
50 return;
51 }
52
53 if (mapping == null) {
54 mapping = new EntryMapping(handler.getServer().getMappings().deobfuscate(entry).getName());
55 }
56 handler.getServer().getMappings().mapFromObf(vc, entry, mapping.withDocs(newDocs.isBlank() ? null : newDocs));
57
58 if (!vc.canProceed()) return;
59
60 int syncId = handler.getServer().lockEntry(handler.getClient(), entry);
61 handler.getServer().sendToAllExcept(handler.getClient(), new ChangeDocsS2CPacket(syncId, entry, newDocs));
62 handler.getServer().sendMessage(Message.editDocs(handler.getServer().getUsername(handler.getClient()), entry));
63 }
64}
diff --git a/enigma-server/src/main/java/cuchaz/enigma/network/packet/ChangeDocsS2CPacket.java b/enigma-server/src/main/java/cuchaz/enigma/network/packet/ChangeDocsS2CPacket.java
deleted file mode 100644
index 78fa4fa..0000000
--- a/enigma-server/src/main/java/cuchaz/enigma/network/packet/ChangeDocsS2CPacket.java
+++ /dev/null
@@ -1,51 +0,0 @@
1package cuchaz.enigma.network.packet;
2
3import java.io.DataInput;
4import java.io.DataOutput;
5import java.io.IOException;
6
7import cuchaz.enigma.analysis.EntryReference;
8import cuchaz.enigma.network.ClientPacketHandler;
9import cuchaz.enigma.translation.representation.entry.Entry;
10import cuchaz.enigma.utils.validation.PrintValidatable;
11import cuchaz.enigma.utils.validation.ValidationContext;
12
13public class ChangeDocsS2CPacket implements Packet<ClientPacketHandler> {
14 private int syncId;
15 private Entry<?> entry;
16 private String newDocs;
17
18 ChangeDocsS2CPacket() {
19 }
20
21 public ChangeDocsS2CPacket(int syncId, Entry<?> entry, String newDocs) {
22 this.syncId = syncId;
23 this.entry = entry;
24 this.newDocs = newDocs;
25 }
26
27 @Override
28 public void read(DataInput input) throws IOException {
29 this.syncId = input.readUnsignedShort();
30 this.entry = PacketHelper.readEntry(input);
31 this.newDocs = PacketHelper.readString(input);
32 }
33
34 @Override
35 public void write(DataOutput output) throws IOException {
36 output.writeShort(syncId);
37 PacketHelper.writeEntry(output, entry);
38 PacketHelper.writeString(output, newDocs);
39 }
40
41 @Override
42 public void handle(ClientPacketHandler controller) {
43 ValidationContext vc = new ValidationContext();
44 vc.setActiveElement(PrintValidatable.INSTANCE);
45
46 controller.changeDocs(vc, new EntryReference<>(entry, entry.getName()), newDocs);
47
48 if (!vc.canProceed()) return;
49 controller.sendPacket(new ConfirmChangeC2SPacket(syncId));
50 }
51}
diff --git a/enigma-server/src/main/java/cuchaz/enigma/network/packet/EntryChangeC2SPacket.java b/enigma-server/src/main/java/cuchaz/enigma/network/packet/EntryChangeC2SPacket.java
new file mode 100644
index 0000000..b97877c
--- /dev/null
+++ b/enigma-server/src/main/java/cuchaz/enigma/network/packet/EntryChangeC2SPacket.java
@@ -0,0 +1,66 @@
1package cuchaz.enigma.network.packet;
2
3import java.io.DataInput;
4import java.io.DataOutput;
5import java.io.IOException;
6
7import cuchaz.enigma.network.Message;
8import cuchaz.enigma.network.ServerPacketHandler;
9import cuchaz.enigma.translation.mapping.EntryChange;
10import cuchaz.enigma.translation.mapping.EntryUtil;
11import cuchaz.enigma.utils.validation.PrintValidatable;
12import cuchaz.enigma.utils.validation.ValidationContext;
13
14public class EntryChangeC2SPacket implements Packet<ServerPacketHandler> {
15
16 private EntryChange<?> change;
17
18 EntryChangeC2SPacket() {
19 }
20
21 public EntryChangeC2SPacket(EntryChange<?> change) {
22 this.change = change;
23 }
24
25 @Override
26 public void read(DataInput input) throws IOException {
27 this.change = PacketHelper.readEntryChange(input);
28 }
29
30 @Override
31 public void write(DataOutput output) throws IOException {
32 PacketHelper.writeEntryChange(output, change);
33 }
34
35 @Override
36 public void handle(ServerPacketHandler handler) {
37 ValidationContext vc = new ValidationContext();
38 vc.setActiveElement(PrintValidatable.INSTANCE);
39
40 boolean valid = handler.getServer().canModifyEntry(handler.getClient(), this.change.getTarget());
41
42 if (valid) {
43 EntryUtil.applyChange(vc, handler.getServer().getMappings(), this.change);
44 valid = vc.canProceed();
45 }
46
47 if (!valid) {
48 handler.getServer().sendCorrectMapping(handler.getClient(), this.change.getTarget(), true);
49 return;
50 }
51
52 int syncId = handler.getServer().lockEntry(handler.getClient(), this.change.getTarget());
53 handler.getServer().sendToAllExcept(handler.getClient(), new EntryChangeS2CPacket(syncId, this.change));
54
55 if (this.change.getDeobfName().isSet()) {
56 handler.getServer().sendMessage(Message.rename(handler.getServer().getUsername(handler.getClient()), this.change.getTarget(), this.change.getDeobfName().getNewValue()));
57 } else if (this.change.getDeobfName().isReset()) {
58 handler.getServer().sendMessage(Message.removeMapping(handler.getServer().getUsername(handler.getClient()), this.change.getTarget()));
59 }
60
61 if (!this.change.getJavadoc().isUnchanged()) {
62 handler.getServer().sendMessage(Message.editDocs(handler.getServer().getUsername(handler.getClient()), this.change.getTarget()));
63 }
64 }
65
66}
diff --git a/enigma-server/src/main/java/cuchaz/enigma/network/packet/EntryChangeS2CPacket.java b/enigma-server/src/main/java/cuchaz/enigma/network/packet/EntryChangeS2CPacket.java
new file mode 100644
index 0000000..a237b91
--- /dev/null
+++ b/enigma-server/src/main/java/cuchaz/enigma/network/packet/EntryChangeS2CPacket.java
@@ -0,0 +1,42 @@
1package cuchaz.enigma.network.packet;
2
3import java.io.DataInput;
4import java.io.DataOutput;
5import java.io.IOException;
6
7import cuchaz.enigma.network.ClientPacketHandler;
8import cuchaz.enigma.translation.mapping.EntryChange;
9
10public class EntryChangeS2CPacket implements Packet<ClientPacketHandler> {
11
12 private int syncId;
13 private EntryChange<?> change;
14
15 public EntryChangeS2CPacket(int syncId, EntryChange<?> change) {
16 this.syncId = syncId;
17 this.change = change;
18 }
19
20 EntryChangeS2CPacket() {
21 }
22
23 @Override
24 public void read(DataInput input) throws IOException {
25 this.syncId = input.readUnsignedShort();
26 this.change = PacketHelper.readEntryChange(input);
27 }
28
29 @Override
30 public void write(DataOutput output) throws IOException {
31 output.writeShort(this.syncId);
32 PacketHelper.writeEntryChange(output, this.change);
33 }
34
35 @Override
36 public void handle(ClientPacketHandler handler) {
37 if (handler.applyChangeFromServer(this.change)) {
38 handler.sendPacket(new ConfirmChangeC2SPacket(this.syncId));
39 }
40 }
41
42}
diff --git a/enigma-server/src/main/java/cuchaz/enigma/network/packet/MarkDeobfuscatedC2SPacket.java b/enigma-server/src/main/java/cuchaz/enigma/network/packet/MarkDeobfuscatedC2SPacket.java
deleted file mode 100644
index 732c744..0000000
--- a/enigma-server/src/main/java/cuchaz/enigma/network/packet/MarkDeobfuscatedC2SPacket.java
+++ /dev/null
@@ -1,56 +0,0 @@
1package cuchaz.enigma.network.packet;
2
3import java.io.DataInput;
4import java.io.DataOutput;
5import java.io.IOException;
6
7import cuchaz.enigma.network.Message;
8import cuchaz.enigma.network.ServerPacketHandler;
9import cuchaz.enigma.translation.mapping.EntryMapping;
10import cuchaz.enigma.translation.representation.entry.Entry;
11import cuchaz.enigma.utils.validation.PrintValidatable;
12import cuchaz.enigma.utils.validation.ValidationContext;
13
14public class MarkDeobfuscatedC2SPacket implements Packet<ServerPacketHandler> {
15 private Entry<?> entry;
16
17 MarkDeobfuscatedC2SPacket() {
18 }
19
20 public MarkDeobfuscatedC2SPacket(Entry<?> entry) {
21 this.entry = entry;
22 }
23
24 @Override
25 public void read(DataInput input) throws IOException {
26 this.entry = PacketHelper.readEntry(input);
27 }
28
29 @Override
30 public void write(DataOutput output) throws IOException {
31 PacketHelper.writeEntry(output, entry);
32 }
33
34 @Override
35 public void handle(ServerPacketHandler handler) {
36 ValidationContext vc = new ValidationContext();
37 vc.setActiveElement(PrintValidatable.INSTANCE);
38
39 boolean valid = handler.getServer().canModifyEntry(handler.getClient(), entry);
40
41 if (!valid) {
42 handler.getServer().sendCorrectMapping(handler.getClient(), entry, true);
43 return;
44 }
45
46 handler.getServer().getMappings().mapFromObf(vc, entry, new EntryMapping(handler.getServer().getMappings().deobfuscate(entry).getName()));
47
48 if (!vc.canProceed()) return;
49
50 handler.getServer().log(handler.getServer().getUsername(handler.getClient()) + " marked " + entry + " as deobfuscated");
51
52 int syncId = handler.getServer().lockEntry(handler.getClient(), entry);
53 handler.getServer().sendToAllExcept(handler.getClient(), new MarkDeobfuscatedS2CPacket(syncId, entry));
54 handler.getServer().sendMessage(Message.markDeobf(handler.getServer().getUsername(handler.getClient()), entry));
55 }
56}
diff --git a/enigma-server/src/main/java/cuchaz/enigma/network/packet/MarkDeobfuscatedS2CPacket.java b/enigma-server/src/main/java/cuchaz/enigma/network/packet/MarkDeobfuscatedS2CPacket.java
deleted file mode 100644
index 969d13c..0000000
--- a/enigma-server/src/main/java/cuchaz/enigma/network/packet/MarkDeobfuscatedS2CPacket.java
+++ /dev/null
@@ -1,47 +0,0 @@
1package cuchaz.enigma.network.packet;
2
3import java.io.DataInput;
4import java.io.DataOutput;
5import java.io.IOException;
6
7import cuchaz.enigma.analysis.EntryReference;
8import cuchaz.enigma.network.ClientPacketHandler;
9import cuchaz.enigma.translation.representation.entry.Entry;
10import cuchaz.enigma.utils.validation.PrintValidatable;
11import cuchaz.enigma.utils.validation.ValidationContext;
12
13public class MarkDeobfuscatedS2CPacket implements Packet<ClientPacketHandler> {
14 private int syncId;
15 private Entry<?> entry;
16
17 MarkDeobfuscatedS2CPacket() {
18 }
19
20 public MarkDeobfuscatedS2CPacket(int syncId, Entry<?> entry) {
21 this.syncId = syncId;
22 this.entry = entry;
23 }
24
25 @Override
26 public void read(DataInput input) throws IOException {
27 this.syncId = input.readUnsignedShort();
28 this.entry = PacketHelper.readEntry(input);
29 }
30
31 @Override
32 public void write(DataOutput output) throws IOException {
33 output.writeShort(syncId);
34 PacketHelper.writeEntry(output, entry);
35 }
36
37 @Override
38 public void handle(ClientPacketHandler controller) {
39 ValidationContext vc = new ValidationContext();
40 vc.setActiveElement(PrintValidatable.INSTANCE);
41
42 controller.markAsDeobfuscated(vc, new EntryReference<>(entry, entry.getName()));
43
44 if (!vc.canProceed()) return;
45 controller.sendPacket(new ConfirmChangeC2SPacket(syncId));
46 }
47}
diff --git a/enigma-server/src/main/java/cuchaz/enigma/network/packet/PacketHelper.java b/enigma-server/src/main/java/cuchaz/enigma/network/packet/PacketHelper.java
index 464606e..2649cdc 100644
--- a/enigma-server/src/main/java/cuchaz/enigma/network/packet/PacketHelper.java
+++ b/enigma-server/src/main/java/cuchaz/enigma/network/packet/PacketHelper.java
@@ -1,18 +1,17 @@
1package cuchaz.enigma.network.packet; 1package cuchaz.enigma.network.packet;
2 2
3import cuchaz.enigma.translation.representation.MethodDescriptor;
4import cuchaz.enigma.translation.representation.TypeDescriptor;
5import cuchaz.enigma.translation.representation.entry.ClassEntry;
6import cuchaz.enigma.translation.representation.entry.Entry;
7import cuchaz.enigma.translation.representation.entry.FieldEntry;
8import cuchaz.enigma.translation.representation.entry.LocalVariableEntry;
9import cuchaz.enigma.translation.representation.entry.MethodEntry;
10
11import java.io.DataInput; 3import java.io.DataInput;
12import java.io.DataOutput; 4import java.io.DataOutput;
13import java.io.IOException; 5import java.io.IOException;
14import java.nio.charset.StandardCharsets; 6import java.nio.charset.StandardCharsets;
15 7
8import cuchaz.enigma.translation.mapping.AccessModifier;
9import cuchaz.enigma.translation.mapping.EntryChange;
10import cuchaz.enigma.translation.representation.MethodDescriptor;
11import cuchaz.enigma.translation.representation.TypeDescriptor;
12import cuchaz.enigma.translation.representation.entry.*;
13import cuchaz.enigma.utils.TristateChange;
14
16public class PacketHelper { 15public class PacketHelper {
17 16
18 private static final int ENTRY_CLASS = 0, ENTRY_FIELD = 1, ENTRY_METHOD = 2, ENTRY_LOCAL_VAR = 3; 17 private static final int ENTRY_CLASS = 0, ENTRY_FIELD = 1, ENTRY_METHOD = 2, ENTRY_LOCAL_VAR = 3;
@@ -37,35 +36,40 @@ public class PacketHelper {
37 } 36 }
38 37
39 switch (type) { 38 switch (type) {
40 case ENTRY_CLASS: { 39 case ENTRY_CLASS: {
41 if (parent != null && !(parent instanceof ClassEntry)) { 40 if (parent != null && !(parent instanceof ClassEntry)) {
42 throw new IOException("Class requires class parent"); 41 throw new IOException("Class requires class parent");
42 }
43
44 return new ClassEntry((ClassEntry) parent, name, javadocs);
43 } 45 }
44 return new ClassEntry((ClassEntry) parent, name, javadocs); 46 case ENTRY_FIELD: {
45 } 47 if (!(parent instanceof ClassEntry parentClass)) {
46 case ENTRY_FIELD: { 48 throw new IOException("Field requires class parent");
47 if (!(parent instanceof ClassEntry)) { 49 }
48 throw new IOException("Field requires class parent"); 50
51 TypeDescriptor desc = new TypeDescriptor(readString(input));
52 return new FieldEntry(parentClass, name, desc, javadocs);
49 } 53 }
50 TypeDescriptor desc = new TypeDescriptor(readString(input)); 54 case ENTRY_METHOD: {
51 return new FieldEntry((ClassEntry) parent, name, desc, javadocs); 55 if (!(parent instanceof ClassEntry parentClass)) {
52 } 56 throw new IOException("Method requires class parent");
53 case ENTRY_METHOD: { 57 }
54 if (!(parent instanceof ClassEntry)) { 58
55 throw new IOException("Method requires class parent"); 59 MethodDescriptor desc = new MethodDescriptor(readString(input));
60 return new MethodEntry(parentClass, name, desc, javadocs);
56 } 61 }
57 MethodDescriptor desc = new MethodDescriptor(readString(input)); 62 case ENTRY_LOCAL_VAR: {
58 return new MethodEntry((ClassEntry) parent, name, desc, javadocs); 63 if (!(parent instanceof MethodEntry parentMethod)) {
59 } 64 throw new IOException("Local variable requires method parent");
60 case ENTRY_LOCAL_VAR: { 65 }
61 if (!(parent instanceof MethodEntry)) { 66
62 throw new IOException("Local variable requires method parent"); 67 int index = input.readUnsignedShort();
68 boolean parameter = input.readBoolean();
69 return new LocalVariableEntry(parentMethod, index, name, parameter, javadocs);
63 } 70 }
64 int index = input.readUnsignedShort(); 71 default:
65 boolean parameter = input.readBoolean(); 72 throw new IOException("Received unknown entry type " + type);
66 return new LocalVariableEntry((MethodEntry) parent, index, name, parameter, javadocs);
67 }
68 default: throw new IOException("Received unknown entry type " + type);
69 } 73 }
70 } 74 }
71 75
@@ -132,4 +136,64 @@ public class PacketHelper {
132 output.write(bytes); 136 output.write(bytes);
133 } 137 }
134 138
139 public static EntryChange<?> readEntryChange(DataInput input) throws IOException {
140 Entry<?> e = readEntry(input);
141 EntryChange<?> change = EntryChange.modify(e);
142
143 int flags = input.readUnsignedByte();
144 TristateChange.Type deobfNameT = TristateChange.Type.values()[flags & 0x3];
145 TristateChange.Type accessT = TristateChange.Type.values()[flags >> 2 & 0x3];
146 TristateChange.Type javadocT = TristateChange.Type.values()[flags >> 4 & 0x3];
147
148 switch (deobfNameT) {
149 case RESET:
150 change = change.clearDeobfName();
151 break;
152 case SET:
153 change = change.withDeobfName(readString(input));
154 break;
155 }
156
157 switch (accessT) {
158 case RESET:
159 change = change.clearAccess();
160 break;
161 case SET:
162 change = change.withAccess(AccessModifier.values()[flags >> 6 & 0x3]);
163 break;
164 }
165
166 switch (javadocT) {
167 case RESET:
168 change = change.clearJavadoc();
169 break;
170 case SET:
171 change = change.withJavadoc(readString(input));
172 break;
173 }
174
175 return change;
176 }
177
178 public static void writeEntryChange(DataOutput output, EntryChange<?> change) throws IOException {
179 writeEntry(output, change.getTarget());
180 int flags = change.getDeobfName().getType().ordinal() |
181 change.getAccess().getType().ordinal() << 2 |
182 change.getJavadoc().getType().ordinal() << 4;
183
184 if (change.getAccess().isSet()) {
185 flags |= change.getAccess().getNewValue().ordinal() << 6;
186 }
187
188 output.writeByte(flags);
189
190 if (change.getDeobfName().isSet()) {
191 writeString(output, change.getDeobfName().getNewValue());
192 }
193
194 if (change.getJavadoc().isSet()) {
195 writeString(output, change.getJavadoc().getNewValue());
196 }
197 }
198
135} 199}
diff --git a/enigma-server/src/main/java/cuchaz/enigma/network/packet/PacketRegistry.java b/enigma-server/src/main/java/cuchaz/enigma/network/packet/PacketRegistry.java
index 3b8af81..59999cc 100644
--- a/enigma-server/src/main/java/cuchaz/enigma/network/packet/PacketRegistry.java
+++ b/enigma-server/src/main/java/cuchaz/enigma/network/packet/PacketRegistry.java
@@ -1,12 +1,12 @@
1package cuchaz.enigma.network.packet; 1package cuchaz.enigma.network.packet;
2 2
3import cuchaz.enigma.network.ClientPacketHandler;
4import cuchaz.enigma.network.ServerPacketHandler;
5
6import java.util.HashMap; 3import java.util.HashMap;
7import java.util.Map; 4import java.util.Map;
8import java.util.function.Supplier; 5import java.util.function.Supplier;
9 6
7import cuchaz.enigma.network.ClientPacketHandler;
8import cuchaz.enigma.network.ServerPacketHandler;
9
10public class PacketRegistry { 10public class PacketRegistry {
11 11
12 private static final Map<Class<? extends Packet<ServerPacketHandler>>, Integer> c2sPacketIds = new HashMap<>(); 12 private static final Map<Class<? extends Packet<ServerPacketHandler>>, Integer> c2sPacketIds = new HashMap<>();
@@ -27,20 +27,14 @@ public class PacketRegistry {
27 static { 27 static {
28 registerC2S(0, LoginC2SPacket.class, LoginC2SPacket::new); 28 registerC2S(0, LoginC2SPacket.class, LoginC2SPacket::new);
29 registerC2S(1, ConfirmChangeC2SPacket.class, ConfirmChangeC2SPacket::new); 29 registerC2S(1, ConfirmChangeC2SPacket.class, ConfirmChangeC2SPacket::new);
30 registerC2S(2, RenameC2SPacket.class, RenameC2SPacket::new);
31 registerC2S(3, RemoveMappingC2SPacket.class, RemoveMappingC2SPacket::new);
32 registerC2S(4, ChangeDocsC2SPacket.class, ChangeDocsC2SPacket::new);
33 registerC2S(5, MarkDeobfuscatedC2SPacket.class, MarkDeobfuscatedC2SPacket::new);
34 registerC2S(6, MessageC2SPacket.class, MessageC2SPacket::new); 30 registerC2S(6, MessageC2SPacket.class, MessageC2SPacket::new);
31 registerC2S(7, EntryChangeC2SPacket.class, EntryChangeC2SPacket::new);
35 32
36 registerS2C(0, KickS2CPacket.class, KickS2CPacket::new); 33 registerS2C(0, KickS2CPacket.class, KickS2CPacket::new);
37 registerS2C(1, SyncMappingsS2CPacket.class, SyncMappingsS2CPacket::new); 34 registerS2C(1, SyncMappingsS2CPacket.class, SyncMappingsS2CPacket::new);
38 registerS2C(2, RenameS2CPacket.class, RenameS2CPacket::new);
39 registerS2C(3, RemoveMappingS2CPacket.class, RemoveMappingS2CPacket::new);
40 registerS2C(4, ChangeDocsS2CPacket.class, ChangeDocsS2CPacket::new);
41 registerS2C(5, MarkDeobfuscatedS2CPacket.class, MarkDeobfuscatedS2CPacket::new);
42 registerS2C(6, MessageS2CPacket.class, MessageS2CPacket::new); 35 registerS2C(6, MessageS2CPacket.class, MessageS2CPacket::new);
43 registerS2C(7, UserListS2CPacket.class, UserListS2CPacket::new); 36 registerS2C(7, UserListS2CPacket.class, UserListS2CPacket::new);
37 registerS2C(8, EntryChangeS2CPacket.class, EntryChangeS2CPacket::new);
44 } 38 }
45 39
46 public static int getC2SId(Packet<ServerPacketHandler> packet) { 40 public static int getC2SId(Packet<ServerPacketHandler> packet) {
diff --git a/enigma-server/src/main/java/cuchaz/enigma/network/packet/RemoveMappingC2SPacket.java b/enigma-server/src/main/java/cuchaz/enigma/network/packet/RemoveMappingC2SPacket.java
deleted file mode 100644
index 298e674..0000000
--- a/enigma-server/src/main/java/cuchaz/enigma/network/packet/RemoveMappingC2SPacket.java
+++ /dev/null
@@ -1,56 +0,0 @@
1package cuchaz.enigma.network.packet;
2
3import java.io.DataInput;
4import java.io.DataOutput;
5import java.io.IOException;
6
7import cuchaz.enigma.network.Message;
8import cuchaz.enigma.network.ServerPacketHandler;
9import cuchaz.enigma.translation.representation.entry.Entry;
10import cuchaz.enigma.utils.validation.PrintValidatable;
11import cuchaz.enigma.utils.validation.ValidationContext;
12
13public class RemoveMappingC2SPacket implements Packet<ServerPacketHandler> {
14 private Entry<?> entry;
15
16 RemoveMappingC2SPacket() {
17 }
18
19 public RemoveMappingC2SPacket(Entry<?> entry) {
20 this.entry = entry;
21 }
22
23 @Override
24 public void read(DataInput input) throws IOException {
25 this.entry = PacketHelper.readEntry(input);
26 }
27
28 @Override
29 public void write(DataOutput output) throws IOException {
30 PacketHelper.writeEntry(output, entry);
31 }
32
33 @Override
34 public void handle(ServerPacketHandler handler) {
35 ValidationContext vc = new ValidationContext();
36 vc.setActiveElement(PrintValidatable.INSTANCE);
37
38 boolean valid = handler.getServer().canModifyEntry(handler.getClient(), entry);
39
40 if (valid) {
41 handler.getServer().getMappings().removeByObf(vc, entry);
42 valid = vc.canProceed();
43 }
44
45 if (!valid) {
46 handler.getServer().sendCorrectMapping(handler.getClient(), entry, true);
47 return;
48 }
49
50 handler.getServer().log(handler.getServer().getUsername(handler.getClient()) + " removed the mapping for " + entry);
51
52 int syncId = handler.getServer().lockEntry(handler.getClient(), entry);
53 handler.getServer().sendToAllExcept(handler.getClient(), new RemoveMappingS2CPacket(syncId, entry));
54 handler.getServer().sendMessage(Message.removeMapping(handler.getServer().getUsername(handler.getClient()), entry));
55 }
56}
diff --git a/enigma-server/src/main/java/cuchaz/enigma/network/packet/RemoveMappingS2CPacket.java b/enigma-server/src/main/java/cuchaz/enigma/network/packet/RemoveMappingS2CPacket.java
deleted file mode 100644
index e336c7b..0000000
--- a/enigma-server/src/main/java/cuchaz/enigma/network/packet/RemoveMappingS2CPacket.java
+++ /dev/null
@@ -1,47 +0,0 @@
1package cuchaz.enigma.network.packet;
2
3import java.io.DataInput;
4import java.io.DataOutput;
5import java.io.IOException;
6
7import cuchaz.enigma.analysis.EntryReference;
8import cuchaz.enigma.network.ClientPacketHandler;
9import cuchaz.enigma.translation.representation.entry.Entry;
10import cuchaz.enigma.utils.validation.PrintValidatable;
11import cuchaz.enigma.utils.validation.ValidationContext;
12
13public class RemoveMappingS2CPacket implements Packet<ClientPacketHandler> {
14 private int syncId;
15 private Entry<?> entry;
16
17 RemoveMappingS2CPacket() {
18 }
19
20 public RemoveMappingS2CPacket(int syncId, Entry<?> entry) {
21 this.syncId = syncId;
22 this.entry = entry;
23 }
24
25 @Override
26 public void read(DataInput input) throws IOException {
27 this.syncId = input.readUnsignedShort();
28 this.entry = PacketHelper.readEntry(input);
29 }
30
31 @Override
32 public void write(DataOutput output) throws IOException {
33 output.writeShort(syncId);
34 PacketHelper.writeEntry(output, entry);
35 }
36
37 @Override
38 public void handle(ClientPacketHandler controller) {
39 ValidationContext vc = new ValidationContext();
40 vc.setActiveElement(PrintValidatable.INSTANCE);
41
42 controller.removeMapping(vc, new EntryReference<>(entry, entry.getName()));
43
44 if (!vc.canProceed()) return;
45 controller.sendPacket(new ConfirmChangeC2SPacket(syncId));
46 }
47}
diff --git a/enigma-server/src/main/java/cuchaz/enigma/network/packet/RenameC2SPacket.java b/enigma-server/src/main/java/cuchaz/enigma/network/packet/RenameC2SPacket.java
deleted file mode 100644
index 694d432..0000000
--- a/enigma-server/src/main/java/cuchaz/enigma/network/packet/RenameC2SPacket.java
+++ /dev/null
@@ -1,66 +0,0 @@
1package cuchaz.enigma.network.packet;
2
3import java.io.DataInput;
4import java.io.DataOutput;
5import java.io.IOException;
6
7import cuchaz.enigma.network.Message;
8import cuchaz.enigma.network.ServerPacketHandler;
9import cuchaz.enigma.translation.mapping.EntryMapping;
10import cuchaz.enigma.translation.representation.entry.Entry;
11import cuchaz.enigma.utils.validation.PrintValidatable;
12import cuchaz.enigma.utils.validation.ValidationContext;
13
14public class RenameC2SPacket implements Packet<ServerPacketHandler> {
15 private Entry<?> entry;
16 private String newName;
17 private boolean refreshClassTree;
18
19 RenameC2SPacket() {
20 }
21
22 public RenameC2SPacket(Entry<?> entry, String newName, boolean refreshClassTree) {
23 this.entry = entry;
24 this.newName = newName;
25 this.refreshClassTree = refreshClassTree;
26 }
27
28 @Override
29 public void read(DataInput input) throws IOException {
30 this.entry = PacketHelper.readEntry(input);
31 this.newName = PacketHelper.readString(input);
32 this.refreshClassTree = input.readBoolean();
33 }
34
35 @Override
36 public void write(DataOutput output) throws IOException {
37 PacketHelper.writeEntry(output, entry);
38 PacketHelper.writeString(output, newName);
39 output.writeBoolean(refreshClassTree);
40 }
41
42 @Override
43 public void handle(ServerPacketHandler handler) {
44 ValidationContext vc = new ValidationContext();
45 vc.setActiveElement(PrintValidatable.INSTANCE);
46
47 boolean valid = handler.getServer().canModifyEntry(handler.getClient(), entry);
48
49 if (valid) {
50 EntryMapping previous = handler.getServer().getMappings().getDeobfMapping(entry);
51 handler.getServer().getMappings().mapFromObf(vc, entry, previous != null ? previous.withName(newName) : new EntryMapping(newName));
52 valid = vc.canProceed();
53 }
54
55 if (!valid) {
56 handler.getServer().sendCorrectMapping(handler.getClient(), entry, refreshClassTree);
57 return;
58 }
59
60 handler.getServer().log(handler.getServer().getUsername(handler.getClient()) + " renamed " + entry + " to " + newName);
61
62 int syncId = handler.getServer().lockEntry(handler.getClient(), entry);
63 handler.getServer().sendToAllExcept(handler.getClient(), new RenameS2CPacket(syncId, entry, newName, refreshClassTree));
64 handler.getServer().sendMessage(Message.rename(handler.getServer().getUsername(handler.getClient()), entry, newName));
65 }
66}
diff --git a/enigma-server/src/main/java/cuchaz/enigma/network/packet/RenameS2CPacket.java b/enigma-server/src/main/java/cuchaz/enigma/network/packet/RenameS2CPacket.java
deleted file mode 100644
index fdf0654..0000000
--- a/enigma-server/src/main/java/cuchaz/enigma/network/packet/RenameS2CPacket.java
+++ /dev/null
@@ -1,55 +0,0 @@
1package cuchaz.enigma.network.packet;
2
3import java.io.DataInput;
4import java.io.DataOutput;
5import java.io.IOException;
6
7import cuchaz.enigma.analysis.EntryReference;
8import cuchaz.enigma.network.ClientPacketHandler;
9import cuchaz.enigma.translation.representation.entry.Entry;
10import cuchaz.enigma.utils.validation.PrintValidatable;
11import cuchaz.enigma.utils.validation.ValidationContext;
12
13public class RenameS2CPacket implements Packet<ClientPacketHandler> {
14 private int syncId;
15 private Entry<?> entry;
16 private String newName;
17 private boolean refreshClassTree;
18
19 RenameS2CPacket() {
20 }
21
22 public RenameS2CPacket(int syncId, Entry<?> entry, String newName, boolean refreshClassTree) {
23 this.syncId = syncId;
24 this.entry = entry;
25 this.newName = newName;
26 this.refreshClassTree = refreshClassTree;
27 }
28
29 @Override
30 public void read(DataInput input) throws IOException {
31 this.syncId = input.readUnsignedShort();
32 this.entry = PacketHelper.readEntry(input);
33 this.newName = PacketHelper.readString(input);
34 this.refreshClassTree = input.readBoolean();
35 }
36
37 @Override
38 public void write(DataOutput output) throws IOException {
39 output.writeShort(syncId);
40 PacketHelper.writeEntry(output, entry);
41 PacketHelper.writeString(output, newName);
42 output.writeBoolean(refreshClassTree);
43 }
44
45 @Override
46 public void handle(ClientPacketHandler controller) {
47 ValidationContext vc = new ValidationContext();
48 vc.setActiveElement(PrintValidatable.INSTANCE);
49
50 controller.rename(vc, new EntryReference<>(entry, entry.getName()), newName, refreshClassTree);
51
52 if (!vc.canProceed()) return;
53 controller.sendPacket(new ConfirmChangeC2SPacket(syncId));
54 }
55}
diff --git a/enigma-server/src/main/java/cuchaz/enigma/network/packet/SyncMappingsS2CPacket.java b/enigma-server/src/main/java/cuchaz/enigma/network/packet/SyncMappingsS2CPacket.java
index 92a7874..6d9c0bc 100644
--- a/enigma-server/src/main/java/cuchaz/enigma/network/packet/SyncMappingsS2CPacket.java
+++ b/enigma-server/src/main/java/cuchaz/enigma/network/packet/SyncMappingsS2CPacket.java
@@ -1,19 +1,19 @@
1package cuchaz.enigma.network.packet; 1package cuchaz.enigma.network.packet;
2 2
3import cuchaz.enigma.translation.mapping.EntryMapping;
4import cuchaz.enigma.translation.mapping.tree.EntryTree;
5import cuchaz.enigma.translation.mapping.tree.EntryTreeNode;
6import cuchaz.enigma.translation.mapping.tree.HashEntryTree;
7import cuchaz.enigma.network.ClientPacketHandler;
8import cuchaz.enigma.network.EnigmaServer;
9import cuchaz.enigma.translation.representation.entry.Entry;
10
11import java.io.DataInput; 3import java.io.DataInput;
12import java.io.DataOutput; 4import java.io.DataOutput;
13import java.io.IOException; 5import java.io.IOException;
14import java.util.Collection; 6import java.util.Collection;
15import java.util.List; 7import java.util.List;
16 8
9import cuchaz.enigma.network.ClientPacketHandler;
10import cuchaz.enigma.network.EnigmaServer;
11import cuchaz.enigma.translation.mapping.EntryMapping;
12import cuchaz.enigma.translation.mapping.tree.EntryTree;
13import cuchaz.enigma.translation.mapping.tree.EntryTreeNode;
14import cuchaz.enigma.translation.mapping.tree.HashEntryTree;
15import cuchaz.enigma.translation.representation.entry.Entry;
16
17public class SyncMappingsS2CPacket implements Packet<ClientPacketHandler> { 17public class SyncMappingsS2CPacket implements Packet<ClientPacketHandler> {
18 private EntryTree<EntryMapping> mappings; 18 private EntryTree<EntryMapping> mappings;
19 19
@@ -35,16 +35,9 @@ public class SyncMappingsS2CPacket implements Packet<ClientPacketHandler> {
35 35
36 private void readEntryTreeNode(DataInput input, Entry<?> parent) throws IOException { 36 private void readEntryTreeNode(DataInput input, Entry<?> parent) throws IOException {
37 Entry<?> entry = PacketHelper.readEntry(input, parent, false); 37 Entry<?> entry = PacketHelper.readEntry(input, parent, false);
38 EntryMapping mapping = null; 38 String name = PacketHelper.readString(input);
39 if (input.readBoolean()) { 39 String javadoc = PacketHelper.readString(input);
40 String name = input.readUTF(); 40 EntryMapping mapping = new EntryMapping(!name.isEmpty() ? name : null, !javadoc.isEmpty() ? javadoc : null);
41 if (input.readBoolean()) {
42 String javadoc = input.readUTF();
43 mapping = new EntryMapping(name, javadoc);
44 } else {
45 mapping = new EntryMapping(name);
46 }
47 }
48 mappings.insert(entry, mapping); 41 mappings.insert(entry, mapping);
49 int size = input.readUnsignedShort(); 42 int size = input.readUnsignedShort();
50 for (int i = 0; i < size; i++) { 43 for (int i = 0; i < size; i++) {
@@ -64,14 +57,10 @@ public class SyncMappingsS2CPacket implements Packet<ClientPacketHandler> {
64 private static void writeEntryTreeNode(DataOutput output, EntryTreeNode<EntryMapping> node) throws IOException { 57 private static void writeEntryTreeNode(DataOutput output, EntryTreeNode<EntryMapping> node) throws IOException {
65 PacketHelper.writeEntry(output, node.getEntry(), false); 58 PacketHelper.writeEntry(output, node.getEntry(), false);
66 EntryMapping value = node.getValue(); 59 EntryMapping value = node.getValue();
67 output.writeBoolean(value != null); 60 if (value == null) value = EntryMapping.DEFAULT;
68 if (value != null) { 61
69 PacketHelper.writeString(output, value.getTargetName()); 62 PacketHelper.writeString(output, value.targetName() != null ? value.targetName() : "");
70 output.writeBoolean(value.getJavadoc() != null); 63 PacketHelper.writeString(output, value.javadoc() != null ? value.javadoc() : "");
71 if (value.getJavadoc() != null) {
72 PacketHelper.writeString(output, value.getJavadoc());
73 }
74 }
75 Collection<? extends EntryTreeNode<EntryMapping>> children = node.getChildNodes(); 64 Collection<? extends EntryTreeNode<EntryMapping>> children = node.getChildNodes();
76 output.writeShort(children.size()); 65 output.writeShort(children.size());
77 for (EntryTreeNode<EntryMapping> child : children) { 66 for (EntryTreeNode<EntryMapping> child : children) {