Initial Commit
This commit is contained in:
commit
42e01c4b78
12 changed files with 739 additions and 0 deletions
|
@ -0,0 +1,7 @@
|
|||
package de.pauljako.cosmeticserver;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public record ClientMapping(UUID uuid, ConcurrentHashMap<String, Object> cosmetics) {
|
||||
}
|
58
src/main/java/de/pauljako/cosmeticserver/CosmeticServer.java
Normal file
58
src/main/java/de/pauljako/cosmeticserver/CosmeticServer.java
Normal file
|
@ -0,0 +1,58 @@
|
|||
package de.pauljako.cosmeticserver;
|
||||
|
||||
import de.craftsblock.craftscore.json.Json;
|
||||
import de.craftsblock.craftscore.json.JsonParser;
|
||||
import de.craftsblock.craftsnet.addon.Addon;
|
||||
import de.craftsblock.craftsnet.api.Handler;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class CosmeticServer extends Addon {
|
||||
|
||||
|
||||
private static CosmeticServer instance;
|
||||
|
||||
private Json serverCosmetics;
|
||||
|
||||
private Thread thread;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
|
||||
instance = this;
|
||||
|
||||
File assets = new File(getDataFolder(), "assets");
|
||||
assets.mkdirs();
|
||||
|
||||
File file = new File(getDataFolder(), "cosmetics.json");
|
||||
serverCosmetics = JsonParser.parse(file);
|
||||
|
||||
routeRegistry().share("/v1/cosmetic/assets", assets);
|
||||
|
||||
CosmeticSocket socket = new CosmeticSocket();
|
||||
routeRegistry().register((Handler) socket);
|
||||
listenerRegistry().register(socket);
|
||||
new HeartbeatThread();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
try {
|
||||
thread.interrupt();
|
||||
thread.join(15);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
instance = null;
|
||||
|
||||
}
|
||||
|
||||
public Json getServerCosmetics() {
|
||||
return serverCosmetics;
|
||||
}
|
||||
|
||||
public static CosmeticServer instance() {
|
||||
return instance;
|
||||
}
|
||||
}
|
138
src/main/java/de/pauljako/cosmeticserver/CosmeticSocket.java
Normal file
138
src/main/java/de/pauljako/cosmeticserver/CosmeticSocket.java
Normal file
|
@ -0,0 +1,138 @@
|
|||
package de.pauljako.cosmeticserver;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import de.craftsblock.craftscore.event.EventHandler;
|
||||
import de.craftsblock.craftscore.event.ListenerAdapter;
|
||||
import de.craftsblock.craftscore.json.Json;
|
||||
import de.craftsblock.craftscore.json.JsonParser;
|
||||
import de.craftsblock.craftscore.utils.Validator;
|
||||
import de.craftsblock.craftsnet.api.websocket.*;
|
||||
import de.craftsblock.craftsnet.api.websocket.annotations.MessageReceiver;
|
||||
import de.craftsblock.craftsnet.api.websocket.annotations.Socket;
|
||||
import de.craftsblock.craftsnet.events.sockets.ClientDisconnectEvent;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Socket("/v1/cosmetic")
|
||||
public class CosmeticSocket implements SocketHandler, ListenerAdapter {
|
||||
|
||||
public static final ConcurrentHashMap<WebSocketClient, ClientMapping> clients = new ConcurrentHashMap<>();
|
||||
|
||||
public static final ConcurrentHashMap<UUID, ClientMapping> cosmetics = new ConcurrentHashMap<>();
|
||||
|
||||
@MessageReceiver
|
||||
public void handleMessage(SocketExchange exchange, String message) throws IOException {
|
||||
WebSocketClient client = exchange.client();
|
||||
if (!Validator.isJsonValid(message)) {
|
||||
client.sendMessage(JsonParser.parse("{}")
|
||||
.set("error", "Send data must be in JSON format")
|
||||
.asString());
|
||||
return;
|
||||
}
|
||||
|
||||
Json data = JsonParser.parse(message);
|
||||
if (data.contains("search")) {
|
||||
|
||||
String type = data.getString("search");
|
||||
String name = data.getString("name");
|
||||
|
||||
JsonObject cosmetic = searchServerCosmetic(type, name);
|
||||
|
||||
Json result = Json.empty()
|
||||
.set("id", data.getLong("id"))
|
||||
.set("search", type)
|
||||
.set("name", name)
|
||||
.set("result", false);
|
||||
|
||||
if (cosmetic != null) {
|
||||
result.set("result", cosmetic);
|
||||
}
|
||||
|
||||
exchange.client().sendMessage(result.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.contains("cosmetics") && data.contains("uuid")) {
|
||||
UUID uuid = UUID.fromString(data.getString("uuid"));
|
||||
|
||||
ConcurrentHashMap<String, Object> cosmetics = new ConcurrentHashMap<>();
|
||||
data.get("cosmetics").getAsJsonObject().entrySet().forEach(entry -> cosmetics.put(entry.getKey(), entry.getValue()));
|
||||
|
||||
|
||||
convertToServer(cosmetics);
|
||||
|
||||
ClientMapping mapping = new ClientMapping(uuid, cosmetics);
|
||||
exchange.broadcast(JsonParser.parse("{}")
|
||||
.set("uuid", uuid.toString())
|
||||
.set("cosmetics", bakeData(cosmetics))
|
||||
.asString());
|
||||
clients.put(client, mapping);
|
||||
CosmeticSocket.cosmetics.put(uuid, mapping);
|
||||
}
|
||||
|
||||
JsonArray array = new JsonArray();
|
||||
if (data.contains("data")) {
|
||||
for (UUID uuid : data.getStringList("data").stream().map(UUID::fromString).toList()) {
|
||||
if (cosmetics.containsKey(uuid)) {
|
||||
ClientMapping mapping = cosmetics.get(uuid);
|
||||
Json target = JsonParser.parse("{}");
|
||||
target.set("uuid", uuid.toString());
|
||||
target.set("cosmetics", bakeData(mapping.cosmetics()));
|
||||
array.add(target.getObject());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
client.sendMessage(JsonParser.parse("{}")
|
||||
.set("data", array)
|
||||
.asString());
|
||||
|
||||
}
|
||||
|
||||
private void convertToServer(ConcurrentHashMap<String, Object> cosmetics) {
|
||||
cosmetics.forEach((type, data) -> {
|
||||
if (!(data instanceof JsonElement element)) return;
|
||||
if (!element.isJsonPrimitive() && !element.getAsJsonPrimitive().isString()) return;
|
||||
|
||||
String name = element.getAsString();
|
||||
JsonObject cosmetic = searchServerCosmetic(type, name);
|
||||
if (cosmetic == null) return;
|
||||
cosmetics.put(type, cosmetic);
|
||||
});
|
||||
}
|
||||
|
||||
private JsonObject searchServerCosmetic(String type, String name) {
|
||||
Json serverCosmetics = CosmeticServer.instance().getServerCosmetics();
|
||||
|
||||
if (!serverCosmetics.contains(type + "." + name)) return null;
|
||||
Json cosmetic = JsonParser.parse(serverCosmetics.get(type + "." + name));
|
||||
String id = cosmetic.contains("id") ? cosmetic.getString("id") : name;
|
||||
return (JsonObject) JsonParser.parse("{}")
|
||||
.set("display", cosmetic.contains("display") ? cosmetic.get("display") : name)
|
||||
.set("name", name)
|
||||
.set("delay", cosmetic.contains("delay") ? cosmetic.getInt("delay") : 30)
|
||||
.set("frames", cosmetic.contains("frames") ? cosmetic.getStringList("frames").size() : 1)
|
||||
.set("url", "http://cosmetic.airclient.pauljako.de/v1/cosmetic/assets/" + type + "/" + name + "/frame_" + id)
|
||||
.getObject();
|
||||
}
|
||||
|
||||
private JsonElement bakeData(ConcurrentHashMap<String, Object> elements) {
|
||||
Json object = JsonParser.parse("{}");
|
||||
elements.forEach(object::set);
|
||||
return object.getObject();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void handleDisconnect(ClientDisconnectEvent event) {
|
||||
WebSocketClient client = event.getExchange().client();
|
||||
if (!clients.containsKey(client)) return;
|
||||
|
||||
ClientMapping mapping = clients.remove(client);
|
||||
cosmetics.remove(mapping.uuid());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package de.pauljako.cosmeticserver;
|
||||
|
||||
import de.craftsblock.craftsnet.api.websocket.WebSocketClient;
|
||||
|
||||
public class HeartbeatThread implements Runnable{
|
||||
|
||||
public HeartbeatThread() {
|
||||
Thread thread = new Thread(this);
|
||||
thread.setName("Connection Heartbeat Thread");
|
||||
thread.start();
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(thread::interrupt));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
|
||||
try {
|
||||
for (WebSocketClient client : CosmeticSocket.clients.keySet()) {
|
||||
client.sendMessage("ping");
|
||||
}
|
||||
Thread.sleep(15000);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
4
src/main/resources/addon.json
Normal file
4
src/main/resources/addon.json
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"name": "AirServer",
|
||||
"main": "de.pauljako.cosmeticserver.CosmeticServer"
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue