diff options
| author | 2021-07-08 16:30:39 +0200 | |
|---|---|---|
| committer | 2021-07-08 16:30:39 +0200 | |
| commit | 8efb62490ec153246d467a1a72c513781db887bf (patch) | |
| tree | 0f2eedd97d9c0d95544ff7d24f2b479cf10271fe /enigma-server | |
| parent | Add --single-class-tree argument that puts all classes into deobf panel & hid... (diff) | |
| download | enigma-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')
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 { | |||
| 75 | The IDs for client-to-server packets are as follows: | 75 | The 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 | ||
| 84 | The IDs for server-to-client packets are as follows: | 81 | The 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 | ||
| 195 | typedef enum tristate_change { | ||
| 196 | TRISTATE_CHANGE_UNCHANGED = 0, | ||
| 197 | TRISTATE_CHANGE_RESET = 1, | ||
| 198 | TRISTATE_CHANGE_SET = 2 | ||
| 199 | } tristate_change_t; | ||
| 200 | |||
| 201 | typedef 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; | ||
| 214 | typedef uint8_t entry_change_flags; | ||
| 215 | |||
| 216 | struct 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 | ||
| 228 | struct 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 | ||
| 240 | struct 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 | ||
| 248 | struct 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 | ||
| 258 | struct 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 |
| 266 | struct MessageC2SPacket { | 261 | struct 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 | ||
| 269 | struct 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 |
| 274 | struct KickS2CPacket { | 277 | struct KickS2CPacket { |
| @@ -286,13 +289,8 @@ struct SyncMappingsS2CPacket { | |||
| 286 | struct MappingNode { | 289 | struct 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 | ||
| 309 | struct 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 | ||
| 323 | struct 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 | ||
| 333 | struct 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 | ||
| 345 | struct 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 |
| 355 | struct MessageS2CPacket { | 307 | struct 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 | ||
| 322 | struct 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 @@ | |||
| 1 | package cuchaz.enigma.network; | 1 | package cuchaz.enigma.network; |
| 2 | 2 | ||
| 3 | import cuchaz.enigma.analysis.EntryReference; | 3 | import cuchaz.enigma.translation.mapping.EntryChange; |
| 4 | import cuchaz.enigma.translation.mapping.EntryMapping; | 4 | import cuchaz.enigma.translation.mapping.EntryMapping; |
| 5 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | 5 | import cuchaz.enigma.translation.mapping.tree.EntryTree; |
| 6 | import cuchaz.enigma.network.packet.Packet; | 6 | import cuchaz.enigma.network.packet.Packet; |
| 7 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 8 | import cuchaz.enigma.utils.validation.ValidationContext; | ||
| 9 | 7 | ||
| 10 | import java.util.List; | 8 | import java.util.List; |
| 11 | 9 | ||
| 12 | public interface ClientPacketHandler { | 10 | public 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.*; | |||
| 8 | import java.util.concurrent.CopyOnWriteArrayList; | 8 | import java.util.concurrent.CopyOnWriteArrayList; |
| 9 | 9 | ||
| 10 | import cuchaz.enigma.network.packet.*; | 10 | import cuchaz.enigma.network.packet.*; |
| 11 | import cuchaz.enigma.translation.mapping.EntryChange; | ||
| 11 | import cuchaz.enigma.translation.mapping.EntryMapping; | 12 | import cuchaz.enigma.translation.mapping.EntryMapping; |
| 12 | import cuchaz.enigma.translation.mapping.EntryRemapper; | 13 | import cuchaz.enigma.translation.mapping.EntryRemapper; |
| 13 | import cuchaz.enigma.translation.representation.entry.Entry; | 14 | import 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 @@ | |||
| 1 | package cuchaz.enigma.network.packet; | ||
| 2 | |||
| 3 | import java.io.DataInput; | ||
| 4 | import java.io.DataOutput; | ||
| 5 | import java.io.IOException; | ||
| 6 | |||
| 7 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 8 | import cuchaz.enigma.network.EnigmaServer; | ||
| 9 | import cuchaz.enigma.network.Message; | ||
| 10 | import cuchaz.enigma.network.ServerPacketHandler; | ||
| 11 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 12 | import cuchaz.enigma.utils.validation.PrintValidatable; | ||
| 13 | import cuchaz.enigma.utils.validation.ValidationContext; | ||
| 14 | |||
| 15 | public 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 @@ | |||
| 1 | package cuchaz.enigma.network.packet; | ||
| 2 | |||
| 3 | import java.io.DataInput; | ||
| 4 | import java.io.DataOutput; | ||
| 5 | import java.io.IOException; | ||
| 6 | |||
| 7 | import cuchaz.enigma.analysis.EntryReference; | ||
| 8 | import cuchaz.enigma.network.ClientPacketHandler; | ||
| 9 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 10 | import cuchaz.enigma.utils.validation.PrintValidatable; | ||
| 11 | import cuchaz.enigma.utils.validation.ValidationContext; | ||
| 12 | |||
| 13 | public 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 @@ | |||
| 1 | package cuchaz.enigma.network.packet; | ||
| 2 | |||
| 3 | import java.io.DataInput; | ||
| 4 | import java.io.DataOutput; | ||
| 5 | import java.io.IOException; | ||
| 6 | |||
| 7 | import cuchaz.enigma.network.Message; | ||
| 8 | import cuchaz.enigma.network.ServerPacketHandler; | ||
| 9 | import cuchaz.enigma.translation.mapping.EntryChange; | ||
| 10 | import cuchaz.enigma.translation.mapping.EntryUtil; | ||
| 11 | import cuchaz.enigma.utils.validation.PrintValidatable; | ||
| 12 | import cuchaz.enigma.utils.validation.ValidationContext; | ||
| 13 | |||
| 14 | public 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 @@ | |||
| 1 | package cuchaz.enigma.network.packet; | ||
| 2 | |||
| 3 | import java.io.DataInput; | ||
| 4 | import java.io.DataOutput; | ||
| 5 | import java.io.IOException; | ||
| 6 | |||
| 7 | import cuchaz.enigma.network.ClientPacketHandler; | ||
| 8 | import cuchaz.enigma.translation.mapping.EntryChange; | ||
| 9 | |||
| 10 | public 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 @@ | |||
| 1 | package cuchaz.enigma.network.packet; | ||
| 2 | |||
| 3 | import java.io.DataInput; | ||
| 4 | import java.io.DataOutput; | ||
| 5 | import java.io.IOException; | ||
| 6 | |||
| 7 | import cuchaz.enigma.network.Message; | ||
| 8 | import cuchaz.enigma.network.ServerPacketHandler; | ||
| 9 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 10 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 11 | import cuchaz.enigma.utils.validation.PrintValidatable; | ||
| 12 | import cuchaz.enigma.utils.validation.ValidationContext; | ||
| 13 | |||
| 14 | public 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 @@ | |||
| 1 | package cuchaz.enigma.network.packet; | ||
| 2 | |||
| 3 | import java.io.DataInput; | ||
| 4 | import java.io.DataOutput; | ||
| 5 | import java.io.IOException; | ||
| 6 | |||
| 7 | import cuchaz.enigma.analysis.EntryReference; | ||
| 8 | import cuchaz.enigma.network.ClientPacketHandler; | ||
| 9 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 10 | import cuchaz.enigma.utils.validation.PrintValidatable; | ||
| 11 | import cuchaz.enigma.utils.validation.ValidationContext; | ||
| 12 | |||
| 13 | public 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 @@ | |||
| 1 | package cuchaz.enigma.network.packet; | 1 | package cuchaz.enigma.network.packet; |
| 2 | 2 | ||
| 3 | import cuchaz.enigma.translation.representation.MethodDescriptor; | ||
| 4 | import cuchaz.enigma.translation.representation.TypeDescriptor; | ||
| 5 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | ||
| 6 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 7 | import cuchaz.enigma.translation.representation.entry.FieldEntry; | ||
| 8 | import cuchaz.enigma.translation.representation.entry.LocalVariableEntry; | ||
| 9 | import cuchaz.enigma.translation.representation.entry.MethodEntry; | ||
| 10 | |||
| 11 | import java.io.DataInput; | 3 | import java.io.DataInput; |
| 12 | import java.io.DataOutput; | 4 | import java.io.DataOutput; |
| 13 | import java.io.IOException; | 5 | import java.io.IOException; |
| 14 | import java.nio.charset.StandardCharsets; | 6 | import java.nio.charset.StandardCharsets; |
| 15 | 7 | ||
| 8 | import cuchaz.enigma.translation.mapping.AccessModifier; | ||
| 9 | import cuchaz.enigma.translation.mapping.EntryChange; | ||
| 10 | import cuchaz.enigma.translation.representation.MethodDescriptor; | ||
| 11 | import cuchaz.enigma.translation.representation.TypeDescriptor; | ||
| 12 | import cuchaz.enigma.translation.representation.entry.*; | ||
| 13 | import cuchaz.enigma.utils.TristateChange; | ||
| 14 | |||
| 16 | public class PacketHelper { | 15 | public 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 @@ | |||
| 1 | package cuchaz.enigma.network.packet; | 1 | package cuchaz.enigma.network.packet; |
| 2 | 2 | ||
| 3 | import cuchaz.enigma.network.ClientPacketHandler; | ||
| 4 | import cuchaz.enigma.network.ServerPacketHandler; | ||
| 5 | |||
| 6 | import java.util.HashMap; | 3 | import java.util.HashMap; |
| 7 | import java.util.Map; | 4 | import java.util.Map; |
| 8 | import java.util.function.Supplier; | 5 | import java.util.function.Supplier; |
| 9 | 6 | ||
| 7 | import cuchaz.enigma.network.ClientPacketHandler; | ||
| 8 | import cuchaz.enigma.network.ServerPacketHandler; | ||
| 9 | |||
| 10 | public class PacketRegistry { | 10 | public 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 @@ | |||
| 1 | package cuchaz.enigma.network.packet; | ||
| 2 | |||
| 3 | import java.io.DataInput; | ||
| 4 | import java.io.DataOutput; | ||
| 5 | import java.io.IOException; | ||
| 6 | |||
| 7 | import cuchaz.enigma.network.Message; | ||
| 8 | import cuchaz.enigma.network.ServerPacketHandler; | ||
| 9 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 10 | import cuchaz.enigma.utils.validation.PrintValidatable; | ||
| 11 | import cuchaz.enigma.utils.validation.ValidationContext; | ||
| 12 | |||
| 13 | public 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 @@ | |||
| 1 | package cuchaz.enigma.network.packet; | ||
| 2 | |||
| 3 | import java.io.DataInput; | ||
| 4 | import java.io.DataOutput; | ||
| 5 | import java.io.IOException; | ||
| 6 | |||
| 7 | import cuchaz.enigma.analysis.EntryReference; | ||
| 8 | import cuchaz.enigma.network.ClientPacketHandler; | ||
| 9 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 10 | import cuchaz.enigma.utils.validation.PrintValidatable; | ||
| 11 | import cuchaz.enigma.utils.validation.ValidationContext; | ||
| 12 | |||
| 13 | public 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 @@ | |||
| 1 | package cuchaz.enigma.network.packet; | ||
| 2 | |||
| 3 | import java.io.DataInput; | ||
| 4 | import java.io.DataOutput; | ||
| 5 | import java.io.IOException; | ||
| 6 | |||
| 7 | import cuchaz.enigma.network.Message; | ||
| 8 | import cuchaz.enigma.network.ServerPacketHandler; | ||
| 9 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 10 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 11 | import cuchaz.enigma.utils.validation.PrintValidatable; | ||
| 12 | import cuchaz.enigma.utils.validation.ValidationContext; | ||
| 13 | |||
| 14 | public 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 @@ | |||
| 1 | package cuchaz.enigma.network.packet; | ||
| 2 | |||
| 3 | import java.io.DataInput; | ||
| 4 | import java.io.DataOutput; | ||
| 5 | import java.io.IOException; | ||
| 6 | |||
| 7 | import cuchaz.enigma.analysis.EntryReference; | ||
| 8 | import cuchaz.enigma.network.ClientPacketHandler; | ||
| 9 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 10 | import cuchaz.enigma.utils.validation.PrintValidatable; | ||
| 11 | import cuchaz.enigma.utils.validation.ValidationContext; | ||
| 12 | |||
| 13 | public 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 @@ | |||
| 1 | package cuchaz.enigma.network.packet; | 1 | package cuchaz.enigma.network.packet; |
| 2 | 2 | ||
| 3 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 4 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | ||
| 5 | import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; | ||
| 6 | import cuchaz.enigma.translation.mapping.tree.HashEntryTree; | ||
| 7 | import cuchaz.enigma.network.ClientPacketHandler; | ||
| 8 | import cuchaz.enigma.network.EnigmaServer; | ||
| 9 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 10 | |||
| 11 | import java.io.DataInput; | 3 | import java.io.DataInput; |
| 12 | import java.io.DataOutput; | 4 | import java.io.DataOutput; |
| 13 | import java.io.IOException; | 5 | import java.io.IOException; |
| 14 | import java.util.Collection; | 6 | import java.util.Collection; |
| 15 | import java.util.List; | 7 | import java.util.List; |
| 16 | 8 | ||
| 9 | import cuchaz.enigma.network.ClientPacketHandler; | ||
| 10 | import cuchaz.enigma.network.EnigmaServer; | ||
| 11 | import cuchaz.enigma.translation.mapping.EntryMapping; | ||
| 12 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | ||
| 13 | import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; | ||
| 14 | import cuchaz.enigma.translation.mapping.tree.HashEntryTree; | ||
| 15 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 16 | |||
| 17 | public class SyncMappingsS2CPacket implements Packet<ClientPacketHandler> { | 17 | public 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) { |