summaryrefslogtreecommitdiff
path: root/enigma-server
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
parentAdd --single-class-tree argument that puts all classes into deobf panel & hid... (diff)
downloadenigma-8efb62490ec153246d467a1a72c513781db887bf.tar.gz
enigma-8efb62490ec153246d467a1a72c513781db887bf.tar.xz
enigma-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')
-rw-r--r--enigma-server/docs/protocol.md164
-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
16 files changed, 295 insertions, 627 deletions
diff --git a/enigma-server/docs/protocol.md b/enigma-server/docs/protocol.md
index c14ecb81..83ef4c01 100644
--- a/enigma-server/docs/protocol.md
+++ b/enigma-server/docs/protocol.md
@@ -75,21 +75,15 @@ struct Packet {
75The IDs for client-to-server packets are as follows: 75The IDs for client-to-server packets are as follows:
76- 0: `Login` 76- 0: `Login`
77- 1: `ConfirmChange` 77- 1: `ConfirmChange`
78- 2: `Rename`
79- 3: `RemoveMapping`
80- 4: `ChangeDocs`
81- 5: `MarkDeobfuscated`
82- 6: `Message` 78- 6: `Message`
79- 7: `EntryChange`
83 80
84The IDs for server-to-client packets are as follows: 81The IDs for server-to-client packets are as follows:
85- 0: `Kick` 82- 0: `Kick`
86- 1: `SyncMappings` 83- 1: `SyncMappings`
87- 2: `Rename`
88- 3: `RemoveMapping`
89- 4: `ChangeDocs`
90- 5: `MarkDeobfuscated`
91- 6: `Message` 84- 6: `Message`
92- 7: `UserList` 85- 7: `UserList`
86- 8: `EntryChange`
93 87
94### The utf struct 88### The utf struct
95```c 89```c
@@ -196,6 +190,45 @@ struct Message {
196- `entry`: The entry that was modified. 190- `entry`: The entry that was modified.
197- `new_name`: The new name for the entry. 191- `new_name`: The new name for the entry.
198 192
193### The entry_change struct
194```c
195typedef enum tristate_change {
196 TRISTATE_CHANGE_UNCHANGED = 0,
197 TRISTATE_CHANGE_RESET = 1,
198 TRISTATE_CHANGE_SET = 2
199} tristate_change_t;
200
201typedef enum access_modifier {
202 ACCESS_MODIFIER_UNCHANGED = 0,
203 ACCESS_MODIFIER_PUBLIC = 1,
204 ACCESS_MODIFIER_PROTECTED = 2,
205 ACCESS_MODIFIER_PRIVATE = 3
206} access_modifier_t;
207
208// Contains 4 packed values:
209// bitmask type
210// 00000011 tristate_change_t deobf_name_change;
211// 00001100 tristate_change_t access_change;
212// 00110000 tristate_change_t javadoc_change;
213// 11000000 access_modifier_t access_modifiers;
214typedef uint8_t entry_change_flags;
215
216struct entry_change {
217 Entry entry;
218 entry_change_flags flags;
219 if <deobf_name_change == TRISTATE_CHANGE_SET> {
220 utf deobf_name;
221 }
222 if <javadoc_change == TRISTATE_CHANGE_SET> {
223 utf javadoc;
224 }
225}
226```
227- `entry`: The entry this change gets applied to.
228- `flags`: See definition of `entry_change_flags`.
229- `deobf_name`: The new deobfuscated name, if deobf_name_change == TRISTATE_CHANGE_SET
230- `javadoc`: The new javadoc, if javadoc_change == TRISTATE_CHANGE_SET
231- `access_modifiers`: The new access modifier, if access_change == TRISTATE_CHANGE_SET (otherwise 0)
199 232
200### Login (client-to-server) 233### Login (client-to-server)
201```c 234```c
@@ -223,44 +256,6 @@ struct ConfirmChangeC2SPacket {
223``` 256```
224- `sync_id`: the sync ID to confirm. 257- `sync_id`: the sync ID to confirm.
225 258
226### Rename (client-to-server)
227```c
228struct RenameC2SPacket {
229 Entry obf_entry;
230 utf new_name;
231 boolean refresh_class_tree;
232}
233```
234- `obf_entry`: the obfuscated name and descriptor of the entry to rename.
235- `new_name`: what to rename the entry to.
236- `refresh_class_tree`: whether the class tree on the sidebar of Enigma needs refreshing as a result of this change.
237
238### RemoveMapping (client-to-server)
239```c
240struct RemoveMappingC2SPacket {
241 Entry obf_entry;
242}
243```
244- `obf_entry`: the obfuscated name and descriptor of the entry to remove the mapping for.
245
246### ChangeDocs (client-to-server)
247```c
248struct ChangeDocsC2SPacket {
249 Entry obf_entry;
250 utf new_docs;
251}
252```
253- `obf_entry`: the obfuscated name and descriptor of the entry to change the documentation for.
254- `new_docs`: the new documentation for this entry, or an empty string to remove the documentation.
255
256### MarkDeobfuscated (client-to-server)
257```c
258struct MarkDeobfuscatedC2SPacket {
259 Entry obf_entry;
260}
261```
262- `obf_entry`: the obfuscated name and descriptor of the entry to mark as deobfuscated.
263
264### Message (client-to-server) 259### Message (client-to-server)
265```c 260```c
266struct MessageC2SPacket { 261struct MessageC2SPacket {
@@ -269,6 +264,14 @@ struct MessageC2SPacket {
269``` 264```
270- `message`: The text message the user sent. 265- `message`: The text message the user sent.
271 266
267### EntryChange (client-to-server)
268```c
269struct EntryChangeC2SPacket {
270 entry_change change;
271}
272```
273- `change`: The change to apply.
274
272### Kick (server-to-client) 275### Kick (server-to-client)
273```c 276```c
274struct KickS2CPacket { 277struct KickS2CPacket {
@@ -286,13 +289,8 @@ struct SyncMappingsS2CPacket {
286struct MappingNode { 289struct MappingNode {
287 NoParentEntry obf_entry; 290 NoParentEntry obf_entry;
288 boolean is_named; 291 boolean is_named;
289 if<is_named> { 292 utf name;
290 utf name; 293 utf javadoc;
291 boolean has_javadoc;
292 if<has_javadoc> {
293 utf javadoc;
294 }
295 }
296 unsigned short children_count; 294 unsigned short children_count;
297 MappingNode children[children_count]; 295 MappingNode children[children_count];
298} 296}
@@ -300,56 +298,10 @@ typedef { Entry but without the has_parent or parent fields } NoParentEntry;
300``` 298```
301- `roots`: The root mapping nodes, containing all the entries without parents. 299- `roots`: The root mapping nodes, containing all the entries without parents.
302- `obf_entry`: The value of a node, containing the obfuscated name and descriptor of the entry. 300- `obf_entry`: The value of a node, containing the obfuscated name and descriptor of the entry.
303- `name`: The deobfuscated name of the entry, if it has a mapping. 301- `name`: The deobfuscated name of the entry, if it exists, otherwise the empty string.
304- `javadoc`: The documentation for the entry, if it is named and has documentation. 302- `javadoc`: The documentation for the entry, if it exists, otherwise the empty string.
305- `children`: The children of this node 303- `children`: The children of this node
306 304
307### Rename (server-to-client)
308```c
309struct RenameS2CPacket {
310 unsigned short sync_id;
311 Entry obf_entry;
312 utf new_name;
313 boolean refresh_class_tree;
314}
315```
316- `sync_id`: the sync ID of the change for locking purposes.
317- `obf_entry`: the obfuscated name and descriptor of the entry to rename.
318- `new_name`: what to rename the entry to.
319- `refresh_class_tree`: whether the class tree on the sidebar of Enigma needs refreshing as a result of this change.
320
321### RemoveMapping (server-to-client)
322```c
323struct RemoveMappingS2CPacket {
324 unsigned short sync_id;
325 Entry obf_entry;
326}
327```
328- `sync_id`: the sync ID of the change for locking purposes.
329- `obf_entry`: the obfuscated name and descriptor of the entry to remove the mapping for.
330
331### ChangeDocs (server-to-client)
332```c
333struct ChangeDocsS2CPacket {
334 unsigned short sync_id;
335 Entry obf_entry;
336 utf new_docs;
337}
338```
339- `sync_id`: the sync ID of the change for locking purposes.
340- `obf_entry`: the obfuscated name and descriptor of the entry to change the documentation for.
341- `new_docs`: the new documentation for this entry, or an empty string to remove the documentation.
342
343### MarkDeobfuscated (server-to-client)
344```c
345struct MarkDeobfuscatedS2CPacket {
346 unsigned short sync_id;
347 Entry obf_entry;
348}
349```
350- `sync_id`: the sync ID of the change for locking purposes.
351- `obf_entry`: the obfuscated name and descriptor of the entry to mark as deobfuscated.
352
353### Message (server-to-client) 305### Message (server-to-client)
354```c 306```c
355struct MessageS2CPacket { 307struct MessageS2CPacket {
@@ -364,3 +316,13 @@ struct UserListS2CPacket {
364 utf user[len]; 316 utf user[len];
365} 317}
366``` 318```
319
320### EntryChange (server-to-client)
321```c
322struct EntryChangeS2CPacket {
323 uint16_t sync_id;
324 entry_change change;
325}
326```
327- `sync_id`: The sync ID of the change for locking purposes.
328- `change`: The change to apply. \ No newline at end of file
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 1b0191be..a651fe84 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 75981c3b..1ce359b6 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 f3e07c2d..00000000
--- 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 78fa4fa9..00000000
--- 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 00000000..b97877c6
--- /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 00000000..a237b916
--- /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 732c7448..00000000
--- 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 969d13c5..00000000
--- 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 464606e0..2649cdc4 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 3b8af81c..59999ccc 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 298e674f..00000000
--- 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 e336c7b2..00000000
--- 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 694d4321..00000000
--- 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 fdf06540..00000000
--- 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 92a78748..6d9c0bcb 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) {