From d8fe269327a1a51f2588a3573a4764613da16388 Mon Sep 17 00:00:00 2001 From: Trumeet Date: Tue, 26 Jul 2022 19:06:11 -0700 Subject: Move the mod to mod/ --- .../typeadapters/RuntimeTypeAdapterFactory.java | 272 --------------------- src/main/java/moe/ymc/acron/Acron.java | 32 --- .../java/moe/ymc/acron/MinecraftServerHolder.java | 28 --- src/main/java/moe/ymc/acron/auth/Action.java | 10 - src/main/java/moe/ymc/acron/auth/Client.java | 9 - .../java/moe/ymc/acron/auth/PolicyChecker.java | 42 ---- src/main/java/moe/ymc/acron/auth/Rule.java | 10 - src/main/java/moe/ymc/acron/c2s/ReqCmd.java | 51 ---- src/main/java/moe/ymc/acron/c2s/ReqSetConfig.java | 63 ----- src/main/java/moe/ymc/acron/c2s/Request.java | 6 - src/main/java/moe/ymc/acron/cmd/CmdOut.java | 53 ---- src/main/java/moe/ymc/acron/cmd/CmdQueue.java | 17 -- .../java/moe/ymc/acron/cmd/CmdResConsumer.java | 33 --- src/main/java/moe/ymc/acron/cmd/CmdSrc.java | 34 --- src/main/java/moe/ymc/acron/common/Vec2f.java | 25 -- src/main/java/moe/ymc/acron/common/Vec3d.java | 34 --- src/main/java/moe/ymc/acron/common/WorldKey.java | 35 --- src/main/java/moe/ymc/acron/config/Config.java | 30 --- .../java/moe/ymc/acron/config/ConfigReloadCmd.java | 41 ---- .../java/moe/ymc/acron/config/json/Client.java | 45 ---- .../java/moe/ymc/acron/config/json/Config.java | 103 -------- .../json/ConfigDeserializationException.java | 18 -- .../ymc/acron/config/json/ConfigDeserializer.java | 27 -- .../ymc/acron/config/json/ConfigJsonObject.java | 7 - src/main/java/moe/ymc/acron/config/json/Rule.java | 35 --- src/main/java/moe/ymc/acron/jvav/Pair.java | 4 - .../moe/ymc/acron/mixin/CommandManagerMixin.java | 38 --- .../moe/ymc/acron/mixin/LivingEntityMixin.java | 41 ---- .../acron/mixin/MinecraftDedicatedServerMixin.java | 21 -- .../moe/ymc/acron/mixin/MinecraftServerMixin.java | 33 --- .../mixin/ServerLoginNetworkHandlerMixin.java | 47 ---- .../moe/ymc/acron/mixin/ServerNetworkIoMixin.java | 65 ----- .../acron/mixin/ServerPlayNetworkHandlerMixin.java | 43 ---- .../ymc/acron/mixin/ServerPlayerEntityMixin.java | 32 --- .../java/moe/ymc/acron/net/AcronInitializer.java | 25 -- src/main/java/moe/ymc/acron/net/Attributes.java | 13 - src/main/java/moe/ymc/acron/net/AuthHandler.java | 98 -------- .../moe/ymc/acron/net/ClientConfiguration.java | 20 -- .../moe/ymc/acron/net/ClientIdentification.java | 11 - .../java/moe/ymc/acron/net/HandshakeComplete.java | 7 - .../java/moe/ymc/acron/net/WSFrameHandler.java | 174 ------------- src/main/java/moe/ymc/acron/s2c/Entity.java | 26 -- src/main/java/moe/ymc/acron/s2c/Event.java | 4 - src/main/java/moe/ymc/acron/s2c/EventQueue.java | 28 --- .../moe/ymc/acron/s2c/event/EventDisconnected.java | 12 - .../moe/ymc/acron/s2c/event/EventEntityDeath.java | 12 - .../java/moe/ymc/acron/s2c/event/EventLagging.java | 9 - .../moe/ymc/acron/s2c/event/EventPlayerJoined.java | 10 - .../ymc/acron/s2c/event/EventPlayerMessage.java | 12 - .../moe/ymc/acron/s2c/response/EventCmdOut.java | 13 - .../moe/ymc/acron/s2c/response/EventCmdRes.java | 10 - .../moe/ymc/acron/s2c/response/EventError.java | 22 -- .../java/moe/ymc/acron/s2c/response/EventOk.java | 8 - .../moe/ymc/acron/serialization/Serializer.java | 60 ----- src/main/resources/acron.mixins.json | 21 -- src/main/resources/fabric.mod.json | 24 -- 56 files changed, 2003 deletions(-) delete mode 100644 src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java delete mode 100644 src/main/java/moe/ymc/acron/Acron.java delete mode 100644 src/main/java/moe/ymc/acron/MinecraftServerHolder.java delete mode 100644 src/main/java/moe/ymc/acron/auth/Action.java delete mode 100644 src/main/java/moe/ymc/acron/auth/Client.java delete mode 100644 src/main/java/moe/ymc/acron/auth/PolicyChecker.java delete mode 100644 src/main/java/moe/ymc/acron/auth/Rule.java delete mode 100644 src/main/java/moe/ymc/acron/c2s/ReqCmd.java delete mode 100644 src/main/java/moe/ymc/acron/c2s/ReqSetConfig.java delete mode 100644 src/main/java/moe/ymc/acron/c2s/Request.java delete mode 100644 src/main/java/moe/ymc/acron/cmd/CmdOut.java delete mode 100644 src/main/java/moe/ymc/acron/cmd/CmdQueue.java delete mode 100644 src/main/java/moe/ymc/acron/cmd/CmdResConsumer.java delete mode 100644 src/main/java/moe/ymc/acron/cmd/CmdSrc.java delete mode 100644 src/main/java/moe/ymc/acron/common/Vec2f.java delete mode 100644 src/main/java/moe/ymc/acron/common/Vec3d.java delete mode 100644 src/main/java/moe/ymc/acron/common/WorldKey.java delete mode 100644 src/main/java/moe/ymc/acron/config/Config.java delete mode 100644 src/main/java/moe/ymc/acron/config/ConfigReloadCmd.java delete mode 100644 src/main/java/moe/ymc/acron/config/json/Client.java delete mode 100644 src/main/java/moe/ymc/acron/config/json/Config.java delete mode 100644 src/main/java/moe/ymc/acron/config/json/ConfigDeserializationException.java delete mode 100644 src/main/java/moe/ymc/acron/config/json/ConfigDeserializer.java delete mode 100644 src/main/java/moe/ymc/acron/config/json/ConfigJsonObject.java delete mode 100644 src/main/java/moe/ymc/acron/config/json/Rule.java delete mode 100644 src/main/java/moe/ymc/acron/jvav/Pair.java delete mode 100644 src/main/java/moe/ymc/acron/mixin/CommandManagerMixin.java delete mode 100644 src/main/java/moe/ymc/acron/mixin/LivingEntityMixin.java delete mode 100644 src/main/java/moe/ymc/acron/mixin/MinecraftDedicatedServerMixin.java delete mode 100644 src/main/java/moe/ymc/acron/mixin/MinecraftServerMixin.java delete mode 100644 src/main/java/moe/ymc/acron/mixin/ServerLoginNetworkHandlerMixin.java delete mode 100644 src/main/java/moe/ymc/acron/mixin/ServerNetworkIoMixin.java delete mode 100644 src/main/java/moe/ymc/acron/mixin/ServerPlayNetworkHandlerMixin.java delete mode 100644 src/main/java/moe/ymc/acron/mixin/ServerPlayerEntityMixin.java delete mode 100644 src/main/java/moe/ymc/acron/net/AcronInitializer.java delete mode 100644 src/main/java/moe/ymc/acron/net/Attributes.java delete mode 100644 src/main/java/moe/ymc/acron/net/AuthHandler.java delete mode 100644 src/main/java/moe/ymc/acron/net/ClientConfiguration.java delete mode 100644 src/main/java/moe/ymc/acron/net/ClientIdentification.java delete mode 100644 src/main/java/moe/ymc/acron/net/HandshakeComplete.java delete mode 100644 src/main/java/moe/ymc/acron/net/WSFrameHandler.java delete mode 100644 src/main/java/moe/ymc/acron/s2c/Entity.java delete mode 100644 src/main/java/moe/ymc/acron/s2c/Event.java delete mode 100644 src/main/java/moe/ymc/acron/s2c/EventQueue.java delete mode 100644 src/main/java/moe/ymc/acron/s2c/event/EventDisconnected.java delete mode 100644 src/main/java/moe/ymc/acron/s2c/event/EventEntityDeath.java delete mode 100644 src/main/java/moe/ymc/acron/s2c/event/EventLagging.java delete mode 100644 src/main/java/moe/ymc/acron/s2c/event/EventPlayerJoined.java delete mode 100644 src/main/java/moe/ymc/acron/s2c/event/EventPlayerMessage.java delete mode 100644 src/main/java/moe/ymc/acron/s2c/response/EventCmdOut.java delete mode 100644 src/main/java/moe/ymc/acron/s2c/response/EventCmdRes.java delete mode 100644 src/main/java/moe/ymc/acron/s2c/response/EventError.java delete mode 100644 src/main/java/moe/ymc/acron/s2c/response/EventOk.java delete mode 100644 src/main/java/moe/ymc/acron/serialization/Serializer.java delete mode 100644 src/main/resources/acron.mixins.json delete mode 100644 src/main/resources/fabric.mod.json (limited to 'src') diff --git a/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java b/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java deleted file mode 100644 index 51f05ff..0000000 --- a/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.gson.typeadapters; - -import com.google.gson.*; -import com.google.gson.reflect.TypeToken; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; - -import java.io.IOException; -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * Adapts values whose runtime type may differ from their declaration type. This - * is necessary when a field's type is not the same type that GSON should create - * when deserializing that field. For example, consider these types: - *
   {@code
- *   abstract class Shape {
- *     int x;
- *     int y;
- *   }
- *   class Circle extends Shape {
- *     int radius;
- *   }
- *   class Rectangle extends Shape {
- *     int width;
- *     int height;
- *   }
- *   class Diamond extends Shape {
- *     int width;
- *     int height;
- *   }
- *   class Drawing {
- *     Shape bottomShape;
- *     Shape topShape;
- *   }
- * }
- *

Without additional type information, the serialized JSON is ambiguous. Is - * the bottom shape in this drawing a rectangle or a diamond?

   {@code
- *   {
- *     "bottomShape": {
- *       "width": 10,
- *       "height": 5,
- *       "x": 0,
- *       "y": 0
- *     },
- *     "topShape": {
- *       "radius": 2,
- *       "x": 4,
- *       "y": 1
- *     }
- *   }}
- * This class addresses this problem by adding type information to the - * serialized JSON and honoring that type information when the JSON is - * deserialized:
   {@code
- *   {
- *     "bottomShape": {
- *       "type": "Diamond",
- *       "width": 10,
- *       "height": 5,
- *       "x": 0,
- *       "y": 0
- *     },
- *     "topShape": {
- *       "type": "Circle",
- *       "radius": 2,
- *       "x": 4,
- *       "y": 1
- *     }
- *   }}
- * Both the type field name ({@code "type"}) and the type labels ({@code - * "Rectangle"}) are configurable. - * - *

