From 09cede554dbbae553c47c36558fbcfdd302071c3 Mon Sep 17 00:00:00 2001 From: WiredSpast Date: Thu, 10 Feb 2022 23:49:52 +0100 Subject: [PATCH 1/3] Small bug fix in `addToPacket` --- .../gearth/extensions/parsers/navigator/HNavigatorRoom.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/G-Earth/src/main/java/gearth/extensions/parsers/navigator/HNavigatorRoom.java b/G-Earth/src/main/java/gearth/extensions/parsers/navigator/HNavigatorRoom.java index 424b57f..2e53c8c 100644 --- a/G-Earth/src/main/java/gearth/extensions/parsers/navigator/HNavigatorRoom.java +++ b/G-Earth/src/main/java/gearth/extensions/parsers/navigator/HNavigatorRoom.java @@ -128,7 +128,7 @@ public class HNavigatorRoom { } packet.appendInt(multiUse); - packet.appendObjects(objectsToAppend); + packet.appendObjects(objectsToAppend.toArray(new Object[] {})); } public int getFlatId() { From 27b754339c0762136b0271319ae27b2ae26501f1 Mon Sep 17 00:00:00 2001 From: WiredSpast Date: Thu, 10 Feb 2022 23:53:23 +0100 Subject: [PATCH 2/3] Small bug fix in `parseFromUpdate` --- G-Earth/src/main/java/gearth/extensions/parsers/HFriend.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/G-Earth/src/main/java/gearth/extensions/parsers/HFriend.java b/G-Earth/src/main/java/gearth/extensions/parsers/HFriend.java index d59cdfc..4ef6c48 100644 --- a/G-Earth/src/main/java/gearth/extensions/parsers/HFriend.java +++ b/G-Earth/src/main/java/gearth/extensions/parsers/HFriend.java @@ -105,7 +105,7 @@ public class HFriend { packet.readString(); } - int friendCount = packet.getReadIndex(); + int friendCount = packet.readInteger(); List removedIds = new ArrayList<>(); for(int i = 0; i < friendCount; i++) { if(packet.readInteger() != -1) { From 46fe97d4ae1d757ed30be4f11f50111b4fb940b4 Mon Sep 17 00:00:00 2001 From: WiredSpast Date: Fri, 11 Feb 2022 00:16:37 +0100 Subject: [PATCH 3/3] Added GAsync tool --- .../extra/tools/AwaitingPacket.java | 84 ++++++++++++++ .../gearth/extensions/extra/tools/GAsync.java | 106 ++++++++++++++++++ 2 files changed, 190 insertions(+) create mode 100644 G-Earth/src/main/java/gearth/extensions/extra/tools/AwaitingPacket.java create mode 100644 G-Earth/src/main/java/gearth/extensions/extra/tools/GAsync.java diff --git a/G-Earth/src/main/java/gearth/extensions/extra/tools/AwaitingPacket.java b/G-Earth/src/main/java/gearth/extensions/extra/tools/AwaitingPacket.java new file mode 100644 index 0000000..297a2bf --- /dev/null +++ b/G-Earth/src/main/java/gearth/extensions/extra/tools/AwaitingPacket.java @@ -0,0 +1,84 @@ +package gearth.extensions.extra.tools; + +import gearth.protocol.HMessage; +import gearth.protocol.HPacket; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Timer; +import java.util.TimerTask; +import java.util.function.Predicate; + +public class AwaitingPacket { + private final String headerName; + private final HMessage.Direction direction; + private HPacket packet; + private boolean received = false; + private final ArrayList> conditions = new ArrayList<>(); + private final long start; + private long minWait = 0; + + public AwaitingPacket(String headerName, HMessage.Direction direction, long maxWaitingTimeMillis) { + if (maxWaitingTimeMillis < 30) { + maxWaitingTimeMillis = 30; + } + + AwaitingPacket self = this; + new Timer().schedule(new TimerTask() { + @Override + public void run() { + self.received = true; + } + }, maxWaitingTimeMillis); + + this.start = System.currentTimeMillis(); + + this.direction = direction; + this.headerName = headerName; + } + + public String getHeaderName() { + return this.headerName; + } + + public HMessage.Direction getDirection() { + return this.direction; + } + + public AwaitingPacket setMinWaitingTime(long millis) { + this.minWait = millis; + + return this; + } + + @SafeVarargs + public final AwaitingPacket addConditions(Predicate... conditions) { + this.conditions.addAll(Arrays.asList(conditions)); + + return this; + } + + protected void setPacket(HPacket packet) { + this.packet = packet; + this.received = true; + } + + protected HPacket getPacket() { + return this.packet; + } + + protected boolean test(HMessage hMessage) { + for (Predicate condition : this.conditions) { + hMessage.getPacket().resetReadIndex(); + if(!condition.test(hMessage.getPacket())) { + return false; + } + } + + return true; + } + + protected boolean isReady() { + return this.received && this.start + this.minWait < System.currentTimeMillis(); + } +} diff --git a/G-Earth/src/main/java/gearth/extensions/extra/tools/GAsync.java b/G-Earth/src/main/java/gearth/extensions/extra/tools/GAsync.java new file mode 100644 index 0000000..dc597f9 --- /dev/null +++ b/G-Earth/src/main/java/gearth/extensions/extra/tools/GAsync.java @@ -0,0 +1,106 @@ +package gearth.extensions.extra.tools; + +import gearth.extensions.ExtensionBase; +import gearth.protocol.HMessage; +import gearth.protocol.HPacket; +import gearth.services.packet_info.PacketInfo; +import gearth.services.packet_info.PacketInfoManager; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class GAsync { + private PacketInfoManager packetInfoManager; + private final ArrayList awaitingPackets = new ArrayList<>(); + + public GAsync(ExtensionBase ext) { + this.packetInfoManager = ext.getPacketInfoManager(); + ext.onConnect((host, port, hotelversion, clientIdentifier, clientType) -> + this.packetInfoManager = ext.getPacketInfoManager() + ); + + ext.intercept(HMessage.Direction.TOSERVER, this::onMessageToServer); + ext.intercept(HMessage.Direction.TOCLIENT, this::onMessageToClient); + } + + private void onMessageToClient(HMessage hMessage) { + if (packetInfoManager != null) { + List packetInfoList = packetInfoManager.getAllPacketInfoFromHeaderId(HMessage.Direction.TOCLIENT, hMessage.getPacket().headerId()); + for (PacketInfo packetInfo : packetInfoList) { + synchronized (awaitingPackets) { + awaitingPackets.stream() + .filter(p -> p.getDirection().equals(HMessage.Direction.TOCLIENT)) + .filter(p -> p.getHeaderName().equals(packetInfo.getName())) + .filter(p -> p.test(hMessage)) + .forEach(p -> p.setPacket(hMessage.getPacket())); + } + } + } + } + + private void onMessageToServer(HMessage hMessage) { + if (packetInfoManager != null) { + List packetInfoList = packetInfoManager.getAllPacketInfoFromHeaderId(HMessage.Direction.TOSERVER, hMessage.getPacket().headerId()); + for (PacketInfo packetInfo : packetInfoList) { + synchronized (awaitingPackets) { + awaitingPackets.stream() + .filter(p -> p.getDirection().equals(HMessage.Direction.TOSERVER)) + .filter(p -> p.getHeaderName().equals(packetInfo.getName())) + .filter(p -> p.test(hMessage)) + .forEach(p -> p.setPacket(hMessage.getPacket())); + } + } + } + } + + public HPacket awaitPacket(AwaitingPacket ...packets) { + synchronized (awaitingPackets) { + awaitingPackets.addAll(Arrays.asList(packets)); + } + + while (true) { + for (AwaitingPacket packet : packets) { + if (packet.isReady()) { + synchronized (awaitingPackets) { + awaitingPackets.removeAll(Arrays.asList(packets)); + } + return packet.getPacket(); + } + } + sleep(1); + } + } + + public HPacket[] awaitMultiplePackets(AwaitingPacket ...packets) { + synchronized (awaitingPackets) { + awaitingPackets.addAll(Arrays.asList(packets)); + } + + while (true) { + if (Arrays.stream(packets).allMatch(AwaitingPacket::isReady)) { + synchronized (awaitingPackets) { + awaitingPackets.removeAll(Arrays.asList(packets)); + } + return Arrays.stream(packets) + .map(AwaitingPacket::getPacket) + .toArray(HPacket[]::new); + } + sleep(1); + } + } + + public void clear() { + synchronized (awaitingPackets) { + awaitingPackets.clear(); + } + } + + private void sleep(int millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +}