beginnings of a new hash/name system

This commit is contained in:
sirjonasxx 2021-04-23 00:17:02 +02:00
parent 964813dfe7
commit e51dcbaff8
12 changed files with 406 additions and 46 deletions

View File

@ -2,7 +2,7 @@ package gearth.extensions.extra.harble;
import gearth.extensions.Extension;
import gearth.extensions.IExtension;
import gearth.misc.harble_api.HarbleAPI;
import gearth.misc.harble_api.PacketInfoManager;
import gearth.protocol.HMessage;
import gearth.protocol.HPacket;
@ -20,7 +20,7 @@ public class HashSupport {
private final Object lock = new Object();
private HarbleAPI harbleAPI = new HarbleAPI(""); //empty
private PacketInfoManager packetInfoManager = new PacketInfoManager(""); //empty
private Map<String, List<Extension.MessageListener>> incomingMessageListeners = new HashMap<>();
private Map<String, List<Extension.MessageListener>> outgoingMessageListeners = new HashMap<>();
@ -31,13 +31,13 @@ public class HashSupport {
extension.onConnect((host, port, hotelversion, clientType, cachePath) -> {
// synchronized (lock) {
harbleAPI = new HarbleAPI(new File(cachePath));
packetInfoManager = new PacketInfoManager(new File(cachePath));
// }
});
extension.intercept(HMessage.Direction.TOSERVER, message -> {
// synchronized (lock) {
HarbleAPI.HarbleMessage haMessage = harbleAPI.getHarbleMessageFromHeaderId(HMessage.Direction.TOSERVER, message.getPacket().headerId());
PacketInfoManager.HarbleMessage haMessage = packetInfoManager.getHarbleMessageFromHeaderId(HMessage.Direction.TOSERVER, message.getPacket().headerId());
if (haMessage != null) {
List<Extension.MessageListener> listeners_hash = outgoingMessageListeners.get(haMessage.getHash());
List<Extension.MessageListener> listeners_name = outgoingMessageListeners.get(haMessage.getName());
@ -58,7 +58,7 @@ public class HashSupport {
});
extension.intercept(HMessage.Direction.TOCLIENT, message -> {
// synchronized (lock) {
HarbleAPI.HarbleMessage haMessage = harbleAPI.getHarbleMessageFromHeaderId(HMessage.Direction.TOCLIENT, message.getPacket().headerId());
PacketInfoManager.HarbleMessage haMessage = packetInfoManager.getHarbleMessageFromHeaderId(HMessage.Direction.TOCLIENT, message.getPacket().headerId());
if (haMessage != null) {
List<Extension.MessageListener> listeners_hash = incomingMessageListeners.get(haMessage.getHash());
List<Extension.MessageListener> listeners_name = incomingMessageListeners.get(haMessage.getName());
@ -91,12 +91,12 @@ public class HashSupport {
private boolean send(HMessage.Direction direction, String hashOrName, Object... objects) {
int headerId;
HarbleAPI.HarbleMessage fromname = harbleAPI.getHarbleMessageFromName(direction, hashOrName);
PacketInfoManager.HarbleMessage fromname = packetInfoManager.getHarbleMessageFromName(direction, hashOrName);
if (fromname != null) {
headerId = fromname.getHeaderId();
}
else {
List<HarbleAPI.HarbleMessage> possibilities = harbleAPI.getHarbleMessagesFromHash(direction, hashOrName);
List<PacketInfoManager.HarbleMessage> possibilities = packetInfoManager.getHarbleMessagesFromHash(direction, hashOrName);
if (possibilities.size() == 0) return false;
headerId = possibilities.get(0).getHeaderId();
}
@ -129,7 +129,7 @@ public class HashSupport {
return send(HMessage.Direction.TOSERVER, hashOrName, objects);
}
public HarbleAPI getHarbleAPI() {
return harbleAPI;
public PacketInfoManager getPacketInfoManager() {
return packetInfoManager;
}
}

View File

@ -2,7 +2,6 @@ package gearth.misc.harble_api;
import gearth.Main;
import gearth.misc.Cacher;
import gearth.protocol.HMessage;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
@ -10,39 +9,20 @@ import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
/**
* Created by Jonas on 10/11/2018.
*/
/**
* Ok the usage of this class is pretty shitty so I'm just gonna add some documentation here
*
* What this class does is fetching the revision (if needed) from the API, this is the only class with communication with the
* actual API. Then the result (if any) gets cached.
*
* The method "fetch(xxx);" needs to be called exactly once at the moment a new connection has been made.
*
* However, at that same moment the Extension class needs to send the "startConnection" signal to the extensions, and we want to make sure
* that the cached revision is already available at the moment the extensions get initialized with a new connection. That's why the
* fetch() method here only gets called by the extension class as that's the only way to ensure this method gets called BEFORE the extensions
* start. (bc im lazy and dont wanna rewrite code too)
*
*
* the "HARBLEAPI" object contains the latest fetched object and is ensured to be up-to-date with the current connection
*/
public class HarbleAPIFetcher {
public static final String CACHE_PREFIX = "HARBLE_API-";
public static final String HARBLE_API_URL = "https://api.harble.net/messages/$hotelversion$.json";
//latest fetched
public static HarbleAPI HARBLEAPI = null;
public static PacketInfoManager HARBLEAPI = null;
public synchronized static void fetch(String hotelversion, String clientType) {
// if unity
if (clientType.toLowerCase().contains("unity")) {
try {
HARBLEAPI = new HarbleAPI(
HARBLEAPI = new PacketInfoManager(
new File(new File(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI())
.getParentFile(), "messages.json"
)
@ -56,7 +36,7 @@ public class HarbleAPIFetcher {
String cacheName = CACHE_PREFIX + hotelversion;
if (Cacher.cacheFileExists(cacheName)) {
HARBLEAPI = new HarbleAPI(hotelversion);
HARBLEAPI = new PacketInfoManager(hotelversion);
}
else {
Connection connection = Jsoup.connect(HARBLE_API_URL.replace("$hotelversion$", hotelversion)).ignoreContentType(true);
@ -66,7 +46,7 @@ public class HarbleAPIFetcher {
if (response.statusCode() == 200) {
String messagesBodyJson = response.body();
Cacher.updateCache(messagesBodyJson, cacheName);
HARBLEAPI = new HarbleAPI(hotelversion);
HARBLEAPI = new PacketInfoManager(hotelversion);
}
else {
HARBLEAPI = null;

View File

@ -16,7 +16,7 @@ import java.util.Map;
/**
* Created by Jonas on 10/11/2018.
*/
public class HarbleAPI {
public class PacketInfoManager {
public class HarbleMessage {
private HMessage.Direction destination;
@ -78,15 +78,15 @@ public class HarbleAPI {
* @param hotelversion
*/
public static HarbleAPI get(String hotelversion) {
HarbleAPI wannabe = new HarbleAPI(hotelversion);
public static PacketInfoManager get(String hotelversion) {
PacketInfoManager wannabe = new PacketInfoManager(hotelversion);
if (!wannabe.success) {
return null;
}
return wannabe;
}
public HarbleAPI(String hotelversion) {
public PacketInfoManager(String hotelversion) {
String possibleCachedMessagesPath = HarbleAPIFetcher.CACHE_PREFIX + hotelversion;
if (Cacher.cacheFileExists(possibleCachedMessagesPath)) {
JSONObject object = Cacher.getCacheContents(possibleCachedMessagesPath);
@ -96,7 +96,7 @@ public class HarbleAPI {
}
}
public HarbleAPI(File f) {
public PacketInfoManager(File f) {
if (f.exists() && !f.isDirectory()) {
try {
String contents = String.join("\n", Files.readAllLines(f.toPath()));

View File

@ -0,0 +1,43 @@
package gearth.misc.packet_info;
import gearth.protocol.HMessage;
public class PacketInfo {
private final HMessage.Direction destination;
private final int headerId;
private final String hash;
private final String name;
private final String structure;
public PacketInfo(HMessage.Direction destination, int headerId, String hash, String name, String structure) {
this.destination = destination;
this.headerId = headerId;
this.hash = hash;
this.name = name;
this.structure = structure;
}
public String getName() {
return name;
}
public String getHash() {
return hash;
}
public int getHeaderId() {
return headerId;
}
public HMessage.Direction getDestination() {
return destination;
}
public String getStructure() {
return structure;
}
public String toString() {
return headerId + ": " + "[" + name + "][" + structure + "]";
}
}

View File

@ -0,0 +1,159 @@
package gearth.misc.packet_info;
import gearth.misc.Cacher;
import gearth.misc.harble_api.HarbleAPIFetcher;
import gearth.misc.packet_info.providers.RemotePacketInfoProvider;
import gearth.misc.packet_info.providers.implementations.HarblePacketInfoProvider;
import gearth.misc.packet_info.providers.implementations.SulekPacketInfoProvider;
import gearth.misc.packet_info.providers.implementations.UnityPacketInfoProvider;
import gearth.protocol.HMessage;
import gearth.protocol.connection.HClient;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.*;
import java.util.concurrent.Semaphore;
public class PacketInfoManager {
private Map<Integer, List<PacketInfo>> headerIdToMessage_incoming = new HashMap<>();
private Map<Integer, List<PacketInfo>> headerIdToMessage_outgoing = new HashMap<>();
private Map<String, List<PacketInfo>> hashToMessage_incoming = new HashMap<>();
private Map<String, List<PacketInfo>> hashToMessage_outgoing = new HashMap<>();
private Map<String, List<PacketInfo>> nameToMessage_incoming = new HashMap<>();
private Map<String, List<PacketInfo>> nameToMessage_outgoing = new HashMap<>();
public PacketInfoManager(List<PacketInfo> packetInfoList) {
for (PacketInfo packetInfo : packetInfoList) {
addMessage(packetInfo);
}
}
private void addMessage(PacketInfo packetInfo) {
Map<Integer, List<PacketInfo>> headerIdToMessage =
packetInfo.getDestination() == HMessage.Direction.TOCLIENT
? headerIdToMessage_incoming :
headerIdToMessage_outgoing;
Map<String, List<PacketInfo>> hashToMessage =
packetInfo.getDestination() == HMessage.Direction.TOCLIENT
? hashToMessage_incoming
: hashToMessage_outgoing;
Map<String, List<PacketInfo>> nameToMessage =
packetInfo.getDestination() == HMessage.Direction.TOCLIENT
? nameToMessage_incoming
: nameToMessage_outgoing;
headerIdToMessage.computeIfAbsent(packetInfo.getHeaderId(), k -> new ArrayList<>());
headerIdToMessage.get(packetInfo.getHeaderId()).add(packetInfo);
if (packetInfo.getHash() != null) {
hashToMessage.computeIfAbsent(packetInfo.getHash(), k -> new ArrayList<>());
hashToMessage.get(packetInfo.getHash()).add(packetInfo);
}
if (packetInfo.getName() != null) {
nameToMessage.computeIfAbsent(packetInfo.getName(), k -> new ArrayList<>());
nameToMessage.get(packetInfo.getName()).add(packetInfo);
}
}
public PacketInfo getPacketInfoFromHeaderId(HMessage.Direction direction, int headerId) {
Map<Integer, List<PacketInfo>> headerIdToMessage =
(direction == HMessage.Direction.TOSERVER
? headerIdToMessage_outgoing
: headerIdToMessage_incoming);
if (headerIdToMessage.get(headerId) == null) return null;
return headerIdToMessage.get(headerId).get(0);
}
public PacketInfo getHarbleMessagesFromHash(HMessage.Direction direction, String hash) {
Map<String, List<PacketInfo>> hashToMessage =
(direction == HMessage.Direction.TOSERVER
? hashToMessage_outgoing
: hashToMessage_incoming);
if (hashToMessage.get(hash) == null) return null;
return hashToMessage.get(hash).get(0);
}
public PacketInfo getHarbleMessageFromName(HMessage.Direction direction, String name) {
Map<String, List<PacketInfo>> nameToMessage =
(direction == HMessage.Direction.TOSERVER
? nameToMessage_outgoing
: nameToMessage_incoming);
if (nameToMessage.get(name) == null) return null;
return nameToMessage.get(name).get(0);
}
public List<PacketInfo> getAllPacketInfoFromHeaderId(HMessage.Direction direction, int headerId) {
Map<Integer, List<PacketInfo>> headerIdToMessage =
(direction == HMessage.Direction.TOSERVER
? headerIdToMessage_outgoing
: headerIdToMessage_incoming);
return headerIdToMessage.get(headerId) == null ? new ArrayList<>() : headerIdToMessage.get(headerId);
}
public List<PacketInfo> getAllHarbleMessagesFromHash(HMessage.Direction direction, String hash) {
Map<String, List<PacketInfo>> hashToMessage =
(direction == HMessage.Direction.TOSERVER
? hashToMessage_outgoing
: hashToMessage_incoming);
return hashToMessage.get(hash) == null ? new ArrayList<>() : hashToMessage.get(hash);
}
public List<PacketInfo> getAllHarbleMessageFromName(HMessage.Direction direction, String name) {
Map<String, List<PacketInfo>> nameToMessage =
(direction == HMessage.Direction.TOSERVER
? nameToMessage_outgoing
: nameToMessage_incoming);
return nameToMessage.get(name) == null ? new ArrayList<>() : nameToMessage.get(name);
}
public static PacketInfoManager fromHotelVersion(String hotelversion, HClient clientType) {
List<PacketInfo> result = new ArrayList<>();
if (clientType == HClient.UNITY) {
result.addAll(new UnityPacketInfoProvider(hotelversion).provide());
}
else if (clientType == HClient.FLASH) {
try {
List<RemotePacketInfoProvider> providers = new ArrayList<>();
providers.add(new HarblePacketInfoProvider(hotelversion));
providers.add(new SulekPacketInfoProvider(hotelversion));
Semaphore blockUntilComplete = new Semaphore(providers.size());
blockUntilComplete.acquire(providers.size());
List<PacketInfo> synchronizedResult = Collections.synchronizedList(result);
for (RemotePacketInfoProvider provider : providers) {
new Thread(() -> {
synchronizedResult.addAll(provider.provide());
blockUntilComplete.release();
}).start();
}
blockUntilComplete.acquire(providers.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return new PacketInfoManager(result);
}
}

View File

@ -0,0 +1,40 @@
package gearth.misc.packet_info.providers;
import gearth.misc.Cacher;
import gearth.misc.packet_info.PacketInfo;
import org.json.JSONObject;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
public abstract class PacketInfoProvider {
protected final String hotelVersion;
public PacketInfoProvider(String hotelVersion) {
this.hotelVersion = hotelVersion;
}
protected abstract File getFile();
public List<PacketInfo> provide() {
File file = getFile();
if (file == null || !file.exists() || file.isDirectory()) return new ArrayList<>();
try {
String contents = String.join("\n", Files.readAllLines(file.toPath()));
JSONObject object = new JSONObject(contents);
return parsePacketInfo(object);
} catch (IOException e) {
e.printStackTrace();
}
return new ArrayList<>();
}
protected abstract List<PacketInfo> parsePacketInfo(JSONObject jsonObject);
}

View File

@ -0,0 +1,41 @@
package gearth.misc.packet_info.providers;
import gearth.misc.Cacher;
import gearth.misc.harble_api.PacketInfoManager;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import java.io.File;
import java.io.IOException;
public abstract class RemotePacketInfoProvider extends PacketInfoProvider {
public RemotePacketInfoProvider(String hotelVersion) {
super(hotelVersion);
}
protected abstract String getRemoteUrl();
protected abstract String getCacheName();
@Override
protected File getFile() {
File f = new File(Cacher.getCacheDir(), getCacheName());
if (!f.exists()) {
Connection connection = Jsoup.connect(getRemoteUrl()).ignoreContentType(true);
try {
connection.timeout(3000);
Connection.Response response = connection.execute();
if (response.statusCode() == 200) {
String messagesBodyJson = response.body();
Cacher.updateCache(messagesBodyJson, getCacheName());
}
else {
return null;
}
} catch (IOException e) {
return null;
}
}
return new File(Cacher.getCacheDir(), getCacheName());
}
}

View File

@ -0,0 +1,35 @@
package gearth.misc.packet_info.providers.implementations;
import gearth.misc.Cacher;
import gearth.misc.packet_info.PacketInfo;
import gearth.misc.packet_info.providers.PacketInfoProvider;
import gearth.misc.packet_info.providers.RemotePacketInfoProvider;
import org.json.JSONObject;
import java.io.File;
import java.util.List;
public class HarblePacketInfoProvider extends RemotePacketInfoProvider {
public static final String CACHE_PREFIX = "HARBLE_API-";
public static final String HARBLE_API_URL = "https://api.harble.net/messages/$hotelversion$.json";
public HarblePacketInfoProvider(String hotelVersion) {
super(hotelVersion);
}
@Override
protected String getRemoteUrl() {
return HARBLE_API_URL.replace("$hotelversion$", hotelVersion);
}
@Override
protected String getCacheName() {
return CACHE_PREFIX + hotelVersion;
}
@Override
protected List<PacketInfo> parsePacketInfo(JSONObject jsonObject) {
return null;
}
}

View File

@ -0,0 +1,32 @@
package gearth.misc.packet_info.providers.implementations;
import gearth.misc.packet_info.PacketInfo;
import gearth.misc.packet_info.providers.RemotePacketInfoProvider;
import org.json.JSONObject;
import java.util.List;
public class SulekPacketInfoProvider extends RemotePacketInfoProvider {
public static final String CACHE_PREFIX = "SULEK_API-";
public static final String SULEK_API_URL = "https://api.sulek.dev/releases/$hotelversion$/messages";
public SulekPacketInfoProvider(String hotelVersion) {
super(hotelVersion);
}
@Override
protected String getRemoteUrl() {
return SULEK_API_URL.replace("$hotelversion$", hotelVersion);
}
@Override
protected String getCacheName() {
return CACHE_PREFIX + hotelVersion;
}
@Override
protected List<PacketInfo> parsePacketInfo(JSONObject jsonObject) {
return null;
}
}

View File

@ -0,0 +1,33 @@
package gearth.misc.packet_info.providers.implementations;
import gearth.Main;
import gearth.misc.packet_info.PacketInfo;
import gearth.misc.packet_info.providers.PacketInfoProvider;
import org.json.JSONObject;
import java.io.File;
import java.net.URISyntaxException;
import java.util.List;
public class UnityPacketInfoProvider extends PacketInfoProvider {
public UnityPacketInfoProvider(String hotelVersion) {
super(hotelVersion);
}
@Override
protected File getFile() {
try {
return new File(new File(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI())
.getParentFile(), "messages.json");
} catch (URISyntaxException e) {
e.printStackTrace();
return null;
}
}
@Override
protected List<PacketInfo> parsePacketInfo(JSONObject jsonObject) {
return null;
}
}

View File

@ -1,12 +1,11 @@
package gearth.protocol;
import gearth.misc.StringifyAble;
import gearth.misc.harble_api.HarbleAPI;
import gearth.misc.harble_api.PacketInfoManager;
import gearth.misc.harble_api.HarbleAPIFetcher;
import gearth.misc.packetrepresentation.InvalidPacketException;
import gearth.misc.packetrepresentation.PacketStringUtils;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
@ -581,7 +580,7 @@ public class HPacket implements StringifyAble {
}
private String getHarbleStructure(HMessage.Direction direction) {
HarbleAPI.HarbleMessage msg;
PacketInfoManager.HarbleMessage msg;
if (HarbleAPIFetcher.HARBLEAPI != null &&
((msg = HarbleAPIFetcher.HARBLEAPI.getHarbleMessageFromHeaderId(direction, headerId())) != null)) {
if (msg.getStructure() != null && structureEquals(msg.getStructure())) {

View File

@ -1,13 +1,11 @@
package gearth.ui.logger.loggerdisplays.uilogger;
import gearth.misc.harble_api.HarbleAPI;
import gearth.misc.harble_api.PacketInfoManager;
import gearth.misc.harble_api.HarbleAPIFetcher;
import gearth.protocol.HMessage;
import gearth.protocol.HPacket;
import gearth.ui.logger.loggerdisplays.PacketLogger;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.event.ActionEvent;
import javafx.fxml.Initializable;
import javafx.scene.control.CheckMenuItem;
@ -96,8 +94,8 @@ public class UiLoggerController implements Initializable {
lblHarbleAPI.setText("Messages: " + (HarbleAPIFetcher.HARBLEAPI == null ? "False" : "True"));
if ((viewMessageName || viewMessageHash) && HarbleAPIFetcher.HARBLEAPI != null) {
HarbleAPI api = HarbleAPIFetcher.HARBLEAPI;
HarbleAPI.HarbleMessage message = api.getHarbleMessageFromHeaderId(
PacketInfoManager api = HarbleAPIFetcher.HARBLEAPI;
PacketInfoManager.HarbleMessage message = api.getHarbleMessageFromHeaderId(
(isIncoming ? HMessage.Direction.TOCLIENT : HMessage.Direction.TOSERVER),
packet.headerId()
);