Registering Types

- * Create a {@code RuntimeTypeAdapterFactory} by passing the base type and type field - * name to the {@link #of} factory method. If you don't supply an explicit type - * field name, {@code "type"} will be used.
   {@code
- *   RuntimeTypeAdapterFactory shapeAdapterFactory
- *       = RuntimeTypeAdapterFactory.of(Shape.class, "type");
- * }
- * Next register all of your subtypes. Every subtype must be explicitly - * registered. This protects your application from injection attacks. If you - * don't supply an explicit type label, the type's simple name will be used. - *
   {@code
- *   shapeAdapterFactory.registerSubtype(Rectangle.class, "Rectangle");
- *   shapeAdapterFactory.registerSubtype(Circle.class, "Circle");
- *   shapeAdapterFactory.registerSubtype(Diamond.class, "Diamond");
- * }
- * Finally, register the type adapter factory in your application's GSON builder: - *
   {@code
- *   Gson gson = new GsonBuilder()
- *       .registerTypeAdapterFactory(shapeAdapterFactory)
- *       .create();
- * }
- * Like {@code GsonBuilder}, this API supports chaining:
   {@code
- *   RuntimeTypeAdapterFactory shapeAdapterFactory = RuntimeTypeAdapterFactory.of(Shape.class)
- *       .registerSubtype(Rectangle.class)
- *       .registerSubtype(Circle.class)
- *       .registerSubtype(Diamond.class);
- * }
- * - *

Serialization and deserialization

- * In order to serialize and deserialize a polymorphic object, - * you must specify the base type explicitly. - *
   {@code
- *   Diamond diamond = new Diamond();
- *   String json = gson.toJson(diamond, Shape.class);
- * }
- * And then: - *
   {@code
- *   Shape shape = gson.fromJson(json, Shape.class);
- * }
- */ -public final class RuntimeTypeAdapterFactory implements TypeAdapterFactory { - private final Class baseType; - private final String typeFieldName; - private final Map> labelToSubtype = new LinkedHashMap<>(); - private final Map, String> subtypeToLabel = new LinkedHashMap<>(); - private final boolean maintainType; - - private RuntimeTypeAdapterFactory(Class baseType, String typeFieldName, boolean maintainType) { - if (typeFieldName == null || baseType == null) { - throw new NullPointerException(); - } - this.baseType = baseType; - this.typeFieldName = typeFieldName; - this.maintainType = maintainType; - } - - /** - * Creates a new runtime type adapter using for {@code baseType} using {@code - * typeFieldName} as the type field name. Type field names are case sensitive. - * {@code maintainType} flag decide if the type will be stored in pojo or not. - */ - public static RuntimeTypeAdapterFactory of(Class baseType, String typeFieldName, boolean maintainType) { - return new RuntimeTypeAdapterFactory<>(baseType, typeFieldName, maintainType); - } - - /** - * Creates a new runtime type adapter using for {@code baseType} using {@code - * typeFieldName} as the type field name. Type field names are case sensitive. - */ - public static RuntimeTypeAdapterFactory of(Class baseType, String typeFieldName) { - return new RuntimeTypeAdapterFactory<>(baseType, typeFieldName, false); - } - - /** - * Creates a new runtime type adapter for {@code baseType} using {@code "type"} as - * the type field name. - */ - public static RuntimeTypeAdapterFactory of(Class baseType) { - return new RuntimeTypeAdapterFactory<>(baseType, "type", false); - } - - /** - * Registers {@code type} identified by {@code label}. Labels are case - * sensitive. - * - * @throws IllegalArgumentException if either {@code type} or {@code label} - * have already been registered on this type adapter. - */ - public RuntimeTypeAdapterFactory registerSubtype(Class type, String label) { - if (type == null || label == null) { - throw new NullPointerException(); - } - if (subtypeToLabel.containsKey(type) || labelToSubtype.containsKey(label)) { - throw new IllegalArgumentException("types and labels must be unique"); - } - labelToSubtype.put(label, type); - subtypeToLabel.put(type, label); - return this; - } - - /** - * Registers {@code type} identified by its {@link Class#getSimpleName simple - * name}. Labels are case sensitive. - * - * @throws IllegalArgumentException if either {@code type} or its simple name - * have already been registered on this type adapter. - */ - public RuntimeTypeAdapterFactory registerSubtype(Class type) { - return registerSubtype(type, type.getSimpleName()); - } - - @Override - public TypeAdapter create(Gson gson, TypeToken type) { - // Workaround found at https://github.com/google/gson/issues/712#issuecomment-148955110 - if (null == type || !baseType.isAssignableFrom(type.getRawType())) { - // if (type.getRawType() != baseType) { - return null; - } - - final TypeAdapter jsonElementAdapter = gson.getAdapter(JsonElement.class); - final Map> labelToDelegate = new LinkedHashMap<>(); - final Map, TypeAdapter> subtypeToDelegate = new LinkedHashMap<>(); - for (Map.Entry> entry : labelToSubtype.entrySet()) { - TypeAdapter delegate = gson.getDelegateAdapter(this, TypeToken.get(entry.getValue())); - labelToDelegate.put(entry.getKey(), delegate); - subtypeToDelegate.put(entry.getValue(), delegate); - } - - return new TypeAdapter() { - @Override public R read(JsonReader in) throws IOException { - JsonElement jsonElement = jsonElementAdapter.read(in); - JsonElement labelJsonElement; - if (maintainType) { - labelJsonElement = jsonElement.getAsJsonObject().get(typeFieldName); - } else { - labelJsonElement = jsonElement.getAsJsonObject().remove(typeFieldName); - } - - if (labelJsonElement == null) { - throw new JsonParseException("cannot deserialize " + baseType - + " because it does not define a field named " + typeFieldName); - } - String label = labelJsonElement.getAsString(); - @SuppressWarnings("unchecked") // registration requires that subtype extends T - TypeAdapter delegate = (TypeAdapter) labelToDelegate.get(label); - if (delegate == null) { - throw new JsonParseException("cannot deserialize " + baseType + " subtype named " - + label + "; did you forget to register a subtype?"); - } - return delegate.fromJsonTree(jsonElement); - } - - @Override public void write(JsonWriter out, R value) throws IOException { - Class srcType = value.getClass(); - String label = subtypeToLabel.get(srcType); - @SuppressWarnings("unchecked") // registration requires that subtype extends T - TypeAdapter delegate = (TypeAdapter) subtypeToDelegate.get(srcType); - if (delegate == null) { - throw new JsonParseException("cannot serialize " + srcType.getName() - + "; did you forget to register a subtype?"); - } - JsonObject jsonObject = delegate.toJsonTree(value).getAsJsonObject(); - - if (maintainType) { - jsonElementAdapter.write(out, jsonObject); - return; - } - - JsonObject clone = new JsonObject(); - - if (jsonObject.has(typeFieldName)) { - throw new JsonParseException("cannot serialize " + srcType.getName() - + " because it already defines a field named " + typeFieldName); - } - clone.add(typeFieldName, new JsonPrimitive(label)); - - for (Map.Entry e : jsonObject.entrySet()) { - clone.add(e.getKey(), e.getValue()); - } - jsonElementAdapter.write(out, clone); - } - }.nullSafe(); - } -} diff --git a/src/main/java/moe/ymc/acron/Acron.java b/src/main/java/moe/ymc/acron/Acron.java deleted file mode 100644 index d6f6214..0000000 --- a/src/main/java/moe/ymc/acron/Acron.java +++ /dev/null @@ -1,32 +0,0 @@ -package moe.ymc.acron; - -import moe.ymc.acron.config.Config; -import moe.ymc.acron.config.json.ConfigDeserializer; -import net.fabricmc.api.ModInitializer; -import net.fabricmc.loader.api.FabricLoader; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.io.IOException; -import java.nio.file.Path; - -public class Acron implements ModInitializer { - private static final Logger LOGGER = LogManager.getLogger(); - - @Override - public void onInitialize() { - LOGGER.debug("onInitialize"); - try { - final Path config = FabricLoader - .getInstance().getConfigDir() - .resolve("acron.json"); - if (!config.toFile().exists()) { - throw new IllegalStateException("Cannot find config/acron.json."); - } - final Config cfg = ConfigDeserializer.deserialize(config.toFile(), true); - Config.setGlobalConfig(cfg); - } catch (IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/src/main/java/moe/ymc/acron/MinecraftServerHolder.java b/src/main/java/moe/ymc/acron/MinecraftServerHolder.java deleted file mode 100644 index f522884..0000000 --- a/src/main/java/moe/ymc/acron/MinecraftServerHolder.java +++ /dev/null @@ -1,28 +0,0 @@ -package moe.ymc.acron; - -import net.minecraft.server.dedicated.MinecraftDedicatedServer; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.NotNull; - -public class MinecraftServerHolder { - private static final Logger LOGGER = LogManager.getLogger(); - public static MinecraftDedicatedServer server; - - public static void setServer(@NotNull MinecraftDedicatedServer server) { - if (MinecraftServerHolder.server != null) { - throw new IllegalStateException(); - } - LOGGER.debug("Got MinecraftDedicatedServer on thread {}.", - Thread.currentThread().getName()); - MinecraftServerHolder.server = server; - } - - public static @NotNull MinecraftDedicatedServer getServer() { - if (server == null) { - throw new IllegalStateException(String.format("[%s] getServer() called before a server is ready.", - Thread.currentThread().getName())); - } - return server; - } -} diff --git a/src/main/java/moe/ymc/acron/auth/Action.java b/src/main/java/moe/ymc/acron/auth/Action.java deleted file mode 100644 index 17d29a3..0000000 --- a/src/main/java/moe/ymc/acron/auth/Action.java +++ /dev/null @@ -1,10 +0,0 @@ -package moe.ymc.acron.auth; - -import com.google.gson.annotations.SerializedName; - -public enum Action { - @SerializedName("allow") - ALLOW, - @SerializedName("deny") - DENY -} diff --git a/src/main/java/moe/ymc/acron/auth/Client.java b/src/main/java/moe/ymc/acron/auth/Client.java deleted file mode 100644 index 2124ad4..0000000 --- a/src/main/java/moe/ymc/acron/auth/Client.java +++ /dev/null @@ -1,9 +0,0 @@ -package moe.ymc.acron.auth; - -import org.jetbrains.annotations.NotNull; - -public record Client(@NotNull String id, - @NotNull String token, - @NotNull Action policyMode, - @NotNull Rule[] rules) { -} diff --git a/src/main/java/moe/ymc/acron/auth/PolicyChecker.java b/src/main/java/moe/ymc/acron/auth/PolicyChecker.java deleted file mode 100644 index 2ab7b97..0000000 --- a/src/main/java/moe/ymc/acron/auth/PolicyChecker.java +++ /dev/null @@ -1,42 +0,0 @@ -package moe.ymc.acron.auth; - -import moe.ymc.acron.jvav.Pair; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.NotNull; - -public class PolicyChecker { - private static final Logger LOGGER = LogManager.getLogger(); - - public static Pair check(@NotNull Client client, - @NotNull String command) { - final String commandToMatch = command.startsWith("/") ? - command.substring(1) : - command; - for (int i = 0; i < client.rules().length; i++) { - final Rule rule = client.rules()[i]; - if (rule.cmdPattern().matcher(commandToMatch).matches()) { - if (rule.action() == Action.DENY) { - LOGGER.warn("The command from client {}, `{}`, was " + - "explicitly denied by rule #{} (starting from 1).", - client.id(), - command, - i + 1); - } else { - LOGGER.warn("The command from client {}, `{}`, was " + - "explicitly allowed by rule #{} (starting from 1).", - client.id(), - command, - i + 1); - } - return new Pair<>(rule.action(), rule.display()); - } - } - LOGGER.warn("The command from client {}, `{}`, was " + - "implicitly {} by the default policy mode.", - client.id(), - command, - client.policyMode() == Action.ALLOW ? "allowed" : "denied"); - return new Pair<>(client.policyMode() == Action.ALLOW ? Action.ALLOW : Action.DENY, false); - } -} diff --git a/src/main/java/moe/ymc/acron/auth/Rule.java b/src/main/java/moe/ymc/acron/auth/Rule.java deleted file mode 100644 index 55ad0d7..0000000 --- a/src/main/java/moe/ymc/acron/auth/Rule.java +++ /dev/null @@ -1,10 +0,0 @@ -package moe.ymc.acron.auth; - -import org.jetbrains.annotations.NotNull; - -import java.util.regex.Pattern; - -public record Rule(@NotNull Pattern cmdPattern, - @NotNull Action action, - boolean display) { -} diff --git a/src/main/java/moe/ymc/acron/c2s/ReqCmd.java b/src/main/java/moe/ymc/acron/c2s/ReqCmd.java deleted file mode 100644 index 6f34b07..0000000 --- a/src/main/java/moe/ymc/acron/c2s/ReqCmd.java +++ /dev/null @@ -1,51 +0,0 @@ -package moe.ymc.acron.c2s; - -import com.google.gson.*; -import com.google.gson.annotations.SerializedName; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.lang.reflect.Type; - -public record ReqCmd(@SerializedName("id") int id, - @SerializedName("cmd") @NotNull String cmd, - @SerializedName("config") @Nullable ReqSetConfig config) - implements Request { - @Override - public void validate() { - if (cmd == null) { - throw new IllegalArgumentException("Property 'cmd' cannot be null."); - } - } - - @Override - public int getId() { - return id; - } - - public static class ReqCmdDeserializer implements JsonDeserializer { - @Override - public ReqCmd deserialize(JsonElement json, - Type typeOfT, - JsonDeserializationContext context) throws JsonParseException { - final JsonObject object = json.getAsJsonObject(); - final int id = object.has("id") ? - object.get("id").getAsInt() : - -1; - final String cmd = object.has("cmd") ? - object.get("cmd").getAsString() : - null; - // We cannot use context#deserialize here - // because RuntimeTypeAdapterFactory keeps kicking in - // and asking for the 'type' property - // which is obviously redundant for an inner field. - // Thus, I pass it directly to the deserializer - // to bypass the RuntimeTypeAdapterFactory. - final ReqSetConfig reqSetConfig = object.has("config") ? - new ReqSetConfig.ReqSetConfigDeserializer() - .deserialize(object.get("config"), ReqSetConfig.class, context) : - null; - return new ReqCmd(id, cmd, reqSetConfig); - } - } -} diff --git a/src/main/java/moe/ymc/acron/c2s/ReqSetConfig.java b/src/main/java/moe/ymc/acron/c2s/ReqSetConfig.java deleted file mode 100644 index fcddf35..0000000 --- a/src/main/java/moe/ymc/acron/c2s/ReqSetConfig.java +++ /dev/null @@ -1,63 +0,0 @@ -package moe.ymc.acron.c2s; - -import com.google.gson.*; -import com.google.gson.annotations.SerializedName; -import moe.ymc.acron.common.Vec2f; -import moe.ymc.acron.common.Vec3d; -import moe.ymc.acron.common.WorldKey; -import org.jetbrains.annotations.Nullable; - -import java.lang.reflect.Type; - -public record ReqSetConfig(@SerializedName("id") int id, - @SerializedName("world") @Nullable WorldKey world, - @SerializedName("pos") @Nullable Vec3d pos, - @SerializedName("rot") @Nullable Vec2f rot, - @SerializedName("name") @Nullable String name) - implements Request { - @Override - public void validate() { - } - - @Override - public int getId() { - return id; - } - - public static class ReqSetConfigDeserializer implements JsonDeserializer { - @Override - public ReqSetConfig deserialize(JsonElement json, - Type typeOfT, - JsonDeserializationContext context) throws JsonParseException { - final JsonObject object = json.getAsJsonObject(); - final int id = object.has("id") ? - object.get("id").getAsInt() : - -1; - final WorldKey world; - if (object.has("world")) { - world = context.deserialize(object.get("world"), WorldKey.class); - // https://stackoverflow.com/a/49574019 - if (world == null) { - throw new JsonParseException("Invalid world"); - } - } else { - world = null; - } - final Vec3d pos = object.has("pos") ? - context.deserialize(object.get("pos"), Vec3d.class) : - null; - final Vec2f rot = object.has("rot") ? - context.deserialize(object.get("rot"), Vec2f.class) : - null; - final String name = object.has("name") ? - object.get("name").getAsString() : - null; - return new ReqSetConfig(id, - world, - pos, - rot, - name); - } - } - -} \ No newline at end of file diff --git a/src/main/java/moe/ymc/acron/c2s/Request.java b/src/main/java/moe/ymc/acron/c2s/Request.java deleted file mode 100644 index af81705..0000000 --- a/src/main/java/moe/ymc/acron/c2s/Request.java +++ /dev/null @@ -1,6 +0,0 @@ -package moe.ymc.acron.c2s; - -public interface Request { - int getId(); - void validate() throws IllegalArgumentException; -} diff --git a/src/main/java/moe/ymc/acron/cmd/CmdOut.java b/src/main/java/moe/ymc/acron/cmd/CmdOut.java deleted file mode 100644 index 55eadf1..0000000 --- a/src/main/java/moe/ymc/acron/cmd/CmdOut.java +++ /dev/null @@ -1,53 +0,0 @@ -package moe.ymc.acron.cmd; - -import io.netty.channel.Channel; -import moe.ymc.acron.s2c.response.EventCmdOut; -import moe.ymc.acron.serialization.Serializer; -import net.minecraft.server.command.CommandOutput; -import net.minecraft.text.Text; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.NotNull; - -import java.util.UUID; - -public class CmdOut implements CommandOutput { - private static final Logger LOGGER = LogManager.getLogger(); - - private final @NotNull Channel channel; - private final int id; - private final boolean display; - - public CmdOut(@NotNull Channel channel, - int id, - boolean display) { - this.channel = channel; - this.id = id; - this.display = display; - } - - @Override - public void sendSystemMessage(Text message, UUID sender) { - LOGGER.debug("sendSystemMessage[{}]: {}", - id, - message.getString()); - channel.writeAndFlush( - Serializer.serialize(new EventCmdOut(id, sender, message.getString())) - ); - } - - @Override - public boolean shouldReceiveFeedback() { - return true; - } - - @Override - public boolean shouldTrackOutput() { - return true; - } - - @Override - public boolean shouldBroadcastConsoleToOps() { - return display; - } -} diff --git a/src/main/java/moe/ymc/acron/cmd/CmdQueue.java b/src/main/java/moe/ymc/acron/cmd/CmdQueue.java deleted file mode 100644 index 3c49143..0000000 --- a/src/main/java/moe/ymc/acron/cmd/CmdQueue.java +++ /dev/null @@ -1,17 +0,0 @@ -package moe.ymc.acron.cmd; - -import io.netty.channel.Channel; -import moe.ymc.acron.MinecraftServerHolder; -import moe.ymc.acron.net.ClientConfiguration; -import org.jetbrains.annotations.NotNull; - -public class CmdQueue { - public static void enqueue(int id, - boolean display, - @NotNull final Channel channel, - @NotNull final ClientConfiguration configuration, - @NotNull final String command) { - MinecraftServerHolder.getServer().enqueueCommand(command, - new CmdSrc(channel, id, display, configuration, MinecraftServerHolder.getServer())); - } -} diff --git a/src/main/java/moe/ymc/acron/cmd/CmdResConsumer.java b/src/main/java/moe/ymc/acron/cmd/CmdResConsumer.java deleted file mode 100644 index d22b77e..0000000 --- a/src/main/java/moe/ymc/acron/cmd/CmdResConsumer.java +++ /dev/null @@ -1,33 +0,0 @@ -package moe.ymc.acron.cmd; - -import com.mojang.brigadier.ResultConsumer; -import com.mojang.brigadier.context.CommandContext; -import io.netty.channel.Channel; -import moe.ymc.acron.s2c.response.EventCmdRes; -import moe.ymc.acron.serialization.Serializer; -import net.minecraft.server.command.ServerCommandSource; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.NotNull; - -public class CmdResConsumer implements ResultConsumer { - private static final Logger LOGGER = LogManager.getLogger(); - - private final @NotNull Channel channel; - private final int id; - - public CmdResConsumer(@NotNull Channel channel, - int id) { - this.channel = channel; - this.id = id; - } - - @Override - public void onCommandComplete(CommandContext context, boolean success, int result) { - LOGGER.debug("onCommandComplete[{}]: {} {}", - id, - success, - result); - channel.writeAndFlush(Serializer.serialize(new EventCmdRes(id, success, result))); - } -} diff --git a/src/main/java/moe/ymc/acron/cmd/CmdSrc.java b/src/main/java/moe/ymc/acron/cmd/CmdSrc.java deleted file mode 100644 index 983b4ed..0000000 --- a/src/main/java/moe/ymc/acron/cmd/CmdSrc.java +++ /dev/null @@ -1,34 +0,0 @@ -package moe.ymc.acron.cmd; - -import io.netty.channel.Channel; -import moe.ymc.acron.net.ClientConfiguration; -import net.minecraft.command.argument.EntityAnchorArgumentType; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.text.LiteralText; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.NotNull; - -class CmdSrc extends ServerCommandSource { - private static final Logger LOGGER = LogManager.getLogger(); - - public CmdSrc(@NotNull Channel channel, - int id, - boolean display, - @NotNull ClientConfiguration configuration, - @NotNull MinecraftServer server) { - super(new CmdOut(channel, id, display), - configuration.pos(), - configuration.rot(), - configuration.world(), - 4, - configuration.name(), - new LiteralText(configuration.name()), - server, - null, - false, - new CmdResConsumer(channel, id), - EntityAnchorArgumentType.EntityAnchor.FEET); - } -} diff --git a/src/main/java/moe/ymc/acron/common/Vec2f.java b/src/main/java/moe/ymc/acron/common/Vec2f.java deleted file mode 100644 index 5ab3dfd..0000000 --- a/src/main/java/moe/ymc/acron/common/Vec2f.java +++ /dev/null @@ -1,25 +0,0 @@ -package moe.ymc.acron.common; - -import com.google.gson.*; -import com.google.gson.annotations.SerializedName; - -import java.lang.reflect.Type; - -public record Vec2f(@SerializedName("x") float x, - @SerializedName("y") float y) { - public static class Vec2fDeserializer implements JsonDeserializer { - @Override - public Vec2f deserialize(JsonElement json, - Type typeOfT, - JsonDeserializationContext context) throws JsonParseException { - final JsonObject object = json.getAsJsonObject(); - final float x = object.has("x") ? - object.get("x").getAsFloat() : - 0.0f; - final float y = object.has("y") ? - object.get("y").getAsFloat() : - 0.0f; - return new Vec2f(x, y); - } - } -} \ No newline at end of file diff --git a/src/main/java/moe/ymc/acron/common/Vec3d.java b/src/main/java/moe/ymc/acron/common/Vec3d.java deleted file mode 100644 index 593019f..0000000 --- a/src/main/java/moe/ymc/acron/common/Vec3d.java +++ /dev/null @@ -1,34 +0,0 @@ -package moe.ymc.acron.common; - -import com.google.gson.*; -import com.google.gson.annotations.SerializedName; -import org.jetbrains.annotations.NotNull; - -import java.lang.reflect.Type; - -public record Vec3d(@SerializedName("x") double x, - @SerializedName("y") double y, - @SerializedName("z") double z) { - public Vec3d(@NotNull net.minecraft.util.math.Vec3d vec3d) { - this(vec3d.x, vec3d.y, vec3d.z); - } - - public static class Vec3dDeserializer implements JsonDeserializer { - @Override - public Vec3d deserialize(JsonElement json, - Type typeOfT, - JsonDeserializationContext context) throws JsonParseException { - final JsonObject object = json.getAsJsonObject(); - final double x = object.has("x") ? - object.get("x").getAsDouble() : - 0.0; - final double y = object.has("y") ? - object.get("y").getAsDouble() : - 0.0; - final double z = object.has("z") ? - object.get("z").getAsDouble() : - 0.0; - return new Vec3d(x, y, z); - } - } -} \ No newline at end of file diff --git a/src/main/java/moe/ymc/acron/common/WorldKey.java b/src/main/java/moe/ymc/acron/common/WorldKey.java deleted file mode 100644 index fa10d54..0000000 --- a/src/main/java/moe/ymc/acron/common/WorldKey.java +++ /dev/null @@ -1,35 +0,0 @@ -package moe.ymc.acron.common; - -import com.google.gson.annotations.SerializedName; -import net.minecraft.util.Identifier; -import net.minecraft.world.dimension.DimensionType; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public enum WorldKey { - @SerializedName("overworld") - OVERWORLD, - @SerializedName("nether") - NETHER, - @SerializedName("end") - END; - - private static final Logger LOGGER = LogManager.getLogger(); - - public static @Nullable WorldKey create(@NotNull Identifier identifier) { - if (identifier.equals(DimensionType.OVERWORLD_ID)) { - return OVERWORLD; - } else if (identifier.equals(DimensionType.THE_NETHER_ID)) { - return NETHER; - } else if (identifier.equals(DimensionType.THE_END_ID)) { - return END; - } else { - LOGGER.warn("Unknown world {}:{}. Returning NULL to the client.", - identifier.getNamespace(), - identifier.getPath()); - return null; - } - } -} \ No newline at end of file diff --git a/src/main/java/moe/ymc/acron/config/Config.java b/src/main/java/moe/ymc/acron/config/Config.java deleted file mode 100644 index 3749c25..0000000 --- a/src/main/java/moe/ymc/acron/config/Config.java +++ /dev/null @@ -1,30 +0,0 @@ -package moe.ymc.acron.config; - -import moe.ymc.acron.auth.Client; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.NotNull; - -import java.net.InetAddress; -import java.util.Map; - -public record Config(@NotNull InetAddress address, - int port, - boolean useNativeTransport, - @NotNull Map clients) { - private static final Logger LOGGER = LogManager.getLogger(); - private static Config globalConfig; - - @NotNull - public static Config getGlobalConfig() { - return globalConfig; - } - - public static void setGlobalConfig(@NotNull Config globalConfig) { - Config.globalConfig = globalConfig; - LOGGER.info("Config loaded with {} clients. Listening on {}:{}.", - globalConfig.clients.size(), - globalConfig.address.toString(), - globalConfig.port); - } -} \ No newline at end of file diff --git a/src/main/java/moe/ymc/acron/config/ConfigReloadCmd.java b/src/main/java/moe/ymc/acron/config/ConfigReloadCmd.java deleted file mode 100644 index 2774c4d..0000000 --- a/src/main/java/moe/ymc/acron/config/ConfigReloadCmd.java +++ /dev/null @@ -1,41 +0,0 @@ -package moe.ymc.acron.config; - -import com.mojang.brigadier.Command; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import moe.ymc.acron.config.json.ConfigDeserializationException; -import moe.ymc.acron.config.json.ConfigDeserializer; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.text.LiteralText; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.io.IOException; -import java.nio.file.Path; - -public class ConfigReloadCmd implements Command { - private static final Logger LOGGER = LogManager.getLogger(); - - @Override - public int run(CommandContext context) throws CommandSyntaxException { - LOGGER.info("Reloading rules."); - try { - final Path config = FabricLoader - .getInstance().getConfigDir() - .resolve("acron.json"); - if (!config.toFile().exists()) { - throw new IllegalStateException("Cannot find config/acron.json."); - } - final Config cfg = ConfigDeserializer.deserialize(config.toFile(), false); - Config.setGlobalConfig(cfg); - context.getSource().sendFeedback(new LiteralText("Rules reloaded."), true); - return 0; - } catch (IOException | ConfigDeserializationException e) { - LOGGER.error("Cannot reload config.", e); - context.getSource().sendError(new LiteralText("Cannot reload rules: " + - e.getMessage())); - return 1; - } - } -} diff --git a/src/main/java/moe/ymc/acron/config/json/Client.java b/src/main/java/moe/ymc/acron/config/json/Client.java deleted file mode 100644 index 4d31308..0000000 --- a/src/main/java/moe/ymc/acron/config/json/Client.java +++ /dev/null @@ -1,45 +0,0 @@ -package moe.ymc.acron.config.json; - -import com.google.gson.annotations.SerializedName; -import moe.ymc.acron.auth.Action; -import org.jetbrains.annotations.NotNull; - -import java.util.List; - -class Client implements ConfigJsonObject { - @SerializedName("id") - private final String id; - - @SerializedName("token") - private final String token; - - @SerializedName("policy_mode") - private final Action policyMode; - - @SerializedName("rules") - private final List rules; - - private Client(String id, - String token, - Action policyMode, - List rules) { - this.id = id; - this.token = token; - this.policyMode = policyMode; - this.rules = rules; - } - - @Override - public @NotNull moe.ymc.acron.auth.Client create(boolean startup) throws ConfigDeserializationException { - if (id == null || id.trim().equals("") || - token == null || token.trim().equals("")) { - throw new ConfigDeserializationException(".clients[].id or .clients[].token is not supplied."); - } - return new moe.ymc.acron.auth.Client(id, - token, - policyMode == null ? Action.DENY : policyMode, - rules == null ? new moe.ymc.acron.auth.Rule[]{} : - rules.stream().map(rule -> rule.create(startup)).toList() - .toArray(new moe.ymc.acron.auth.Rule[rules.size()])); - } -} diff --git a/src/main/java/moe/ymc/acron/config/json/Config.java b/src/main/java/moe/ymc/acron/config/json/Config.java deleted file mode 100644 index e8c5a83..0000000 --- a/src/main/java/moe/ymc/acron/config/json/Config.java +++ /dev/null @@ -1,103 +0,0 @@ -package moe.ymc.acron.config.json; - -import com.google.gson.annotations.SerializedName; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.NotNull; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -class Config implements ConfigJsonObject { - private static final Logger LOGGER = LogManager.getLogger(); - - @SerializedName("listen") - private final String listen; - - @SerializedName("port") - private final Integer port; - - @SerializedName("native_transport") - private final boolean nativeTransport; - - @SerializedName("clients") - private final List clients; - - private Config(String listen, - Integer port, - boolean nativeTransport, - List clients) { - this.listen = listen; - this.port = port; - this.nativeTransport = nativeTransport; - this.clients = clients; - } - - @Override - public @NotNull moe.ymc.acron.config.Config create(boolean startup) throws ConfigDeserializationException { - final InetAddress address; - final int p; - final boolean nt; - if (!startup) { - address = moe.ymc.acron.config.Config.getGlobalConfig().address(); - p = moe.ymc.acron.config.Config.getGlobalConfig().port(); - nt = moe.ymc.acron.config.Config.getGlobalConfig().useNativeTransport(); - } else { - if (listen == null || listen.trim().equals("")) { - address = InetAddress.getLoopbackAddress(); - } else { - try { - address = InetAddress.getByName(listen); - } catch (UnknownHostException e) { - throw new ConfigDeserializationException("Cannot parse address: " + e.getMessage(), - true); - } - } - if (port == null) { - p = 25575; - } else { - if (port < 0 || port > 65535) { - throw new ConfigDeserializationException("The port is out of range.", true); - } - p = port; - } - nt = nativeTransport; - } - - - Map map; - try { - if (clients != null) { - map = clients.stream() - .collect(Collectors. - toMap(client -> client.create(startup).id(), - client -> client.create(startup))); - } else { - map = new HashMap<>(0); - } - } catch (IllegalStateException e) { - // Collision. - LOGGER.error("Duplicate clients with the same ID in the Acron configuration. All clients are ignored. " + - "Fix the configuration and reload.", e); - if (!startup) { - throw new ConfigDeserializationException("Duplicate clients with the same ID: " + e.getMessage()); - } - map = new HashMap<>(0); - } catch (ConfigDeserializationException e) { - LOGGER.error("Cannot parse the Acron configuration. All clients are ignored. " + - "Fix the configuration and reload.", e); - if (!startup) { - throw e; - } - map = new HashMap<>(0); - } - return new moe.ymc.acron.config.Config(address, - p, - nt, - map); - } -} diff --git a/src/main/java/moe/ymc/acron/config/json/ConfigDeserializationException.java b/src/main/java/moe/ymc/acron/config/json/ConfigDeserializationException.java deleted file mode 100644 index baf5b35..0000000 --- a/src/main/java/moe/ymc/acron/config/json/ConfigDeserializationException.java +++ /dev/null @@ -1,18 +0,0 @@ -package moe.ymc.acron.config.json; - -public class ConfigDeserializationException extends RuntimeException { - private final boolean fetal; - - public ConfigDeserializationException(String message) { - this(message, false); - } - - public ConfigDeserializationException(String message, boolean fetal) { - super(message); - this.fetal = fetal; - } - - public boolean isFetal() { - return fetal; - } -} diff --git a/src/main/java/moe/ymc/acron/config/json/ConfigDeserializer.java b/src/main/java/moe/ymc/acron/config/json/ConfigDeserializer.java deleted file mode 100644 index e91b355..0000000 --- a/src/main/java/moe/ymc/acron/config/json/ConfigDeserializer.java +++ /dev/null @@ -1,27 +0,0 @@ -package moe.ymc.acron.config.json; - -import com.google.gson.Gson; -import moe.ymc.acron.config.Config; -import org.jetbrains.annotations.NotNull; - -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.Reader; - -public class ConfigDeserializer { - public static @NotNull Config deserialize(@NotNull File file, boolean startup) - throws ConfigDeserializationException, IOException { - final Reader reader = new FileReader(file); - final moe.ymc.acron.config.json.Config config; - try { - config = new Gson() - .fromJson(reader, moe.ymc.acron.config.json.Config.class); - } catch (Throwable e) { - throw new ConfigDeserializationException("Cannot parse JSON: " + e.getMessage(), - true); - } - reader.close(); - return config.create(startup); - } -} diff --git a/src/main/java/moe/ymc/acron/config/json/ConfigJsonObject.java b/src/main/java/moe/ymc/acron/config/json/ConfigJsonObject.java deleted file mode 100644 index 0efd9a9..0000000 --- a/src/main/java/moe/ymc/acron/config/json/ConfigJsonObject.java +++ /dev/null @@ -1,7 +0,0 @@ -package moe.ymc.acron.config.json; - -import org.jetbrains.annotations.NotNull; - -public interface ConfigJsonObject { - @NotNull T create(boolean startup) throws ConfigDeserializationException; -} diff --git a/src/main/java/moe/ymc/acron/config/json/Rule.java b/src/main/java/moe/ymc/acron/config/json/Rule.java deleted file mode 100644 index 114e17d..0000000 --- a/src/main/java/moe/ymc/acron/config/json/Rule.java +++ /dev/null @@ -1,35 +0,0 @@ -package moe.ymc.acron.config.json; - -import com.google.gson.annotations.SerializedName; -import moe.ymc.acron.auth.Action; -import org.jetbrains.annotations.NotNull; - -import java.util.regex.Pattern; - -class Rule implements ConfigJsonObject { - @SerializedName("regex") - private final String regex; - - @SerializedName("action") - private final Action action; - - @SerializedName("display") - private final boolean display; - - private Rule(String regex, - Action action, - boolean display) { - this.regex = regex; - this.action = action; - this.display = display; - } - - public @NotNull moe.ymc.acron.auth.Rule create(boolean startup) throws ConfigDeserializationException { - if (regex == null || regex.trim().equals("") || - action == null) throw new ConfigDeserializationException(".clients.[]rules.regex or .clients.[]rules.action is" + - "not specified."); - return new moe.ymc.acron.auth.Rule(Pattern.compile(regex), - action, - display); - } -} diff --git a/src/main/java/moe/ymc/acron/jvav/Pair.java b/src/main/java/moe/ymc/acron/jvav/Pair.java deleted file mode 100644 index 29b83dc..0000000 --- a/src/main/java/moe/ymc/acron/jvav/Pair.java +++ /dev/null @@ -1,4 +0,0 @@ -package moe.ymc.acron.jvav; - -public record Pair(L l, R r) { -} \ No newline at end of file diff --git a/src/main/java/moe/ymc/acron/mixin/CommandManagerMixin.java b/src/main/java/moe/ymc/acron/mixin/CommandManagerMixin.java deleted file mode 100644 index 9aaed2e..0000000 --- a/src/main/java/moe/ymc/acron/mixin/CommandManagerMixin.java +++ /dev/null @@ -1,38 +0,0 @@ -package moe.ymc.acron.mixin; - -import com.mojang.brigadier.CommandDispatcher; -import moe.ymc.acron.config.ConfigReloadCmd; -import net.minecraft.server.command.CommandManager; -import net.minecraft.server.command.ServerCommandSource; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import static net.minecraft.server.command.CommandManager.literal; - - -@Mixin(CommandManager.class) -public abstract class CommandManagerMixin { - private static final Logger AC_LOGGER = LogManager.getLogger(); - - @Shadow - @Final - private CommandDispatcher dispatcher; - - @Inject(method = "", at = @At("RETURN")) - private void onRegister(CommandManager.RegistrationEnvironment arg, CallbackInfo ci) { - AC_LOGGER.debug("onRegister"); - dispatcher.register( - literal("acron").requires(player -> player.hasPermissionLevel(4)).then( - literal("rule").then( - literal("update") - .executes(new ConfigReloadCmd())) - ) - ); - } -} diff --git a/src/main/java/moe/ymc/acron/mixin/LivingEntityMixin.java b/src/main/java/moe/ymc/acron/mixin/LivingEntityMixin.java deleted file mode 100644 index 9e16569..0000000 --- a/src/main/java/moe/ymc/acron/mixin/LivingEntityMixin.java +++ /dev/null @@ -1,41 +0,0 @@ -package moe.ymc.acron.mixin; - -import moe.ymc.acron.s2c.Entity; -import moe.ymc.acron.s2c.EventQueue; -import moe.ymc.acron.s2c.event.EventEntityDeath; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.damage.DamageSource; -import net.minecraft.entity.damage.DamageTracker; -import net.minecraft.world.World; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(LivingEntity.class) -public abstract class LivingEntityMixin extends net.minecraft.entity.Entity { - private static final Logger AC_LOGGER = LogManager.getLogger(); - - @Shadow public abstract DamageTracker getDamageTracker(); - - public LivingEntityMixin(EntityType type, World world) { - super(type, world); - } - - // The original onDeath() will call getDamageTracker().update(), - // which clears all recent damages, making the getDeathMessage() - // output always generic. - // Thus, we need to use @At("HEAD") to get the injection called - // before it does anything else. - @Inject(at = @At("HEAD"), method = "onDeath") - public void onDeath(DamageSource source, CallbackInfo ci) { - AC_LOGGER.debug("onDeath[{}]", - getUuid()); - EventQueue.enqueue(new EventEntityDeath(new Entity(this), - getDamageTracker().getDeathMessage().getString())); - } -} \ No newline at end of file diff --git a/src/main/java/moe/ymc/acron/mixin/MinecraftDedicatedServerMixin.java b/src/main/java/moe/ymc/acron/mixin/MinecraftDedicatedServerMixin.java deleted file mode 100644 index 32d2fbf..0000000 --- a/src/main/java/moe/ymc/acron/mixin/MinecraftDedicatedServerMixin.java +++ /dev/null @@ -1,21 +0,0 @@ -package moe.ymc.acron.mixin; - -import moe.ymc.acron.MinecraftServerHolder; -import net.minecraft.server.dedicated.MinecraftDedicatedServer; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(MinecraftDedicatedServer.class) -public class MinecraftDedicatedServerMixin { - private static final Logger AC_LOGGER = LogManager.getLogger(); - - @Inject(at = @At("RETURN"), method = "") - private void init(CallbackInfo info) { - AC_LOGGER.debug("init"); - MinecraftServerHolder.setServer((MinecraftDedicatedServer) (Object) this); - } -} diff --git a/src/main/java/moe/ymc/acron/mixin/MinecraftServerMixin.java b/src/main/java/moe/ymc/acron/mixin/MinecraftServerMixin.java deleted file mode 100644 index cb813b4..0000000 --- a/src/main/java/moe/ymc/acron/mixin/MinecraftServerMixin.java +++ /dev/null @@ -1,33 +0,0 @@ -package moe.ymc.acron.mixin; - -import moe.ymc.acron.s2c.EventQueue; -import moe.ymc.acron.s2c.event.EventLagging; -import net.minecraft.server.MinecraftServer; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(MinecraftServer.class) -public class MinecraftServerMixin { - private static final Logger AC_LOGGER = LogManager.getLogger(); - - @Redirect(method = "runServer()V", - remap = false, - at = @At(value = "INVOKE", - target = "Lorg/apache/logging/log4j/Logger;warn(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V")) - private void startServer(Logger instance, String s, Object o1, Object o2) { - instance.warn(s, o1, o2); - if (s.equals("Can't keep up! " + - "Is the server overloaded? " + - "Running {}ms or {} ticks behind") && - o1 instanceof Long && - o2 instanceof Long) { - AC_LOGGER.debug("Lag: {}ms, {} ticks", - o1, - o2); - EventQueue.enqueue(new EventLagging((long) o1, (long) o2)); - } - } -} diff --git a/src/main/java/moe/ymc/acron/mixin/ServerLoginNetworkHandlerMixin.java b/src/main/java/moe/ymc/acron/mixin/ServerLoginNetworkHandlerMixin.java deleted file mode 100644 index 94a48b5..0000000 --- a/src/main/java/moe/ymc/acron/mixin/ServerLoginNetworkHandlerMixin.java +++ /dev/null @@ -1,47 +0,0 @@ -package moe.ymc.acron.mixin; - -import com.mojang.authlib.GameProfile; -import moe.ymc.acron.s2c.Entity; -import moe.ymc.acron.s2c.EventQueue; -import moe.ymc.acron.s2c.event.EventDisconnected; -import moe.ymc.acron.s2c.event.EventPlayerJoined; -import net.minecraft.network.ClientConnection; -import net.minecraft.server.network.ServerLoginNetworkHandler; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.Text; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(ServerLoginNetworkHandler.class) -public class ServerLoginNetworkHandlerMixin { - private static final Logger AC_LOGGER = LogManager.getLogger(); - - @Shadow - @Nullable - GameProfile profile; - - @Shadow - @Final - public ClientConnection connection; - - @Inject(at = @At("RETURN"), method = "onDisconnected") - private void onDisconnected(Text reason, CallbackInfo ci) { - EventQueue.enqueue(new EventDisconnected(profile == null ? null : - new Entity(profile), - reason.getString())); - } - - @Inject(at = @At("RETURN"), method = "addToServer") - private void addToServer(ServerPlayerEntity entity, CallbackInfo ci) { - AC_LOGGER.debug("addToServer: {}", - entity.getUuid()); - EventQueue.enqueue(new EventPlayerJoined(new Entity(entity))); - } -} diff --git a/src/main/java/moe/ymc/acron/mixin/ServerNetworkIoMixin.java b/src/main/java/moe/ymc/acron/mixin/ServerNetworkIoMixin.java deleted file mode 100644 index f49914e..0000000 --- a/src/main/java/moe/ymc/acron/mixin/ServerNetworkIoMixin.java +++ /dev/null @@ -1,65 +0,0 @@ -package moe.ymc.acron.mixin; - -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.MultithreadEventLoopGroup; -import io.netty.channel.ServerChannel; -import io.netty.channel.epoll.Epoll; -import io.netty.channel.epoll.EpollServerSocketChannel; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import moe.ymc.acron.config.Config; -import moe.ymc.acron.net.AcronInitializer; -import net.minecraft.server.ServerNetworkIo; -import net.minecraft.util.Lazy; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.List; - -import static net.minecraft.server.ServerNetworkIo.EPOLL_CHANNEL; - -@Mixin(ServerNetworkIo.class) -public class ServerNetworkIoMixin { - private static final Logger AC_LOGGER = LogManager.getLogger(); - - @Shadow - @Final - private List channels; - - @Shadow - @Final - public static Lazy DEFAULT_CHANNEL; - - @Inject(at = @At("RETURN"), method = "") - private void init(CallbackInfo info) { - AC_LOGGER.debug("Adding Acron channel."); - Lazy group; - Class channel; - if (Epoll.isAvailable() && Config.getGlobalConfig().useNativeTransport()) { - channel = EpollServerSocketChannel.class; - group = EPOLL_CHANNEL; - AC_LOGGER.info("Using native transport."); - } else { - channel = NioServerSocketChannel.class; - group = DEFAULT_CHANNEL; - AC_LOGGER.info("Not using native transport due to " + - "it is either disabled in acron.json or not available."); - } - channels.add(new ServerBootstrap() - .channel(channel) - .childHandler(new AcronInitializer()) - .group(group.get()) - .localAddress(Config.getGlobalConfig().address(), - Config.getGlobalConfig().port()) - .bind() - .syncUninterruptibly()); - - } -} diff --git a/src/main/java/moe/ymc/acron/mixin/ServerPlayNetworkHandlerMixin.java b/src/main/java/moe/ymc/acron/mixin/ServerPlayNetworkHandlerMixin.java deleted file mode 100644 index 58bef78..0000000 --- a/src/main/java/moe/ymc/acron/mixin/ServerPlayNetworkHandlerMixin.java +++ /dev/null @@ -1,43 +0,0 @@ -package moe.ymc.acron.mixin; - -import moe.ymc.acron.s2c.Entity; -import moe.ymc.acron.s2c.EventQueue; -import moe.ymc.acron.s2c.event.EventDisconnected; -import moe.ymc.acron.s2c.event.EventPlayerMessage; -import net.minecraft.network.ClientConnection; -import net.minecraft.server.filter.TextStream; -import net.minecraft.server.network.ServerPlayNetworkHandler; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.Text; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(ServerPlayNetworkHandler.class) -public class ServerPlayNetworkHandlerMixin { - private static final Logger AC_LOGGER = LogManager.getLogger(); - - @Shadow - public ServerPlayerEntity player; - - @Shadow - @Final - public ClientConnection connection; - - @Inject(at = @At("RETURN"), method = "handleMessage") - private void handleMessage(TextStream.Message message, CallbackInfo ci) { - EventQueue.enqueue(new EventPlayerMessage(new Entity(player), - message.getRaw())); - } - - @Inject(at = @At("RETURN"), method = "onDisconnected") - private void onDisconnected(Text reason, CallbackInfo ci) { - EventQueue.enqueue(new EventDisconnected(new Entity(player), - reason.getString())); - } -} diff --git a/src/main/java/moe/ymc/acron/mixin/ServerPlayerEntityMixin.java b/src/main/java/moe/ymc/acron/mixin/ServerPlayerEntityMixin.java deleted file mode 100644 index 4c6758b..0000000 --- a/src/main/java/moe/ymc/acron/mixin/ServerPlayerEntityMixin.java +++ /dev/null @@ -1,32 +0,0 @@ -package moe.ymc.acron.mixin; - -import moe.ymc.acron.s2c.EventQueue; -import moe.ymc.acron.s2c.event.EventEntityDeath; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.damage.DamageSource; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.world.World; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(ServerPlayerEntity.class) -public abstract class ServerPlayerEntityMixin extends LivingEntity { - private static final Logger AC_LOGGER = LogManager.getLogger(); - - public ServerPlayerEntityMixin(EntityType entityType, World world) { - super(entityType, world); - } - - @Inject(at = @At("HEAD"), method = "onDeath") - public void onDeath(DamageSource source, CallbackInfo ci) { - AC_LOGGER.debug("onDeath: {}", - getUuid()); - EventQueue.enqueue(new EventEntityDeath(new moe.ymc.acron.s2c.Entity(this), - getDamageTracker().getDeathMessage().getString())); - } -} \ No newline at end of file diff --git a/src/main/java/moe/ymc/acron/net/AcronInitializer.java b/src/main/java/moe/ymc/acron/net/AcronInitializer.java deleted file mode 100644 index c9953e3..0000000 --- a/src/main/java/moe/ymc/acron/net/AcronInitializer.java +++ /dev/null @@ -1,25 +0,0 @@ -package moe.ymc.acron.net; - -import io.netty.channel.ChannelInitializer; -import io.netty.channel.socket.SocketChannel; -import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.codec.http.HttpServerCodec; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -/** - * A channel initializer for all Acron handlers. - */ -public class AcronInitializer extends ChannelInitializer { - private static final Logger LOGGER = LogManager.getLogger(); - - @Override - protected void initChannel(SocketChannel ch) throws Exception { - LOGGER.debug("initChannel"); - ch.pipeline() - .addLast(new HttpServerCodec()) - .addLast(new HttpObjectAggregator(65536)) - .addLast(new AuthHandler()) - ; - } -} diff --git a/src/main/java/moe/ymc/acron/net/Attributes.java b/src/main/java/moe/ymc/acron/net/Attributes.java deleted file mode 100644 index ddb0f5c..0000000 --- a/src/main/java/moe/ymc/acron/net/Attributes.java +++ /dev/null @@ -1,13 +0,0 @@ -package moe.ymc.acron.net; - -import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker; -import io.netty.util.AttributeKey; - -final class Attributes { - public static final AttributeKey ID = - AttributeKey.newInstance("CLENT_ID"); - public static final AttributeKey CONFIGURATION = - AttributeKey.newInstance("CLIENT_CONFIG"); - public static final AttributeKey HANDSHAKER = - AttributeKey.newInstance("HANDSHAKER"); -} diff --git a/src/main/java/moe/ymc/acron/net/AuthHandler.java b/src/main/java/moe/ymc/acron/net/AuthHandler.java deleted file mode 100644 index 3e42e14..0000000 --- a/src/main/java/moe/ymc/acron/net/AuthHandler.java +++ /dev/null @@ -1,98 +0,0 @@ -package moe.ymc.acron.net; - -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.handler.codec.http.*; -import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker; -import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory; -import moe.ymc.acron.auth.Client; -import moe.ymc.acron.config.Config; -import org.apache.commons.codec.digest.DigestUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -/** - * Handle handshake request and authentication. - * We cannot use WebSocketServerProtocolHandler because it does not allow - * us doing anything before handshaking. - */ -public class AuthHandler extends SimpleChannelInboundHandler { - private static final Logger LOGGER = LogManager.getLogger(); - - @Override - protected void channelRead0(ChannelHandlerContext ctx, HttpRequest msg) throws Exception { - LOGGER.debug("channelRead0: {}", msg.uri()); - if (msg.method() != HttpMethod.GET) { - ctx.channel().writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, - HttpResponseStatus.BAD_REQUEST)) - .addListener(ChannelFutureListener.CLOSE); - return; - } - HttpHeaders headers = msg.headers(); - - if (!"Upgrade".equalsIgnoreCase(headers.get(HttpHeaderNames.CONNECTION)) || - !"WebSocket".equalsIgnoreCase(headers.get(HttpHeaderNames.UPGRADE))) { - ctx.channel().writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, - HttpResponseStatus.BAD_REQUEST)) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - final QueryStringDecoder decoder = new QueryStringDecoder(msg.uri()); - if (!decoder.path().equals("/ws")) { - ctx.fireChannelRead(msg); - return; - } - if (decoder.parameters().isEmpty() || - decoder.parameters().get("id") == null || - decoder.parameters().get("id").size() != 1 || - decoder.parameters().get("token") == null || - decoder.parameters().get("token").size() != 1) { - ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, - HttpResponseStatus.BAD_REQUEST)) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - final String id = decoder.parameters().get("id").get(0); - final String token = decoder.parameters().get("token").get(0); - final String versionRaw = (decoder.parameters().get("version") == null || - decoder.parameters().get("version").isEmpty()) ? "0" : - decoder.parameters().get("version").get(0); - try { - if (Integer.parseInt(versionRaw) != 0) { - ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, - HttpResponseStatus.BAD_REQUEST)) - .addListener(ChannelFutureListener.CLOSE); - return; - } - } catch (NumberFormatException ignored) { - ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, - HttpResponseStatus.BAD_REQUEST)) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - final Client client = Config.getGlobalConfig().clients().get(id); - if (client == null || - !client.token().equals(DigestUtils.sha256Hex(token))) { - ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, - HttpResponseStatus.UNAUTHORIZED)) - .addListener(ChannelFutureListener.CLOSE); - return; - } - ctx.channel().attr(Attributes.ID).set(new ClientIdentification(0, client)); - WebSocketServerHandshakerFactory wsFactory = - new WebSocketServerHandshakerFactory("/ws", null, true); - final WebSocketServerHandshaker handshaker = wsFactory.newHandshaker(msg); - if (handshaker == null) { - WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel()); - return; - } - ctx.channel().attr(Attributes.HANDSHAKER).set(handshaker); - handshaker.handshake(ctx.channel(), msg); - ctx.pipeline().replace(this, "websocketHandler", new WSFrameHandler()); - ctx.fireUserEventTriggered(new HandshakeComplete()); - } -} diff --git a/src/main/java/moe/ymc/acron/net/ClientConfiguration.java b/src/main/java/moe/ymc/acron/net/ClientConfiguration.java deleted file mode 100644 index 450ccd4..0000000 --- a/src/main/java/moe/ymc/acron/net/ClientConfiguration.java +++ /dev/null @@ -1,20 +0,0 @@ -package moe.ymc.acron.net; - -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.math.Vec2f; -import net.minecraft.util.math.Vec3d; -import org.jetbrains.annotations.NotNull; - -public record ClientConfiguration(@NotNull Vec3d pos, - @NotNull Vec2f rot, - @NotNull ServerWorld world, - @NotNull String name) { - public ClientConfiguration(@NotNull ServerWorld world, - @NotNull String name) { - // Rcon defaults. @see RconCommandOutput - this(Vec3d.of(world.getSpawnPos()), - Vec2f.ZERO, - world, - name); - } -} diff --git a/src/main/java/moe/ymc/acron/net/ClientIdentification.java b/src/main/java/moe/ymc/acron/net/ClientIdentification.java deleted file mode 100644 index 1cb4375..0000000 --- a/src/main/java/moe/ymc/acron/net/ClientIdentification.java +++ /dev/null @@ -1,11 +0,0 @@ -package moe.ymc.acron.net; - -import moe.ymc.acron.auth.Client; -import org.jetbrains.annotations.NotNull; - -/** - * Read only client configurations. - */ -public record ClientIdentification(int version, - @NotNull Client client) { -} diff --git a/src/main/java/moe/ymc/acron/net/HandshakeComplete.java b/src/main/java/moe/ymc/acron/net/HandshakeComplete.java deleted file mode 100644 index 348b5e2..0000000 --- a/src/main/java/moe/ymc/acron/net/HandshakeComplete.java +++ /dev/null @@ -1,7 +0,0 @@ -package moe.ymc.acron.net; - -/** - * User event used to tell WSFrameHandler that the handshake is complete. - */ -public class HandshakeComplete { -} diff --git a/src/main/java/moe/ymc/acron/net/WSFrameHandler.java b/src/main/java/moe/ymc/acron/net/WSFrameHandler.java deleted file mode 100644 index 912e73a..0000000 --- a/src/main/java/moe/ymc/acron/net/WSFrameHandler.java +++ /dev/null @@ -1,174 +0,0 @@ -package moe.ymc.acron.net; - -import com.google.gson.JsonParseException; -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.handler.codec.http.websocketx.*; -import moe.ymc.acron.MinecraftServerHolder; -import moe.ymc.acron.auth.Action; -import moe.ymc.acron.auth.PolicyChecker; -import moe.ymc.acron.c2s.ReqCmd; -import moe.ymc.acron.c2s.ReqSetConfig; -import moe.ymc.acron.c2s.Request; -import moe.ymc.acron.cmd.CmdQueue; -import moe.ymc.acron.jvav.Pair; -import moe.ymc.acron.s2c.Event; -import moe.ymc.acron.s2c.EventQueue; -import moe.ymc.acron.s2c.response.EventError; -import moe.ymc.acron.s2c.response.EventOk; -import moe.ymc.acron.serialization.Serializer; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.math.Vec2f; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.NotNull; - -/** - * The handler for WebSocket requests. - */ -public class WSFrameHandler extends SimpleChannelInboundHandler { - private static final Logger LOGGER = LogManager.getLogger(); - - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - super.handlerAdded(ctx); - } - - @Override - protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame msg) throws Exception { - LOGGER.debug("channelRead0: {} {}", - this, - ctx.channel()); - final WebSocketServerHandshaker handshaker = - ctx.channel().attr(Attributes.HANDSHAKER).get(); - if (msg instanceof CloseWebSocketFrame) { - handshaker.close(ctx.channel(), (CloseWebSocketFrame) msg.retain()); - return; - } - if (msg instanceof PingWebSocketFrame) { - ctx.write(new PongWebSocketFrame(msg.content().retain())); - return; - } - if (msg instanceof BinaryWebSocketFrame) { - throw new UnsupportedOperationException("Only text frames are accepted."); - } - final TextWebSocketFrame frame = (TextWebSocketFrame) msg; - - final ClientIdentification identification = ctx.channel().attr(Attributes.ID).get(); - final ClientConfiguration configuration = ctx.channel().attr(Attributes.CONFIGURATION).get(); - int id; - final Request request; - try { - request = Serializer.deserialize(frame); - id = request.getId(); - } catch (JsonParseException | IllegalArgumentException | IllegalStateException e) { - ctx.channel().writeAndFlush( - Serializer.serialize(new EventError(-2, EventError.Code.BAD_REQUEST.value, e.getMessage())) - ); - return; - } - try { - ctx.channel().writeAndFlush(Serializer.serialize(handle(request, - identification, - configuration, - ctx.channel()))); - } catch (Throwable e) { - LOGGER.info("An error occurred while processing the request. " + - "This may just be a malformed request. " + - "It is reported to the client.", - e); - ctx.channel().writeAndFlush( - Serializer.serialize(new EventError(id, EventError.Code.SERVER_ERROR.value, e.getMessage())) - ); - } - } - - @NotNull - private Event handle(@NotNull Request request, - @NotNull ClientIdentification identification, - @NotNull ClientConfiguration configuration, - @NotNull Channel channel) throws Throwable { - if (request instanceof final ReqCmd reqCmd) { - LOGGER.info("Client {} executed a command: `{}`.", - identification.client().id(), - reqCmd.cmd()); - final Pair res = PolicyChecker.check(identification.client(), - reqCmd.cmd()); - if (res.l() == Action.DENY) { - return new EventError(reqCmd.id(), - EventError.Code.FORBIDDEN.value, "This client is not allowed to " + - "execute this command."); - } - // TODO: Ok event may be sent after executing the command. - CmdQueue.enqueue(reqCmd.id(), - res.r(), - channel, - reqCmd.config() == null ? - configuration : - convertConfiguration(reqCmd.config()), - reqCmd.cmd()); - return new EventOk(request.getId()); - } else if (request instanceof final ReqSetConfig reqSetConfig) { - channel.attr(Attributes.CONFIGURATION).set(convertConfiguration(reqSetConfig)); - return new EventOk(request.getId()); - } - // This should not occur. - throw new IllegalStateException("This should not occur."); - } - - private ClientConfiguration convertConfiguration(@NotNull ReqSetConfig request) { - final ServerWorld world; - if (request.world() != null) { - switch (request.world()) { - case OVERWORLD -> world = MinecraftServerHolder.getServer().getWorld(World.OVERWORLD); - case NETHER -> world = MinecraftServerHolder.getServer().getWorld(World.NETHER); - case END -> world = MinecraftServerHolder.getServer().getWorld(World.END); - default -> throw new IllegalArgumentException(); - } - } else { - world = MinecraftServerHolder.getServer().getOverworld(); - } - if (world == null) { - throw new IllegalStateException(String.format("The requested world %s is not available at this time.", - request.world())); - } - return new ClientConfiguration( - request.pos() == null ? - Vec3d.of(world.getSpawnPos()) : - new Vec3d(request.pos().x(), request.pos().y(), request.pos().z()), - request.rot() == null ? - Vec2f.ZERO : - new Vec2f(request.rot().x(), request.rot().y()), - world, - request.name() == null ? this.toString() : request.name() - ); - } - - @Override - public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { - LOGGER.debug("handshakeComplete: {} {}", - this, - ctx.channel()); - if (evt instanceof HandshakeComplete) { - final ClientIdentification identification = ctx.channel().attr(Attributes.ID).get(); - LOGGER.info("Client {} connected. It has {} rules with {} policy mode.", - identification.client().id(), - identification.client().rules().length, - identification.client().policyMode()); - final ServerWorld defaultWorld = MinecraftServerHolder.getServer().getOverworld(); - if (defaultWorld == null) { - throw new IllegalStateException("The default world is not available at this time."); - } - final ClientConfiguration configuration = - new ClientConfiguration(defaultWorld, - identification.client().id()); - ctx.channel().attr(Attributes.CONFIGURATION).set(configuration); - EventQueue.registerMessageRecipient(ctx.channel()); - } else { - ctx.fireUserEventTriggered(evt); - } - } -} diff --git a/src/main/java/moe/ymc/acron/s2c/Entity.java b/src/main/java/moe/ymc/acron/s2c/Entity.java deleted file mode 100644 index 3e0add1..0000000 --- a/src/main/java/moe/ymc/acron/s2c/Entity.java +++ /dev/null @@ -1,26 +0,0 @@ -package moe.ymc.acron.s2c; - -import com.google.gson.annotations.SerializedName; -import com.mojang.authlib.GameProfile; -import moe.ymc.acron.common.Vec3d; -import moe.ymc.acron.common.WorldKey; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.UUID; - -public record Entity(@SerializedName("name") @NotNull String name, - @SerializedName("uuid") @NotNull UUID uuid, - @SerializedName("pos") @Nullable Vec3d pos, - @SerializedName("world") @Nullable WorldKey world) { - public Entity(@NotNull net.minecraft.entity.Entity entity) { - this(entity.getName().getString(), - entity.getUuid(), - new Vec3d(entity.getPos()), - WorldKey.create(entity.world.getRegistryKey().getValue())); - } - - public Entity(@NotNull GameProfile profile) { - this(profile.getName(), profile.getId(), null, null); - } -} diff --git a/src/main/java/moe/ymc/acron/s2c/Event.java b/src/main/java/moe/ymc/acron/s2c/Event.java deleted file mode 100644 index 1abc35c..0000000 --- a/src/main/java/moe/ymc/acron/s2c/Event.java +++ /dev/null @@ -1,4 +0,0 @@ -package moe.ymc.acron.s2c; - -public interface Event { -} diff --git a/src/main/java/moe/ymc/acron/s2c/EventQueue.java b/src/main/java/moe/ymc/acron/s2c/EventQueue.java deleted file mode 100644 index 8c470a1..0000000 --- a/src/main/java/moe/ymc/acron/s2c/EventQueue.java +++ /dev/null @@ -1,28 +0,0 @@ -package moe.ymc.acron.s2c; - -import io.netty.channel.Channel; -import io.netty.channel.group.ChannelGroup; -import io.netty.channel.group.DefaultChannelGroup; -import io.netty.util.concurrent.GlobalEventExecutor; -import moe.ymc.acron.serialization.Serializer; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.NotNull; - -public class EventQueue { - private static final Logger LOGGER = LogManager.getLogger(); - - private static final ChannelGroup sMessageRecipients = - new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); - - public static void registerMessageRecipient(@NotNull Channel channel) { - sMessageRecipients.add(channel); - } - - public static void enqueue(@NotNull Event message) { - LOGGER.debug("Enqueue: {} ({} channels)", - message, - sMessageRecipients.size()); - sMessageRecipients.writeAndFlush(Serializer.serialize(message)); - } -} diff --git a/src/main/java/moe/ymc/acron/s2c/event/EventDisconnected.java b/src/main/java/moe/ymc/acron/s2c/event/EventDisconnected.java deleted file mode 100644 index 610fc58..0000000 --- a/src/main/java/moe/ymc/acron/s2c/event/EventDisconnected.java +++ /dev/null @@ -1,12 +0,0 @@ -package moe.ymc.acron.s2c.event; - -import com.google.gson.annotations.SerializedName; -import moe.ymc.acron.s2c.Entity; -import moe.ymc.acron.s2c.Event; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public record EventDisconnected(@SerializedName("player") @Nullable Entity player, - @SerializedName("reason") @NotNull String reason) - implements Event { -} diff --git a/src/main/java/moe/ymc/acron/s2c/event/EventEntityDeath.java b/src/main/java/moe/ymc/acron/s2c/event/EventEntityDeath.java deleted file mode 100644 index 4735241..0000000 --- a/src/main/java/moe/ymc/acron/s2c/event/EventEntityDeath.java +++ /dev/null @@ -1,12 +0,0 @@ -package moe.ymc.acron.s2c.event; - -import com.google.gson.annotations.SerializedName; -import moe.ymc.acron.s2c.Entity; -import moe.ymc.acron.s2c.Event; -import org.jetbrains.annotations.NotNull; - -// TODO: More detailed death report. -public record EventEntityDeath(@SerializedName("entity") @NotNull Entity entity, - @SerializedName("message") @NotNull String message) - implements Event { -} diff --git a/src/main/java/moe/ymc/acron/s2c/event/EventLagging.java b/src/main/java/moe/ymc/acron/s2c/event/EventLagging.java deleted file mode 100644 index 30974df..0000000 --- a/src/main/java/moe/ymc/acron/s2c/event/EventLagging.java +++ /dev/null @@ -1,9 +0,0 @@ -package moe.ymc.acron.s2c.event; - -import com.google.gson.annotations.SerializedName; -import moe.ymc.acron.s2c.Event; - -public record EventLagging(@SerializedName("ms") long ms, - @SerializedName("ticks") long ticks) - implements Event { -} diff --git a/src/main/java/moe/ymc/acron/s2c/event/EventPlayerJoined.java b/src/main/java/moe/ymc/acron/s2c/event/EventPlayerJoined.java deleted file mode 100644 index 408680b..0000000 --- a/src/main/java/moe/ymc/acron/s2c/event/EventPlayerJoined.java +++ /dev/null @@ -1,10 +0,0 @@ -package moe.ymc.acron.s2c.event; - -import com.google.gson.annotations.SerializedName; -import moe.ymc.acron.s2c.Entity; -import moe.ymc.acron.s2c.Event; -import org.jetbrains.annotations.NotNull; - -public record EventPlayerJoined(@SerializedName("player") @NotNull Entity player) - implements Event { -} diff --git a/src/main/java/moe/ymc/acron/s2c/event/EventPlayerMessage.java b/src/main/java/moe/ymc/acron/s2c/event/EventPlayerMessage.java deleted file mode 100644 index 2769493..0000000 --- a/src/main/java/moe/ymc/acron/s2c/event/EventPlayerMessage.java +++ /dev/null @@ -1,12 +0,0 @@ -package moe.ymc.acron.s2c.event; - -import com.google.gson.annotations.SerializedName; -import moe.ymc.acron.s2c.Entity; -import moe.ymc.acron.s2c.Event; -import org.jetbrains.annotations.NotNull; - -public record EventPlayerMessage(@SerializedName("player") @NotNull Entity player, - @SerializedName("text") @NotNull String text) - implements Event { - -} diff --git a/src/main/java/moe/ymc/acron/s2c/response/EventCmdOut.java b/src/main/java/moe/ymc/acron/s2c/response/EventCmdOut.java deleted file mode 100644 index a4cb798..0000000 --- a/src/main/java/moe/ymc/acron/s2c/response/EventCmdOut.java +++ /dev/null @@ -1,13 +0,0 @@ -package moe.ymc.acron.s2c.response; - -import com.google.gson.annotations.SerializedName; -import moe.ymc.acron.s2c.Event; -import org.jetbrains.annotations.NotNull; - -import java.util.UUID; - -public record EventCmdOut(@SerializedName("id") int id, - @SerializedName("sender") @NotNull UUID sender, - @SerializedName("out") @NotNull String out) - implements Event { -} diff --git a/src/main/java/moe/ymc/acron/s2c/response/EventCmdRes.java b/src/main/java/moe/ymc/acron/s2c/response/EventCmdRes.java deleted file mode 100644 index 8c1b6a9..0000000 --- a/src/main/java/moe/ymc/acron/s2c/response/EventCmdRes.java +++ /dev/null @@ -1,10 +0,0 @@ -package moe.ymc.acron.s2c.response; - -import com.google.gson.annotations.SerializedName; -import moe.ymc.acron.s2c.Event; - -public record EventCmdRes(@SerializedName("id") int id, - @SerializedName("success") boolean success, - @SerializedName("result") int result) - implements Event { -} diff --git a/src/main/java/moe/ymc/acron/s2c/response/EventError.java b/src/main/java/moe/ymc/acron/s2c/response/EventError.java deleted file mode 100644 index 370e8f3..0000000 --- a/src/main/java/moe/ymc/acron/s2c/response/EventError.java +++ /dev/null @@ -1,22 +0,0 @@ -package moe.ymc.acron.s2c.response; - -import com.google.gson.annotations.SerializedName; -import moe.ymc.acron.s2c.Event; -import org.jetbrains.annotations.Nullable; - -public record EventError(@SerializedName("id") int id, - @SerializedName("code") int code, - @SerializedName("message") @Nullable String message) - implements Event { - public enum Code { - SERVER_ERROR(500), - BAD_REQUEST(400), - FORBIDDEN(403) - ; - - public final int value; - Code(int value) { - this.value = value; - } - } -} diff --git a/src/main/java/moe/ymc/acron/s2c/response/EventOk.java b/src/main/java/moe/ymc/acron/s2c/response/EventOk.java deleted file mode 100644 index eb8c82d..0000000 --- a/src/main/java/moe/ymc/acron/s2c/response/EventOk.java +++ /dev/null @@ -1,8 +0,0 @@ -package moe.ymc.acron.s2c.response; - -import com.google.gson.annotations.SerializedName; -import moe.ymc.acron.s2c.Event; - -public record EventOk(@SerializedName("id") int id) - implements Event { -} diff --git a/src/main/java/moe/ymc/acron/serialization/Serializer.java b/src/main/java/moe/ymc/acron/serialization/Serializer.java deleted file mode 100644 index 8091c25..0000000 --- a/src/main/java/moe/ymc/acron/serialization/Serializer.java +++ /dev/null @@ -1,60 +0,0 @@ -package moe.ymc.acron.serialization; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonParseException; -import com.google.gson.typeadapters.RuntimeTypeAdapterFactory; -import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; -import moe.ymc.acron.c2s.ReqCmd; -import moe.ymc.acron.c2s.ReqSetConfig; -import moe.ymc.acron.c2s.Request; -import moe.ymc.acron.common.Vec2f; -import moe.ymc.acron.common.Vec3d; -import moe.ymc.acron.s2c.Event; -import moe.ymc.acron.s2c.event.*; -import moe.ymc.acron.s2c.response.EventCmdOut; -import moe.ymc.acron.s2c.response.EventCmdRes; -import moe.ymc.acron.s2c.response.EventError; -import moe.ymc.acron.s2c.response.EventOk; -import org.jetbrains.annotations.NotNull; - -public class Serializer { - @NotNull - public static Request deserialize(@NotNull TextWebSocketFrame frame) - throws JsonParseException, IllegalArgumentException, IllegalStateException { - final String text = frame.text(); - final RuntimeTypeAdapterFactory adapter = - RuntimeTypeAdapterFactory.of(Request.class, "type") - .registerSubtype(ReqSetConfig.class, "set_config") - .registerSubtype(ReqCmd.class, "cmd"); - final Gson gson = new GsonBuilder() - .registerTypeAdapter(ReqSetConfig.class, new ReqSetConfig.ReqSetConfigDeserializer()) - .registerTypeAdapter(Vec3d.class, new Vec3d.Vec3dDeserializer()) - .registerTypeAdapter(Vec2f.class, new Vec2f.Vec2fDeserializer()) - .registerTypeAdapter(ReqCmd.class, new ReqCmd.ReqCmdDeserializer()) - .registerTypeAdapterFactory(adapter) - .create(); - final Request request = gson.fromJson(text, Request.class); - request.validate(); - return request; - } - - @NotNull - public static TextWebSocketFrame serialize(@NotNull Event message) { - final RuntimeTypeAdapterFactory adapter = - RuntimeTypeAdapterFactory.of(Event.class, "type") - .registerSubtype(EventDisconnected.class, "disconnect") - .registerSubtype(EventPlayerMessage.class, "message") - .registerSubtype(EventPlayerJoined.class, "join") - .registerSubtype(EventEntityDeath.class, "death") - .registerSubtype(EventCmdOut.class, "cmd_out") - .registerSubtype(EventCmdRes.class, "cmd_result") - .registerSubtype(EventLagging.class, "lagging") - .registerSubtype(EventError.class, "error") - .registerSubtype(EventOk.class, "ok"); - final Gson gson = new GsonBuilder() - .registerTypeAdapterFactory(adapter) - .create(); - return new TextWebSocketFrame(gson.toJson(message, message.getClass())); - } -} diff --git a/src/main/resources/acron.mixins.json b/src/main/resources/acron.mixins.json deleted file mode 100644 index 5d0911f..0000000 --- a/src/main/resources/acron.mixins.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "required": true, - "minVersion": "0.8", - "package": "moe.ymc.acron.mixin", - "compatibilityLevel": "JAVA_8", - "mixins": [ - "CommandManagerMixin", - "LivingEntityMixin", - "MinecraftDedicatedServerMixin", - "MinecraftServerMixin", - "ServerLoginNetworkHandlerMixin", - "ServerNetworkIoMixin", - "ServerPlayerEntityMixin", - "ServerPlayNetworkHandlerMixin" - ], - "client": [ - ], - "injectors": { - "defaultRequire": 1 - } -} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json deleted file mode 100644 index 999aeeb..0000000 --- a/src/main/resources/fabric.mod.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "schemaVersion": 1, - "id": "acron", - "version": "${version}", - "name": "Acron", - "description": "WebSocket based remote server management", - "authors": ["YuutaW"], - "contact": {}, - "license": "GPL-2.0", - "icon": "assets/acron/icon.png", - "environment": "server", - "entrypoints": { - "main": [ - "moe.ymc.acron.Acron" - ] - }, - "mixins": [ - "acron.mixins.json" - ], - "depends": { - "fabricloader": ">=0.14.4", - "minecraft": "1.17.1" - } -} -- cgit v1.2.3