diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..1d6ed64 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,70 @@ +name: CI + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build: + if: ${{ github.event_name == 'push' || (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'deploy-test')) }} + + runs-on: crazypokemondev-runner + permissions: + contents: read + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + + - name: Setup Gradle caches + uses: gradle/actions/setup-gradle@v4.0.0 + + - name: Build with Gradle Wrapper + run: ./gradlew build + - name: Upload Paper Plugin + uses: actions/upload-artifact@v4 + with: + name: UniGui Plugin + path: paper/build/libs/*-all.jar + if-no-files-found: error + + deploy: + needs: + - build + + runs-on: crazypokemondev-runner + environment: mctest + + steps: + - name: Download artifact + uses: actions/download-artifact@v5 + with: + name: UniGui Plugin + path: artifact + + - name: Set up SSH key + env: + SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} + SSH_HOST_PUBLIC_KEY: ${{ vars.SSH_HOST_PUBLIC_KEY }} + run: | + mkdir -p ~/.ssh + touch ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa + echo $SSH_HOST_PUBLIC_KEY >> ~/.ssh/known_hosts + cat << EOF >> ~/.ssh/config + Host flommc + HashKnownHosts no + EOF + - name: Upload plugin to server + run: scp artifact/*.jar mctest@flommc:~/paper-1.21.10/plugins/ + - name: Restart server + run: ssh mctest@flommc 'screen -dmS "STOP" ~/paper-1.21.10/stop.sh' \ No newline at end of file diff --git a/.gitignore b/.gitignore index d5f737e..2ea1e75 100644 --- a/.gitignore +++ b/.gitignore @@ -112,7 +112,9 @@ gradle-app.setting **/build/ # Common working directory -run/ +paper/run/ +neoforge/run/ +fabric/run/ runs/ # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) diff --git a/api/build.gradle b/api/build.gradle new file mode 100644 index 0000000..e69de29 diff --git a/api/src/main/java/de/crazypokemondev/unigui/UniGuiApi.java b/api/src/main/java/de/crazypokemondev/unigui/UniGuiApi.java new file mode 100644 index 0000000..9a32639 --- /dev/null +++ b/api/src/main/java/de/crazypokemondev/unigui/UniGuiApi.java @@ -0,0 +1,5 @@ +package de.crazypokemondev.unigui; + +public class UniGuiApi { + public static final String MOD_ID = "unigui"; +} diff --git a/api/src/main/java/de/crazypokemondev/unigui/api/GuiBase.java b/api/src/main/java/de/crazypokemondev/unigui/api/GuiBase.java new file mode 100644 index 0000000..17b4470 --- /dev/null +++ b/api/src/main/java/de/crazypokemondev/unigui/api/GuiBase.java @@ -0,0 +1,20 @@ +package de.crazypokemondev.unigui.api; + +/** + * Represents a GUI instance. Might be a singleton (usually for stateless GUIs) or a unique instance for one player. + */ +interface GuiBase { + /** + * Should open this GUI for the given player. + * + * @param player The player to open the GUI for. + */ + void open(TPlayer player); + + /** + * Should close the GUI for the player. + * + * @param player The player to close this GUI for. + */ + void close(TPlayer player); +} diff --git a/src/main/java/de/crazypokemondev/uniGUI/api/GuiFactory.java b/api/src/main/java/de/crazypokemondev/unigui/api/GuiFactoryBase.java similarity index 79% rename from src/main/java/de/crazypokemondev/uniGUI/api/GuiFactory.java rename to api/src/main/java/de/crazypokemondev/unigui/api/GuiFactoryBase.java index b025726..6da51e9 100644 --- a/src/main/java/de/crazypokemondev/uniGUI/api/GuiFactory.java +++ b/api/src/main/java/de/crazypokemondev/unigui/api/GuiFactoryBase.java @@ -1,10 +1,12 @@ -package de.crazypokemondev.uniGUI.api; +package de.crazypokemondev.unigui.api; -import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public interface GuiFactory extends Comparable { +/** + * A factory for GUI instances. + */ +interface GuiFactoryBase> extends Comparable> { /** * Should return an identifier for your specific GUI. Recommended pattern is pluginid:guiname. * If you have multiple implementations for the same GUI (e.g. one vanilla implementation and one custom @@ -30,7 +32,7 @@ public interface GuiFactory extends Comparable { * @param player The player to check GUI support for * @return true if the player's client supports this GUI implementation */ - boolean isSupportedByPlayer(Player player); + boolean isSupportedByPlayer(TPlayer player); /** * Should return an instance of your GUI for the given player and state. @@ -41,10 +43,10 @@ public interface GuiFactory extends Comparable { * @return a Gui instance */ @NotNull - Gui createGui(Player player, @Nullable GuiState state); + TGui createGui(TPlayer player, @Nullable TState state); @Override - default int compareTo(@NotNull GuiFactory o) { + default int compareTo(@NotNull GuiFactoryBase o) { return o.getPriority() - this.getPriority(); } } diff --git a/src/main/java/de/crazypokemondev/uniGUI/api/GuiHandler.java b/api/src/main/java/de/crazypokemondev/unigui/api/GuiHandlerBase.java similarity index 55% rename from src/main/java/de/crazypokemondev/uniGUI/api/GuiHandler.java rename to api/src/main/java/de/crazypokemondev/unigui/api/GuiHandlerBase.java index 0630efe..045f5a3 100644 --- a/src/main/java/de/crazypokemondev/uniGUI/api/GuiHandler.java +++ b/api/src/main/java/de/crazypokemondev/unigui/api/GuiHandlerBase.java @@ -1,11 +1,13 @@ -package de.crazypokemondev.uniGUI.api; +package de.crazypokemondev.unigui.api; -import de.crazypokemondev.uniGUI.api.error.GuiNotSupportedException; -import org.bukkit.entity.Player; +import de.crazypokemondev.unigui.api.error.GuiNotSupportedException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public interface GuiHandler { +/** + * The GUI handler service. You don't need to implement this interface, since UniGUI provides this service. + */ +interface GuiHandlerBase> { /** * Opens the specified GUI for the specified player. @@ -16,5 +18,5 @@ public interface GuiHandler { * @return the implementation of the GUI opened for the player * @throws GuiNotSupportedException if the player's client does not support any implementation of the specified GUI */ - Gui openGui(@NotNull Player player, @NotNull String guiId, @Nullable GuiState state) throws GuiNotSupportedException; + TGui openGui(@NotNull TPlayer player, @NotNull String guiId, @Nullable TState state) throws GuiNotSupportedException; } diff --git a/src/main/java/de/crazypokemondev/uniGUI/api/GuiRegistry.java b/api/src/main/java/de/crazypokemondev/unigui/api/GuiRegistryBase.java similarity index 65% rename from src/main/java/de/crazypokemondev/uniGUI/api/GuiRegistry.java rename to api/src/main/java/de/crazypokemondev/unigui/api/GuiRegistryBase.java index e863e9a..0cdb9b0 100644 --- a/src/main/java/de/crazypokemondev/uniGUI/api/GuiRegistry.java +++ b/api/src/main/java/de/crazypokemondev/unigui/api/GuiRegistryBase.java @@ -1,18 +1,20 @@ -package de.crazypokemondev.uniGUI.api; +package de.crazypokemondev.unigui.api; -import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.Optional; -public interface GuiRegistry { +/** + * The GUI registry service. You don't need to implement this interface, since UniGUI provides this service. + */ +interface GuiRegistryBase, TFactory extends GuiFactoryBase> { /** * Registers a GUI factory for usage by the UniGUI lib. * * @param gui The GUI factory to register */ - void register(@NotNull GuiFactory gui); + void register(@NotNull TFactory gui); /** * Unregisters a GUI factory for usage by the UniGUI lib. @@ -20,7 +22,7 @@ public interface GuiRegistry { * @param gui The GUI factory to unregister * @return true if the GUI was previously registered. */ - boolean unregister(@NotNull GuiFactory gui); + boolean unregister(@NotNull TFactory gui); /** * Returns the GUI factory with the highest priority supported by the specified player. @@ -29,7 +31,7 @@ public interface GuiRegistry { * @param player The player that should have support for the given GUI. * @return An Optional of the GUI implementation with the highest priority supported, if any. */ - Optional getGui(@NotNull String guiId, @NotNull Player player); + Optional getGui(@NotNull String guiId, @NotNull TPlayer player); /** * Returns a list of all implementations supported for this GUI id. @@ -37,5 +39,5 @@ public interface GuiRegistry { * @param guiId The identifier of the GUI requested. * @return A list of all registered implementations for this GUI identifier. */ - List getAllGuis(@NotNull String guiId); + List getAllGuis(@NotNull String guiId); } diff --git a/api/src/main/java/de/crazypokemondev/unigui/api/GuiStateBase.java b/api/src/main/java/de/crazypokemondev/unigui/api/GuiStateBase.java new file mode 100644 index 0000000..264a429 --- /dev/null +++ b/api/src/main/java/de/crazypokemondev/unigui/api/GuiStateBase.java @@ -0,0 +1,40 @@ +package de.crazypokemondev.unigui.api; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * Implement this interface on the class representing your GUI state. It provides functionality to notify on changed state, + * so you only need to register update handlers and call {@link GuiStateBase#notifyStateChanged()} to send a notification + * to all handlers. + * For Bukkit or its derivatives it also makes sure the update handlers are being executed on the main thread. + */ +interface GuiStateBase { + /** + * A thread-safe list used to keep track of update handlers + */ + List updateHandlers = new CopyOnWriteArrayList<>(); + + /** + * Registers an update handler to be called every time the state changes. + * + * @param updateHandler The method to be called on state change + */ + default void registerUpdateHandler(Runnable updateHandler) { + updateHandlers.add(updateHandler); + } + + /** + * Unregisters an update handler. + * + * @param updateHandler The handler to unregister + */ + default void unregisterUpdateHandler(Runnable updateHandler) { + updateHandlers.remove(updateHandler); + } + + /** + * Call this method whenever you need to inform all attached GUI instances of an update to the state. + */ + void notifyStateChanged(); +} diff --git a/api/src/main/java/de/crazypokemondev/unigui/api/error/GuiNotSupportedException.java b/api/src/main/java/de/crazypokemondev/unigui/api/error/GuiNotSupportedException.java new file mode 100644 index 0000000..e23bab3 --- /dev/null +++ b/api/src/main/java/de/crazypokemondev/unigui/api/error/GuiNotSupportedException.java @@ -0,0 +1,16 @@ +package de.crazypokemondev.unigui.api.error; + +import java.util.UUID; + +/** + * Thrown when a player's client does not support any GUI for the requested guiId. + * This only happens if you forgot to register a GUI implementation, or if no vanilla implementation is present while + * the player doesn't support any of the modded implementations. + */ +public class GuiNotSupportedException extends RuntimeException { + public GuiNotSupportedException(UUID playerUuid, String guiId) { + super(String.format( + "GUI %s is not compatible with vanilla clients and no supported custom GUI client was reported by player %s", + guiId, playerUuid)); + } +} diff --git a/api/src/main/java/de/crazypokemondev/unigui/network/packets/OpenGuiPayload.java b/api/src/main/java/de/crazypokemondev/unigui/network/packets/OpenGuiPayload.java new file mode 100644 index 0000000..5fcddf4 --- /dev/null +++ b/api/src/main/java/de/crazypokemondev/unigui/network/packets/OpenGuiPayload.java @@ -0,0 +1,16 @@ +package de.crazypokemondev.unigui.network.packets; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.jetbrains.annotations.Nullable; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public abstract class OpenGuiPayload { + public static final String PACKET_NAME = "open_gui"; + protected String guiId; + @Nullable + protected TState state; +} diff --git a/build.gradle b/build.gradle index 132b7e1..3fb8656 100644 --- a/build.gradle +++ b/build.gradle @@ -1,57 +1,86 @@ plugins { - id 'java' - id("xyz.jpenilla.run-paper") version "2.3.1" - id("io.freefair.lombok") version "9.0.0" + id 'dev.architectury.loom' version '1.11-SNAPSHOT' apply false + id 'architectury-plugin' version '3.4-SNAPSHOT' + id 'com.gradleup.shadow' version '8.3.6' apply false + id 'io.freefair.lombok' version "9.0.0" apply false } -group = 'de.crazypokemondev' -version = '0.1' - -repositories { - mavenCentral() - maven { - name = "papermc-repo" - url = "https://repo.papermc.io/repository/maven-public/" - } - maven { url = "https://jitpack.io" } +architectury { + minecraft = project.minecraft_version } -dependencies { - compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT") +allprojects { + group = rootProject.maven_group + version = rootProject.mod_version } -tasks { - runServer { - // Configure the Minecraft version for our task. - // This is the only required configuration besides applying the plugin. - // Your plugin's jar (or shadowJar if present) will be used automatically. - minecraftVersion("1.21.10") +subprojects { + apply plugin: 'maven-publish' + apply plugin: 'architectury-plugin' + apply plugin: 'io.freefair.lombok' + apply plugin: 'com.gradleup.shadow' + + repositories { + // Add repositories to retrieve artifacts from in here. + // You should only use this when depending on other mods because + // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html + // for more information about repositories. } -} -def targetJavaVersion = 21 -java { - def javaVersion = JavaVersion.toVersion(targetJavaVersion) - sourceCompatibility = javaVersion - targetCompatibility = javaVersion - if (JavaVersion.current() < javaVersion) { - toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion) + tasks.withType(JavaCompile).configureEach { + it.options.release = 21 } -} -tasks.withType(JavaCompile).configureEach { - options.encoding = 'UTF-8' + if (!project.hasProperty('skiploom')) { + apply plugin: 'dev.architectury.loom' - if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) { - options.release.set(targetJavaVersion) - } -} + base { + // Set up a suffixed format for the mod jar names, e.g. `example-fabric`. + archivesName = "$rootProject.archives_name-$project.name" + } + + loom { + silentMojangMappingsLicense() + } + + dependencies { + minecraft "net.minecraft:minecraft:$rootProject.minecraft_version" + mappings loom.officialMojangMappings() + if (project.name != 'api') { + implementation project(":api") + if (project.name != 'common') { + include project(":api") + } + } + } + + java { + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() + + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 + } + + // Configure Maven publishing. + publishing { + publications { + mavenJava(MavenPublication) { + artifactId = base.archivesName.get() + from components.java + } + } -processResources { - def props = [version: version] - inputs.properties props - filteringCharset 'UTF-8' - filesMatching('plugin.yml') { - expand props + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + // Notice: This block does NOT have the same function as the block in the top level. + // The repositories here will be used for publishing your artifact, not for + // retrieving dependencies. + } + } } } diff --git a/common/build.gradle b/common/build.gradle new file mode 100644 index 0000000..816616f --- /dev/null +++ b/common/build.gradle @@ -0,0 +1,13 @@ +architectury { + common rootProject.enabled_platforms.split(',') +} + +dependencies { + // We depend on Fabric Loader here to use the Fabric @Environment annotations, + // which get remapped to the correct annotations on each platform. + // Do NOT use other classes from Fabric Loader. + modImplementation "net.fabricmc:fabric-loader:$rootProject.fabric_loader_version" + + // Architectury API. This is optional, and you can comment it out if you don't need it. + modImplementation "dev.architectury:architectury:$rootProject.architectury_api_version" +} diff --git a/common/src/main/java/de/crazypokemondev/unigui/UniGuiCommon.java b/common/src/main/java/de/crazypokemondev/unigui/UniGuiCommon.java new file mode 100644 index 0000000..1757a26 --- /dev/null +++ b/common/src/main/java/de/crazypokemondev/unigui/UniGuiCommon.java @@ -0,0 +1,49 @@ +package de.crazypokemondev.unigui; + +import com.google.common.base.Suppliers; +import de.crazypokemondev.unigui.api.CustomGuiFactory; +import de.crazypokemondev.unigui.api.StateDecoder; +import de.crazypokemondev.unigui.network.packets.OpenGuiPacket; +import de.crazypokemondev.unigui.screens.TestGui; +import de.crazypokemondev.unigui.screens.TestGuiState; +import de.crazypokemondev.unigui.state.NullState; +import dev.architectury.networking.NetworkManager; +import dev.architectury.platform.Platform; +import dev.architectury.registry.registries.Registrar; +import dev.architectury.registry.registries.RegistrarManager; +import dev.architectury.registry.registries.options.DefaultIdRegistrarOption; +import lombok.extern.slf4j.Slf4j; +import net.fabricmc.api.EnvType; +import net.minecraft.resources.ResourceLocation; + +import java.util.function.Supplier; + +@Slf4j +public final class UniGuiCommon { + public static final Supplier REGISTRY_MANAGER = Suppliers.memoize(() -> RegistrarManager.get(UniGuiApi.MOD_ID)); + public static Registrar GUI_FACTORIES; + public static Registrar> STATE_DECODERS; + private static final ResourceLocation NULL_STATE_LOCATION = ResourceLocation.fromNamespaceAndPath(UniGuiApi.MOD_ID, "null"); + + public static void init() { + // Write common init code here. + GUI_FACTORIES = REGISTRY_MANAGER.get() + .builder(ResourceLocation.fromNamespaceAndPath(UniGuiApi.MOD_ID, "gui_factories"), new CustomGuiFactory[0]) + .build(); + STATE_DECODERS = REGISTRY_MANAGER.get() + .builder(ResourceLocation.fromNamespaceAndPath(UniGuiApi.MOD_ID, "states"), new StateDecoder[0]) + .option(new DefaultIdRegistrarOption(NULL_STATE_LOCATION)) + .build(); + STATE_DECODERS.register(NULL_STATE_LOCATION, NullState::new); + + GUI_FACTORIES.register(ResourceLocation.fromNamespaceAndPath(UniGuiApi.MOD_ID, "testgui"), () -> TestGui::new); + STATE_DECODERS.register(ResourceLocation.fromNamespaceAndPath(UniGuiApi.MOD_ID, "testgui"), TestGuiState::new); + + if (Platform.getEnv() == EnvType.SERVER) { + NetworkManager.registerS2CPayloadType(OpenGuiPacket.TYPE, OpenGuiPacket.CODEC); + } + if (Platform.getEnv() == EnvType.CLIENT) { + NetworkManager.registerReceiver(NetworkManager.Side.S2C, OpenGuiPacket.TYPE, OpenGuiPacket.CODEC, OpenGuiPacket::receive); + } + } +} diff --git a/common/src/main/java/de/crazypokemondev/unigui/UniGuiHandler.java b/common/src/main/java/de/crazypokemondev/unigui/UniGuiHandler.java new file mode 100644 index 0000000..b6bdccf --- /dev/null +++ b/common/src/main/java/de/crazypokemondev/unigui/UniGuiHandler.java @@ -0,0 +1,27 @@ +package de.crazypokemondev.unigui; + +import de.crazypokemondev.unigui.api.*; +import de.crazypokemondev.unigui.api.error.GuiNotSupportedException; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import net.minecraft.server.level.ServerPlayer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; + +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class UniGuiHandler implements GuiHandler { + public static final UniGuiHandler INSTANCE = new UniGuiHandler(UniGuiRegistry.INSTANCE); + + private final GuiRegistry registry; + + @Override + public Gui openGui(@NotNull ServerPlayer player, @NotNull String guiId, @Nullable GuiState state) throws GuiNotSupportedException { + Optional optional = registry.getGui(guiId, player); + GuiFactory factory = optional.orElseThrow(() -> new GuiNotSupportedException(player.getUUID(), guiId)); + Gui gui = factory.createGui(player, state); + gui.open(player); + return gui; + } +} diff --git a/common/src/main/java/de/crazypokemondev/unigui/UniGuiRegistry.java b/common/src/main/java/de/crazypokemondev/unigui/UniGuiRegistry.java new file mode 100644 index 0000000..dd26b07 --- /dev/null +++ b/common/src/main/java/de/crazypokemondev/unigui/UniGuiRegistry.java @@ -0,0 +1,49 @@ +package de.crazypokemondev.unigui; + +import de.crazypokemondev.unigui.api.GuiFactory; +import de.crazypokemondev.unigui.api.GuiRegistry; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import net.minecraft.server.level.ServerPlayer; +import org.jetbrains.annotations.NotNull; + +import java.util.*; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class UniGuiRegistry implements GuiRegistry { + public static UniGuiRegistry INSTANCE = new UniGuiRegistry(); + + private final Map> registry = new HashMap<>(); + + @Override + public void register(@NotNull GuiFactory factory) { + if (!registry.containsKey(factory.getId())) { + registry.put(factory.getId(), new PriorityQueue<>()); + } + registry.get(factory.getId()).add(factory); + } + + @Override + public boolean unregister(@NotNull GuiFactory factory) { + if (registry.containsKey(factory.getId())) { + return registry.get(factory.getId()).remove(factory); + } else return false; + } + + @Override + public Optional getGui(@NotNull String guiId, @NotNull ServerPlayer player) { + PriorityQueue guis = registry.getOrDefault(guiId, null); + if (guis != null) { + for (GuiFactory f : guis) { + if (f.isSupportedByPlayer(player)) return Optional.of(f); + } + } + return Optional.empty(); + } + + @Override + public List getAllGuis(@NotNull String guiId) { + if (registry.containsKey(guiId)) return registry.get(guiId).stream().toList(); + else return Collections.emptyList(); + } +} diff --git a/common/src/main/java/de/crazypokemondev/unigui/api/CustomGuiFactory.java b/common/src/main/java/de/crazypokemondev/unigui/api/CustomGuiFactory.java new file mode 100644 index 0000000..08a8a36 --- /dev/null +++ b/common/src/main/java/de/crazypokemondev/unigui/api/CustomGuiFactory.java @@ -0,0 +1,10 @@ +package de.crazypokemondev.unigui.api; + +import net.minecraft.client.gui.screens.Screen; +import org.jetbrains.annotations.NotNull; + +@FunctionalInterface +public interface CustomGuiFactory { + @NotNull + Screen createScreen(); +} diff --git a/common/src/main/java/de/crazypokemondev/unigui/api/EncodableGuiState.java b/common/src/main/java/de/crazypokemondev/unigui/api/EncodableGuiState.java new file mode 100644 index 0000000..f969419 --- /dev/null +++ b/common/src/main/java/de/crazypokemondev/unigui/api/EncodableGuiState.java @@ -0,0 +1,9 @@ +package de.crazypokemondev.unigui.api; + +import net.minecraft.network.FriendlyByteBuf; + +public interface EncodableGuiState> extends GuiState { + void encode(FriendlyByteBuf buf); + + TState decode(FriendlyByteBuf buf); +} diff --git a/common/src/main/java/de/crazypokemondev/unigui/api/Gui.java b/common/src/main/java/de/crazypokemondev/unigui/api/Gui.java new file mode 100644 index 0000000..01fc49b --- /dev/null +++ b/common/src/main/java/de/crazypokemondev/unigui/api/Gui.java @@ -0,0 +1,10 @@ +package de.crazypokemondev.unigui.api; + +import net.minecraft.server.level.ServerPlayer; + +/** + * @see de.crazypokemondev.unigui.api.GuiBase + */ +public interface Gui extends GuiBase { + +} diff --git a/common/src/main/java/de/crazypokemondev/unigui/api/GuiFactory.java b/common/src/main/java/de/crazypokemondev/unigui/api/GuiFactory.java new file mode 100644 index 0000000..07a412e --- /dev/null +++ b/common/src/main/java/de/crazypokemondev/unigui/api/GuiFactory.java @@ -0,0 +1,10 @@ +package de.crazypokemondev.unigui.api; + +import net.minecraft.server.level.ServerPlayer; + +/** + * @see de.crazypokemondev.unigui.api.GuiFactoryBase + */ +public interface GuiFactory extends GuiFactoryBase { + +} diff --git a/common/src/main/java/de/crazypokemondev/unigui/api/GuiHandler.java b/common/src/main/java/de/crazypokemondev/unigui/api/GuiHandler.java new file mode 100644 index 0000000..118decb --- /dev/null +++ b/common/src/main/java/de/crazypokemondev/unigui/api/GuiHandler.java @@ -0,0 +1,10 @@ +package de.crazypokemondev.unigui.api; + +import net.minecraft.server.level.ServerPlayer; + +/** + * @see de.crazypokemondev.unigui.api.GuiHandlerBase + */ +public interface GuiHandler extends GuiHandlerBase { + +} diff --git a/common/src/main/java/de/crazypokemondev/unigui/api/GuiRegistry.java b/common/src/main/java/de/crazypokemondev/unigui/api/GuiRegistry.java new file mode 100644 index 0000000..038b3eb --- /dev/null +++ b/common/src/main/java/de/crazypokemondev/unigui/api/GuiRegistry.java @@ -0,0 +1,10 @@ +package de.crazypokemondev.unigui.api; + +import net.minecraft.server.level.ServerPlayer; + +/** + * @see de.crazypokemondev.unigui.api.GuiRegistryBase + */ +public interface GuiRegistry extends GuiRegistryBase { + +} diff --git a/common/src/main/java/de/crazypokemondev/unigui/api/GuiState.java b/common/src/main/java/de/crazypokemondev/unigui/api/GuiState.java new file mode 100644 index 0000000..39e7a10 --- /dev/null +++ b/common/src/main/java/de/crazypokemondev/unigui/api/GuiState.java @@ -0,0 +1,16 @@ +package de.crazypokemondev.unigui.api; + +/** + * @see de.crazypokemondev.unigui.api.GuiStateBase + */ +public interface GuiState extends GuiStateBase { + + /** + * {@inheritDoc} + */ + default void notifyStateChanged() { + for (Runnable handler : updateHandlers) { + handler.run(); + } + } +} diff --git a/common/src/main/java/de/crazypokemondev/unigui/api/StateDecoder.java b/common/src/main/java/de/crazypokemondev/unigui/api/StateDecoder.java new file mode 100644 index 0000000..ca5aaf1 --- /dev/null +++ b/common/src/main/java/de/crazypokemondev/unigui/api/StateDecoder.java @@ -0,0 +1,8 @@ +package de.crazypokemondev.unigui.api; + +import net.minecraft.network.FriendlyByteBuf; + +@FunctionalInterface +public interface StateDecoder> { + EncodableGuiState decode(FriendlyByteBuf buf); +} diff --git a/common/src/main/java/de/crazypokemondev/unigui/api/StatefulScreen.java b/common/src/main/java/de/crazypokemondev/unigui/api/StatefulScreen.java new file mode 100644 index 0000000..5db0ebb --- /dev/null +++ b/common/src/main/java/de/crazypokemondev/unigui/api/StatefulScreen.java @@ -0,0 +1,10 @@ +package de.crazypokemondev.unigui.api; + +import org.jetbrains.annotations.NotNull; + +public interface StatefulScreen> { + void updateState(T state); + + @NotNull + Class stateType(); +} diff --git a/common/src/main/java/de/crazypokemondev/unigui/network/packets/OpenGuiPacket.java b/common/src/main/java/de/crazypokemondev/unigui/network/packets/OpenGuiPacket.java new file mode 100644 index 0000000..bd9f781 --- /dev/null +++ b/common/src/main/java/de/crazypokemondev/unigui/network/packets/OpenGuiPacket.java @@ -0,0 +1,71 @@ +package de.crazypokemondev.unigui.network.packets; + +import de.crazypokemondev.unigui.UniGuiApi; +import de.crazypokemondev.unigui.UniGuiCommon; +import de.crazypokemondev.unigui.api.CustomGuiFactory; +import de.crazypokemondev.unigui.api.EncodableGuiState; +import de.crazypokemondev.unigui.api.StateDecoder; +import de.crazypokemondev.unigui.api.StatefulScreen; +import dev.architectury.networking.NetworkManager; +import lombok.extern.slf4j.Slf4j; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.NotNull; + +@Slf4j +public class OpenGuiPacket extends OpenGuiPayload> implements CustomPacketPayload { + public static final ResourceLocation ID = ResourceLocation.fromNamespaceAndPath(UniGuiApi.MOD_ID, PACKET_NAME); + public static final Type TYPE = new Type<>(ID); + public static final StreamCodec CODEC = StreamCodec.of(OpenGuiPacket::encode, OpenGuiPacket::new); + + public OpenGuiPacket(FriendlyByteBuf byteBuf) { + guiId = byteBuf.readUtf(); + StateDecoder stateDecoder = null; + ResourceLocation location = ResourceLocation.tryParse(guiId); + if (location != null) { + stateDecoder = UniGuiCommon.STATE_DECODERS.get(location); + } + if (stateDecoder != null) { + this.state = stateDecoder.decode(byteBuf); + } + } + + @Override + public @NotNull Type type() { + return TYPE; + } + + public static void encode(FriendlyByteBuf byteBuf, OpenGuiPacket testPackage) { + byteBuf.writeUtf(testPackage.guiId); + if (testPackage.state != null) { + testPackage.state.encode(byteBuf); + } + } + + public static void receive(OpenGuiPacket packet, NetworkManager.PacketContext context) { + context.queue(() -> { + ResourceLocation location = ResourceLocation.tryParse(packet.getGuiId()); + if (location != null) { + CustomGuiFactory guiFactory = UniGuiCommon.GUI_FACTORIES.get(location); + if (guiFactory != null) { + Screen screen = guiFactory.createScreen(); + if (packet.state != null && screen instanceof StatefulScreen statefulScreen) { + setState(statefulScreen, packet.state); + } + Minecraft.getInstance().setScreen(screen); + } + } + }); + } + + public static > void setState(StatefulScreen screen, EncodableGuiState state) { + Class type = screen.stateType(); + if (type.isAssignableFrom(state.getClass())) { + screen.updateState(type.cast(state)); + } + } +} diff --git a/common/src/main/java/de/crazypokemondev/unigui/screens/TestGui.java b/common/src/main/java/de/crazypokemondev/unigui/screens/TestGui.java new file mode 100644 index 0000000..5ebc5f6 --- /dev/null +++ b/common/src/main/java/de/crazypokemondev/unigui/screens/TestGui.java @@ -0,0 +1,32 @@ +package de.crazypokemondev.unigui.screens; + +import de.crazypokemondev.unigui.api.StatefulScreen; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.NotNull; + +public class TestGui extends Screen implements StatefulScreen { + private TestGuiState state; + + public TestGui() { + super(Component.literal("Test")); + } + + @Override + public void render(GuiGraphics guiGraphics, int i, int j, float f) { + super.render(guiGraphics, i, j, f); + + guiGraphics.drawCenteredString(font, state.getText(), width / 2, height / 2, 0xffffffff); + } + + @Override + public void updateState(TestGuiState state) { + this.state = state; + } + + @Override + public @NotNull Class stateType() { + return TestGuiState.class; + } +} diff --git a/common/src/main/java/de/crazypokemondev/unigui/screens/TestGuiState.java b/common/src/main/java/de/crazypokemondev/unigui/screens/TestGuiState.java new file mode 100644 index 0000000..9d15ce4 --- /dev/null +++ b/common/src/main/java/de/crazypokemondev/unigui/screens/TestGuiState.java @@ -0,0 +1,25 @@ +package de.crazypokemondev.unigui.screens; + +import de.crazypokemondev.unigui.api.EncodableGuiState; +import de.crazypokemondev.unigui.api.StateDecoder; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.minecraft.network.FriendlyByteBuf; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class TestGuiState implements EncodableGuiState, StateDecoder { + private String text; + + @Override + public void encode(FriendlyByteBuf buf) { + buf.writeUtf(text); + } + + @Override + public TestGuiState decode(FriendlyByteBuf buf) { + return new TestGuiState(buf.readUtf()); + } +} diff --git a/common/src/main/java/de/crazypokemondev/unigui/state/NullState.java b/common/src/main/java/de/crazypokemondev/unigui/state/NullState.java new file mode 100644 index 0000000..dfaa334 --- /dev/null +++ b/common/src/main/java/de/crazypokemondev/unigui/state/NullState.java @@ -0,0 +1,17 @@ +package de.crazypokemondev.unigui.state; + +import de.crazypokemondev.unigui.api.EncodableGuiState; +import de.crazypokemondev.unigui.api.StateDecoder; +import net.minecraft.network.FriendlyByteBuf; + +public class NullState implements EncodableGuiState, StateDecoder { + @Override + public void encode(FriendlyByteBuf buf) { + + } + + @Override + public NullState decode(FriendlyByteBuf buf) { + return new NullState(); + } +} diff --git a/common/src/main/java/de/crazypokemondev/unigui/vanilla/VanillaGuiFactory.java b/common/src/main/java/de/crazypokemondev/unigui/vanilla/VanillaGuiFactory.java new file mode 100644 index 0000000..455e014 --- /dev/null +++ b/common/src/main/java/de/crazypokemondev/unigui/vanilla/VanillaGuiFactory.java @@ -0,0 +1,27 @@ +package de.crazypokemondev.unigui.vanilla; + +import de.crazypokemondev.unigui.api.GuiFactory; +import net.minecraft.server.level.ServerPlayer; + +public abstract class VanillaGuiFactory implements GuiFactory { + private final String id; + + public VanillaGuiFactory(String id) { + this.id = id; + } + + @Override + public String getId() { + return id; + } + + @Override + public int getPriority() { + return 0; + } + + @Override + public boolean isSupportedByPlayer(ServerPlayer player) { + return true; + } +} diff --git a/common/src/main/java/de/crazypokemondev/unigui/vanilla/VanillaGuiFactoryStateful.java b/common/src/main/java/de/crazypokemondev/unigui/vanilla/VanillaGuiFactoryStateful.java new file mode 100644 index 0000000..18bfac1 --- /dev/null +++ b/common/src/main/java/de/crazypokemondev/unigui/vanilla/VanillaGuiFactoryStateful.java @@ -0,0 +1,34 @@ +package de.crazypokemondev.unigui.vanilla; + +import de.crazypokemondev.unigui.api.Gui; +import de.crazypokemondev.unigui.api.GuiState; +import net.minecraft.server.level.ServerPlayer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.function.BiFunction; + +public class VanillaGuiFactoryStateful extends VanillaGuiFactory { + private final BiFunction supplier; + + /** + * Creates a new factory for a stateless vanilla GUI + * + * @param id The identifier for your specific GUI. Recommended pattern is pluginid:guiname. + * If you have multiple implementations for the same GUI (e.g. one vanilla implementation and one custom + * implementation) they need to share the same identifier. The implementation with the highest priority available + * to the client will be used. + * @param supplier A supplier method that will return a new instance of the GUI for the given player, + * referencing the GuiState it receives. + * This can be the same state holder for multiple GUI instances. + */ + public VanillaGuiFactoryStateful(String id, BiFunction supplier) { + super(id); + this.supplier = supplier; + } + + @Override + public @NotNull Gui createGui(ServerPlayer player, @Nullable GuiState state) { + return supplier.apply(player, state); + } +} diff --git a/common/src/main/java/de/crazypokemondev/unigui/vanilla/VanillaGuiFactoryStateless.java b/common/src/main/java/de/crazypokemondev/unigui/vanilla/VanillaGuiFactoryStateless.java new file mode 100644 index 0000000..829e69c --- /dev/null +++ b/common/src/main/java/de/crazypokemondev/unigui/vanilla/VanillaGuiFactoryStateless.java @@ -0,0 +1,29 @@ +package de.crazypokemondev.unigui.vanilla; + +import de.crazypokemondev.unigui.api.Gui; +import de.crazypokemondev.unigui.api.GuiState; +import net.minecraft.server.level.ServerPlayer; +import org.jetbrains.annotations.NotNull; + +public class VanillaGuiFactoryStateless extends VanillaGuiFactory { + private final Gui gui; + + /** + * Creates a new factory for a stateless vanilla GUI + * + * @param id The identifier for your specific GUI. Recommended pattern is pluginid:guiname. + * If you have multiple implementations for the same GUI (e.g. one vanilla implementation and one custom + * implementation) they need to share the same identifier. The implementation with the highest priority available + * to the client will be used. + * @param gui The Gui instance to return. Since this GUI is stateless, the same instance can be returned for every player. + */ + public VanillaGuiFactoryStateless(String id, Gui gui) { + super(id); + this.gui = gui; + } + + @Override + public @NotNull Gui createGui(ServerPlayer player, GuiState state) { + return gui; + } +} diff --git a/common/src/main/resources/unigui.mixins.json b/common/src/main/resources/unigui.mixins.json new file mode 100644 index 0000000..0a9a29a --- /dev/null +++ b/common/src/main/resources/unigui.mixins.json @@ -0,0 +1,13 @@ +{ + "required": true, + "package": "de.crazypokemondev.unigui.mixin", + "compatibilityLevel": "JAVA_21", + "minVersion": "0.8", + "client": [ + ], + "mixins": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/fabric/build.gradle b/fabric/build.gradle new file mode 100644 index 0000000..31d58a0 --- /dev/null +++ b/fabric/build.gradle @@ -0,0 +1,55 @@ +plugins { + id 'com.gradleup.shadow' +} + +architectury { + platformSetupLoomIde() + fabric() +} + +configurations { + common { + canBeResolved = true + canBeConsumed = false + } + compileClasspath.extendsFrom common + runtimeClasspath.extendsFrom common + developmentFabric.extendsFrom common + + // Files in this configuration will be bundled into your mod using the Shadow plugin. + // Don't use the `shadow` configuration from the plugin itself as it's meant for excluding files. + shadowBundle { + canBeResolved = true + canBeConsumed = false + } +} + +dependencies { + modImplementation "net.fabricmc:fabric-loader:$rootProject.fabric_loader_version" + + // Fabric API. This is technically optional, but you probably want it anyway. + modImplementation "net.fabricmc.fabric-api:fabric-api:$rootProject.fabric_api_version" + + // Architectury API. This is optional, and you can comment it out if you don't need it. + modImplementation "dev.architectury:architectury-fabric:$rootProject.architectury_api_version" + + common(project(path: ':common', configuration: 'namedElements')) { transitive = false } + shadowBundle project(path: ':common', configuration: 'transformProductionFabric') +} + +processResources { + inputs.property 'version', project.version + + filesMatching('fabric.mod.json') { + expand version: inputs.properties.version + } +} + +shadowJar { + configurations = [project.configurations.shadowBundle] + archiveClassifier = 'dev-shadow' +} + +remapJar { + inputFile.set shadowJar.archiveFile +} diff --git a/fabric/src/main/java/de/crazypokemondev/unigui/fabric/UniGuiFabric.java b/fabric/src/main/java/de/crazypokemondev/unigui/fabric/UniGuiFabric.java new file mode 100644 index 0000000..5038711 --- /dev/null +++ b/fabric/src/main/java/de/crazypokemondev/unigui/fabric/UniGuiFabric.java @@ -0,0 +1,17 @@ +package de.crazypokemondev.unigui.fabric; + +import net.fabricmc.api.ModInitializer; + +import de.crazypokemondev.unigui.UniGuiCommon; + +public final class UniGuiFabric implements ModInitializer { + @Override + public void onInitialize() { + // This code runs as soon as Minecraft is in a mod-load-ready state. + // However, some things (like resources) may still be uninitialized. + // Proceed with mild caution. + + // Run our common setup. + UniGuiCommon.init(); + } +} diff --git a/fabric/src/main/java/de/crazypokemondev/unigui/fabric/client/ExampleModFabricClient.java b/fabric/src/main/java/de/crazypokemondev/unigui/fabric/client/ExampleModFabricClient.java new file mode 100644 index 0000000..918a4dc --- /dev/null +++ b/fabric/src/main/java/de/crazypokemondev/unigui/fabric/client/ExampleModFabricClient.java @@ -0,0 +1,10 @@ +package de.crazypokemondev.unigui.fabric.client; + +import net.fabricmc.api.ClientModInitializer; + +public final class ExampleModFabricClient implements ClientModInitializer { + @Override + public void onInitializeClient() { + // This entrypoint is suitable for setting up client-specific logic, such as rendering. + } +} diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..e526446 --- /dev/null +++ b/fabric/src/main/resources/fabric.mod.json @@ -0,0 +1,38 @@ +{ + "schemaVersion": 1, + "id": "unigui", + "version": "${version}", + "name": "UniGUI", + "description": "This is an example description! Tell everyone what your mod is about!", + "authors": [ + "Me!" + ], + "contact": { + "homepage": "https://fabricmc.net/", + "sources": "https://github.com/FabricMC/fabric-example-mod" + }, + "license": "CC0-1.0", + "icon": "assets/unigui/icon.png", + "environment": "*", + "entrypoints": { + "main": [ + "de.crazypokemondev.unigui.fabric.UniGuiFabric" + ], + "client": [ + "de.crazypokemondev.unigui.fabric.client.ExampleModFabricClient" + ] + }, + "mixins": [ + "unigui.mixins.json" + ], + "depends": { + "fabricloader": ">=0.18.0", + "minecraft": "~1.21.10", + "java": ">=21", + "architectury": ">=18.0.6", + "fabric-api": "*" + }, + "suggests": { + "another-mod": "*" + } +} diff --git a/gradle.properties b/gradle.properties index e69de29..2dee8c6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -0,0 +1,15 @@ +# Done to increase the memory available to Gradle. +org.gradle.jvmargs=-Xmx2G +org.gradle.parallel=true +# Mod properties +mod_version=SNAPSHOT +maven_group=de.crazypokemondev.unigui +archives_name=unigui +enabled_platforms=fabric,neoforge +# Minecraft properties +minecraft_version=1.21.10 +# Dependencies +architectury_api_version=18.0.6 +fabric_loader_version=0.18.0 +fabric_api_version=0.138.3+1.21.10 +neoforge_version=21.10.34-beta diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e644113..f8e1ee3 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a441313..bad7c24 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 index b740cf1..adff685 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -84,7 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -112,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -170,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -203,15 +203,14 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat old mode 100644 new mode 100755 index 25da30d..c4bdd3a --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -68,11 +70,10 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/neoforge/build.gradle b/neoforge/build.gradle new file mode 100644 index 0000000..da5c1f1 --- /dev/null +++ b/neoforge/build.gradle @@ -0,0 +1,59 @@ +plugins { + id 'com.gradleup.shadow' +} + +architectury { + platformSetupLoomIde() + neoForge() +} + +configurations { + common { + canBeResolved = true + canBeConsumed = false + } + compileClasspath.extendsFrom common + runtimeClasspath.extendsFrom common + developmentNeoForge.extendsFrom common + + // Files in this configuration will be bundled into your mod using the Shadow plugin. + // Don't use the `shadow` configuration from the plugin itself as it's meant for excluding files. + shadowBundle { + canBeResolved = true + canBeConsumed = false + } +} + +repositories { + maven { + name = 'NeoForged' + url = 'https://maven.neoforged.net/releases' + } +} + +dependencies { + neoForge "net.neoforged:neoforge:$rootProject.neoforge_version" + + // Architectury API. This is optional, and you can comment it out if you don't need it. + modImplementation "dev.architectury:architectury-neoforge:$rootProject.architectury_api_version" + + common(project(path: ':common', configuration: 'namedElements')) { transitive = false } + shadowBundle project(path: ':common', configuration: 'transformProductionNeoForge') +} + +processResources { + inputs.property 'version', project.version + + filesMatching('META-INF/neoforge.mods.toml') { + expand version: inputs.properties.version + } +} + +shadowJar { + configurations = [project.configurations.shadowBundle] + archiveClassifier = 'dev-shadow' +} + +remapJar { + inputFile.set shadowJar.archiveFile +} diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties new file mode 100644 index 0000000..2e6ed76 --- /dev/null +++ b/neoforge/gradle.properties @@ -0,0 +1 @@ +loom.platform = neoforge diff --git a/neoforge/src/main/java/de/crazypokemondev/unigui/neoforge/UniGuiNeoForge.java b/neoforge/src/main/java/de/crazypokemondev/unigui/neoforge/UniGuiNeoForge.java new file mode 100644 index 0000000..cd28891 --- /dev/null +++ b/neoforge/src/main/java/de/crazypokemondev/unigui/neoforge/UniGuiNeoForge.java @@ -0,0 +1,14 @@ +package de.crazypokemondev.unigui.neoforge; + +import de.crazypokemondev.unigui.UniGuiApi; +import net.neoforged.fml.common.Mod; + +import de.crazypokemondev.unigui.UniGuiCommon; + +@Mod(UniGuiApi.MOD_ID) +public final class UniGuiNeoForge { + public UniGuiNeoForge() { + // Run our common setup. + UniGuiCommon.init(); + } +} diff --git a/neoforge/src/main/resources/META-INF/neoforge.mods.toml b/neoforge/src/main/resources/META-INF/neoforge.mods.toml new file mode 100644 index 0000000..4f14672 --- /dev/null +++ b/neoforge/src/main/resources/META-INF/neoforge.mods.toml @@ -0,0 +1,38 @@ +modLoader = "javafml" +loaderVersion = "[10,)" +#issueTrackerURL = "" +license = "Insert License Here" + +[[mods]] +modId = "unigui" +version = "${version}" +displayName = "UniGUI" +authors = "Me!" +description = ''' +This is an example description! Tell everyone what your mod is about! +''' +#logoFile = "" + +[[dependencies.unigui]] +modId = "neoforge" +type = "required" +versionRange = "[21.10,)" +ordering = "NONE" +side = "BOTH" + +[[dependencies.unigui]] +modId = "minecraft" +type = "required" +versionRange = "[1.21.10,)" +ordering = "NONE" +side = "BOTH" + +[[dependencies.unigui]] +modId = "architectury" +type = "required" +versionRange = "[18.0.6,)" +ordering = "AFTER" +side = "BOTH" + +[[mixins]] +config = "unigui.mixins.json" diff --git a/README.md b/paper/README.md similarity index 100% rename from README.md rename to paper/README.md diff --git a/paper/build.gradle b/paper/build.gradle new file mode 100644 index 0000000..74f8ba5 --- /dev/null +++ b/paper/build.gradle @@ -0,0 +1,64 @@ +plugins { + id 'java' + id('io.papermc.paperweight.userdev') version "2.0.0-beta.19" + id("xyz.jpenilla.run-paper") version "2.3.1" +} + +repositories { + mavenCentral() + maven { + name = "papermc-repo" + url = "https://repo.papermc.io/repository/maven-public/" + } + maven { url = "https://jitpack.io" } +} + +dependencies { + compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT") + paperweight.paperDevBundle("1.21.10-R0.1-SNAPSHOT") + implementation project(':api') +} + +base { + archivesName = "$rootProject.archives_name-$project.name" +} + +build { + dependsOn shadowJar +} + +tasks { + runServer { + // Configure the Minecraft version for our task. + // This is the only required configuration besides applying the plugin. + // Your plugin's jar (or shadowJar if present) will be used automatically. + minecraftVersion("1.21.10") + } +} + +def targetJavaVersion = 21 +java { + def javaVersion = JavaVersion.toVersion(targetJavaVersion) + sourceCompatibility = javaVersion + targetCompatibility = javaVersion + if (JavaVersion.current() < javaVersion) { + toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion) + } +} + +tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' + + if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) { + options.release.set(targetJavaVersion) + } +} + +processResources { + def props = [version: version, minecraft_version: rootProject.minecraft_version] + inputs.properties props + filteringCharset 'UTF-8' + filesMatching('plugin.yml') { + expand props + } +} diff --git a/paper/gradle.properties b/paper/gradle.properties new file mode 100644 index 0000000..200d06c --- /dev/null +++ b/paper/gradle.properties @@ -0,0 +1 @@ +skiploom=true \ No newline at end of file diff --git a/src/main/java/de/crazypokemondev/uniGUI/UniGuiHandler.java b/paper/src/main/java/de/crazypokemondev/unigui/UniGuiHandler.java similarity index 51% rename from src/main/java/de/crazypokemondev/uniGUI/UniGuiHandler.java rename to paper/src/main/java/de/crazypokemondev/unigui/UniGuiHandler.java index 104b1b8..ee572f6 100644 --- a/src/main/java/de/crazypokemondev/uniGUI/UniGuiHandler.java +++ b/paper/src/main/java/de/crazypokemondev/unigui/UniGuiHandler.java @@ -1,28 +1,29 @@ -package de.crazypokemondev.uniGUI; +package de.crazypokemondev.unigui; -import de.crazypokemondev.uniGUI.api.Gui; -import de.crazypokemondev.uniGUI.api.GuiFactory; -import de.crazypokemondev.uniGUI.api.GuiHandler; -import de.crazypokemondev.uniGUI.api.GuiRegistry; -import de.crazypokemondev.uniGUI.api.error.GuiNotSupportedException; -import de.crazypokemondev.uniGUI.api.GuiState; +import de.crazypokemondev.unigui.api.Gui; +import de.crazypokemondev.unigui.api.GuiFactory; +import de.crazypokemondev.unigui.api.GuiHandler; +import de.crazypokemondev.unigui.api.GuiRegistry; +import de.crazypokemondev.unigui.api.GuiState; +import de.crazypokemondev.unigui.api.error.GuiNotSupportedException; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Optional; +@AllArgsConstructor(access = AccessLevel.PRIVATE) public class UniGuiHandler implements GuiHandler { - private final GuiRegistry registry; + public static final UniGuiHandler INSTANCE = new UniGuiHandler(UniGuiRegistry.INSTANCE); - public UniGuiHandler(GuiRegistry registry) { - this.registry = registry; - } + private final GuiRegistry registry; @Override public Gui openGui(@NotNull Player player, @NotNull String guiId, @Nullable GuiState state) throws GuiNotSupportedException { Optional optional = registry.getGui(guiId, player); - GuiFactory factory = optional.orElseThrow(() -> new GuiNotSupportedException(player, guiId)); + GuiFactory factory = optional.orElseThrow(() -> new GuiNotSupportedException(player.getUniqueId(), guiId)); Gui gui = factory.createGui(player, state); gui.open(player); return gui; diff --git a/paper/src/main/java/de/crazypokemondev/unigui/UniGuiPaper.java b/paper/src/main/java/de/crazypokemondev/unigui/UniGuiPaper.java new file mode 100644 index 0000000..b7bcd44 --- /dev/null +++ b/paper/src/main/java/de/crazypokemondev/unigui/UniGuiPaper.java @@ -0,0 +1,40 @@ +package de.crazypokemondev.unigui; + +import de.crazypokemondev.unigui.api.GuiHandler; +import de.crazypokemondev.unigui.api.GuiRegistry; +import de.crazypokemondev.unigui.network.NetworkManager; +import de.crazypokemondev.unigui.network.packets.OpenGuiPacket; +import de.crazypokemondev.unigui.state.TestGuiState; +import org.bukkit.entity.Player; +import org.bukkit.plugin.ServicePriority; +import org.bukkit.plugin.java.JavaPlugin; + +public final class UniGuiPaper extends JavaPlugin { + public static UniGuiPaper INSTANCE; + + @Override + public void onEnable() { + INSTANCE = this; + getServer().getMessenger().registerOutgoingPluginChannel(this, UniGuiApi.MOD_ID + ":" + OpenGuiPacket.PACKET_NAME); + TestGuiState state = new TestGuiState("hello"); + registerCommand("nettest", (source, args) -> { + if (!(source.getSender() instanceof Player player)) return; + NetworkManager.sendToPlayer(player, new OpenGuiPacket("unigui:testgui", state)); + }); + registerCommand("changetext", (source, args) -> { + state.setText(String.join(" ", args)); + state.notifyStateChanged(); + }); + // TODO incoming listener for default abstract implementations + getServer().getServicesManager().register(GuiRegistry.class, UniGuiRegistry.INSTANCE, this, ServicePriority.Normal); + getServer().getServicesManager().register(GuiHandler.class, UniGuiHandler.INSTANCE, this, ServicePriority.Normal); + } + + @Override + public void onDisable() { + getServer().getMessenger().unregisterOutgoingPluginChannel(this, UniGuiApi.MOD_ID + ":" + OpenGuiPacket.PACKET_NAME); + // TODO incoming listener for default abstract implementations + getServer().getServicesManager().unregister(UniGuiRegistry.INSTANCE); + getServer().getServicesManager().unregister(UniGuiHandler.INSTANCE); + } +} diff --git a/src/main/java/de/crazypokemondev/uniGUI/UniGuiRegistry.java b/paper/src/main/java/de/crazypokemondev/unigui/UniGuiRegistry.java similarity index 80% rename from src/main/java/de/crazypokemondev/uniGUI/UniGuiRegistry.java rename to paper/src/main/java/de/crazypokemondev/unigui/UniGuiRegistry.java index f0ac658..1c7daa4 100644 --- a/src/main/java/de/crazypokemondev/uniGUI/UniGuiRegistry.java +++ b/paper/src/main/java/de/crazypokemondev/unigui/UniGuiRegistry.java @@ -1,13 +1,18 @@ -package de.crazypokemondev.uniGUI; +package de.crazypokemondev.unigui; -import de.crazypokemondev.uniGUI.api.GuiFactory; -import de.crazypokemondev.uniGUI.api.GuiRegistry; +import de.crazypokemondev.unigui.api.GuiFactory; +import de.crazypokemondev.unigui.api.GuiRegistry; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import java.util.*; +@NoArgsConstructor(access = AccessLevel.PRIVATE) public class UniGuiRegistry implements GuiRegistry { + public static final UniGuiRegistry INSTANCE = new UniGuiRegistry(); + private final Map> registry = new HashMap<>(); @Override diff --git a/paper/src/main/java/de/crazypokemondev/unigui/api/EncodableGuiState.java b/paper/src/main/java/de/crazypokemondev/unigui/api/EncodableGuiState.java new file mode 100644 index 0000000..f969419 --- /dev/null +++ b/paper/src/main/java/de/crazypokemondev/unigui/api/EncodableGuiState.java @@ -0,0 +1,9 @@ +package de.crazypokemondev.unigui.api; + +import net.minecraft.network.FriendlyByteBuf; + +public interface EncodableGuiState> extends GuiState { + void encode(FriendlyByteBuf buf); + + TState decode(FriendlyByteBuf buf); +} diff --git a/paper/src/main/java/de/crazypokemondev/unigui/api/Gui.java b/paper/src/main/java/de/crazypokemondev/unigui/api/Gui.java new file mode 100644 index 0000000..0b1ac91 --- /dev/null +++ b/paper/src/main/java/de/crazypokemondev/unigui/api/Gui.java @@ -0,0 +1,10 @@ +package de.crazypokemondev.unigui.api; + +import org.bukkit.entity.Player; + +/** + * @see de.crazypokemondev.unigui.api.GuiBase + */ +public interface Gui extends GuiBase { + +} diff --git a/paper/src/main/java/de/crazypokemondev/unigui/api/GuiFactory.java b/paper/src/main/java/de/crazypokemondev/unigui/api/GuiFactory.java new file mode 100644 index 0000000..b1e497d --- /dev/null +++ b/paper/src/main/java/de/crazypokemondev/unigui/api/GuiFactory.java @@ -0,0 +1,10 @@ +package de.crazypokemondev.unigui.api; + +import org.bukkit.entity.Player; + +/** + * @see de.crazypokemondev.unigui.api.GuiFactoryBase + */ +public interface GuiFactory extends GuiFactoryBase { + +} diff --git a/paper/src/main/java/de/crazypokemondev/unigui/api/GuiHandler.java b/paper/src/main/java/de/crazypokemondev/unigui/api/GuiHandler.java new file mode 100644 index 0000000..ef8d492 --- /dev/null +++ b/paper/src/main/java/de/crazypokemondev/unigui/api/GuiHandler.java @@ -0,0 +1,10 @@ +package de.crazypokemondev.unigui.api; + +import org.bukkit.entity.Player; + +/** + * @see de.crazypokemondev.unigui.api.GuiHandlerBase + */ +public interface GuiHandler extends GuiHandlerBase { + +} diff --git a/paper/src/main/java/de/crazypokemondev/unigui/api/GuiRegistry.java b/paper/src/main/java/de/crazypokemondev/unigui/api/GuiRegistry.java new file mode 100644 index 0000000..495983b --- /dev/null +++ b/paper/src/main/java/de/crazypokemondev/unigui/api/GuiRegistry.java @@ -0,0 +1,10 @@ +package de.crazypokemondev.unigui.api; + +import org.bukkit.entity.Player; + +/** + * @see de.crazypokemondev.unigui.api.GuiRegistryBase + */ +public interface GuiRegistry extends GuiRegistryBase { + +} diff --git a/paper/src/main/java/de/crazypokemondev/unigui/api/GuiState.java b/paper/src/main/java/de/crazypokemondev/unigui/api/GuiState.java new file mode 100644 index 0000000..0a4a7f1 --- /dev/null +++ b/paper/src/main/java/de/crazypokemondev/unigui/api/GuiState.java @@ -0,0 +1,24 @@ +package de.crazypokemondev.unigui.api; + +import de.crazypokemondev.unigui.UniGuiPaper; +import org.bukkit.Bukkit; +import org.bukkit.scheduler.BukkitScheduler; + +/** + * @see de.crazypokemondev.unigui.api.GuiStateBase + */ +public interface GuiState extends GuiStateBase { + /** + * The scheduler instance used to ensure that all update handlers are being run on the main thread + */ + BukkitScheduler scheduler = Bukkit.getScheduler(); + + /** + * {@inheritDoc} + */ + default void notifyStateChanged() { + for (Runnable handler : updateHandlers) { + scheduler.runTask(UniGuiPaper.INSTANCE, handler); + } + } +} diff --git a/src/main/java/de/crazypokemondev/uniGUI/guis/vanilla/VanillaGuiFactory.java b/paper/src/main/java/de/crazypokemondev/unigui/guis/vanilla/VanillaGuiFactory.java similarity index 64% rename from src/main/java/de/crazypokemondev/uniGUI/guis/vanilla/VanillaGuiFactory.java rename to paper/src/main/java/de/crazypokemondev/unigui/guis/vanilla/VanillaGuiFactory.java index b0fc50a..a1e5042 100644 --- a/src/main/java/de/crazypokemondev/uniGUI/guis/vanilla/VanillaGuiFactory.java +++ b/paper/src/main/java/de/crazypokemondev/unigui/guis/vanilla/VanillaGuiFactory.java @@ -1,10 +1,9 @@ -package de.crazypokemondev.uniGUI.guis.vanilla; +package de.crazypokemondev.unigui.guis.vanilla; -import de.crazypokemondev.uniGUI.UniGuiFactory; -import de.crazypokemondev.uniGUI.api.Gui; +import de.crazypokemondev.unigui.api.GuiFactory; import org.bukkit.entity.Player; -public abstract class VanillaGuiFactory extends UniGuiFactory { +public abstract class VanillaGuiFactory implements GuiFactory { private final String id; public VanillaGuiFactory(String id) { diff --git a/src/main/java/de/crazypokemondev/uniGUI/guis/vanilla/VanillaGuiFactoryStateful.java b/paper/src/main/java/de/crazypokemondev/unigui/guis/vanilla/VanillaGuiFactoryStateful.java similarity index 90% rename from src/main/java/de/crazypokemondev/uniGUI/guis/vanilla/VanillaGuiFactoryStateful.java rename to paper/src/main/java/de/crazypokemondev/unigui/guis/vanilla/VanillaGuiFactoryStateful.java index 0580e53..922609b 100644 --- a/src/main/java/de/crazypokemondev/uniGUI/guis/vanilla/VanillaGuiFactoryStateful.java +++ b/paper/src/main/java/de/crazypokemondev/unigui/guis/vanilla/VanillaGuiFactoryStateful.java @@ -1,7 +1,7 @@ -package de.crazypokemondev.uniGUI.guis.vanilla; +package de.crazypokemondev.unigui.guis.vanilla; -import de.crazypokemondev.uniGUI.api.Gui; -import de.crazypokemondev.uniGUI.api.GuiState; +import de.crazypokemondev.unigui.api.Gui; +import de.crazypokemondev.unigui.api.GuiState; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/de/crazypokemondev/uniGUI/guis/vanilla/VanillaGuiFactoryStateless.java b/paper/src/main/java/de/crazypokemondev/unigui/guis/vanilla/VanillaGuiFactoryStateless.java similarity index 87% rename from src/main/java/de/crazypokemondev/uniGUI/guis/vanilla/VanillaGuiFactoryStateless.java rename to paper/src/main/java/de/crazypokemondev/unigui/guis/vanilla/VanillaGuiFactoryStateless.java index b861378..562b8fe 100644 --- a/src/main/java/de/crazypokemondev/uniGUI/guis/vanilla/VanillaGuiFactoryStateless.java +++ b/paper/src/main/java/de/crazypokemondev/unigui/guis/vanilla/VanillaGuiFactoryStateless.java @@ -1,7 +1,7 @@ -package de.crazypokemondev.uniGUI.guis.vanilla; +package de.crazypokemondev.unigui.guis.vanilla; -import de.crazypokemondev.uniGUI.api.Gui; -import de.crazypokemondev.uniGUI.api.GuiState; +import de.crazypokemondev.unigui.api.Gui; +import de.crazypokemondev.unigui.api.GuiState; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; diff --git a/paper/src/main/java/de/crazypokemondev/unigui/network/NetworkManager.java b/paper/src/main/java/de/crazypokemondev/unigui/network/NetworkManager.java new file mode 100644 index 0000000..0e48713 --- /dev/null +++ b/paper/src/main/java/de/crazypokemondev/unigui/network/NetworkManager.java @@ -0,0 +1,26 @@ +package de.crazypokemondev.unigui.network; + +import de.crazypokemondev.unigui.UniGuiApi; +import de.crazypokemondev.unigui.UniGuiPaper; +import de.crazypokemondev.unigui.network.packets.Packet; +import io.netty.buffer.Unpooled; +import net.minecraft.network.FriendlyByteBuf; +import org.bukkit.entity.Player; + +public class NetworkManager { + public static void sendToPlayer(Player player, T packet) { + FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.buffer()); + packet.encode(buffer); + + FriendlyByteBuf packetSizeBuf = new FriendlyByteBuf(Unpooled.buffer()); + int packetSize = buffer.readableBytes(); + packetSizeBuf.writeVarInt(packetSize); + + int packetSizeLength = packetSizeBuf.readableBytes(); + byte[] bytes = new byte[packetSizeLength + packetSize]; + packetSizeBuf.readBytes(bytes, 0, packetSizeLength); + buffer.readBytes(bytes, packetSizeLength, packetSize); + + player.sendPluginMessage(UniGuiPaper.INSTANCE, UniGuiApi.MOD_ID + ":" + packet.getName(), bytes); + } +} diff --git a/paper/src/main/java/de/crazypokemondev/unigui/network/packets/OpenGuiPacket.java b/paper/src/main/java/de/crazypokemondev/unigui/network/packets/OpenGuiPacket.java new file mode 100644 index 0000000..5bb0be5 --- /dev/null +++ b/paper/src/main/java/de/crazypokemondev/unigui/network/packets/OpenGuiPacket.java @@ -0,0 +1,24 @@ +package de.crazypokemondev.unigui.network.packets; + +import de.crazypokemondev.unigui.api.EncodableGuiState; +import net.minecraft.network.FriendlyByteBuf; +import org.jetbrains.annotations.Nullable; + +public class OpenGuiPacket extends OpenGuiPayload> implements Packet { + public OpenGuiPacket(String guiId, @Nullable EncodableGuiState state) { + super(guiId, state); + } + + @Override + public void encode(FriendlyByteBuf buffer) { + buffer.writeUtf(getGuiId()); + if (state != null) { + state.encode(buffer); + } + } + + @Override + public String getName() { + return OpenGuiPayload.PACKET_NAME; + } +} diff --git a/paper/src/main/java/de/crazypokemondev/unigui/network/packets/Packet.java b/paper/src/main/java/de/crazypokemondev/unigui/network/packets/Packet.java new file mode 100644 index 0000000..59509f8 --- /dev/null +++ b/paper/src/main/java/de/crazypokemondev/unigui/network/packets/Packet.java @@ -0,0 +1,9 @@ +package de.crazypokemondev.unigui.network.packets; + +import net.minecraft.network.FriendlyByteBuf; + +public interface Packet { + void encode(FriendlyByteBuf buffer); + + String getName(); +} diff --git a/paper/src/main/java/de/crazypokemondev/unigui/state/NullState.java b/paper/src/main/java/de/crazypokemondev/unigui/state/NullState.java new file mode 100644 index 0000000..c20b5d8 --- /dev/null +++ b/paper/src/main/java/de/crazypokemondev/unigui/state/NullState.java @@ -0,0 +1,16 @@ +package de.crazypokemondev.unigui.state; + +import de.crazypokemondev.unigui.api.EncodableGuiState; +import net.minecraft.network.FriendlyByteBuf; + +public class NullState implements EncodableGuiState { + @Override + public void encode(FriendlyByteBuf buf) { + + } + + @Override + public NullState decode(FriendlyByteBuf buf) { + return new NullState(); + } +} diff --git a/paper/src/main/java/de/crazypokemondev/unigui/state/TestGuiState.java b/paper/src/main/java/de/crazypokemondev/unigui/state/TestGuiState.java new file mode 100644 index 0000000..2c71e9c --- /dev/null +++ b/paper/src/main/java/de/crazypokemondev/unigui/state/TestGuiState.java @@ -0,0 +1,26 @@ +package de.crazypokemondev.unigui.state; + +import de.crazypokemondev.unigui.api.EncodableGuiState; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.network.FriendlyByteBuf; + +@Getter +@Setter +public class TestGuiState implements EncodableGuiState { + private String text; + + public TestGuiState(String text) { + this.text = text; + } + + @Override + public void encode(FriendlyByteBuf buf) { + buf.writeUtf(text); + } + + @Override + public TestGuiState decode(FriendlyByteBuf buf) { + return new TestGuiState(buf.readUtf()); + } +} diff --git a/src/main/resources/plugin.yml b/paper/src/main/resources/plugin.yml similarity index 65% rename from src/main/resources/plugin.yml rename to paper/src/main/resources/plugin.yml index b3d2c23..471e605 100644 --- a/src/main/resources/plugin.yml +++ b/paper/src/main/resources/plugin.yml @@ -1,8 +1,8 @@ name: UniGUI -version: '0.1' -main: de.crazypokemondev.uniGUI.UniGUI +version: '${version}' +main: de.crazypokemondev.unigui.UniGuiPaper description: Universal GUI library for Paper, combines support for both Vanilla and modded clients. -api-version: '1.21.10' +api-version: '${minecraft_version}' authors: [ Olfi01 ] website: https://github.com/Olfi01/UniGUI depend: diff --git a/settings.gradle b/settings.gradle index 5e0bb40..d94f662 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,16 @@ +pluginManagement { + repositories { + maven { url = 'https://maven.fabricmc.net/' } + maven { url = 'https://maven.architectury.dev/' } + maven { url = 'https://files.minecraftforge.net/maven/' } + gradlePluginPortal() + } +} + rootProject.name = 'UniGUI' + +include 'api' +include 'common' +include 'fabric' +include 'neoforge' +include 'paper' diff --git a/src/main/java/de/crazypokemondev/uniGUI/UniGUI.java b/src/main/java/de/crazypokemondev/uniGUI/UniGUI.java deleted file mode 100644 index 4b21d07..0000000 --- a/src/main/java/de/crazypokemondev/uniGUI/UniGUI.java +++ /dev/null @@ -1,28 +0,0 @@ -package de.crazypokemondev.uniGUI; - -import de.crazypokemondev.uniGUI.api.GuiHandler; -import de.crazypokemondev.uniGUI.api.GuiRegistry; -import de.crazypokemondev.uniGUI.network.Channels; -import org.bukkit.plugin.ServicePriority; -import org.bukkit.plugin.java.JavaPlugin; - -public final class UniGUI extends JavaPlugin { - public static final String PLUGIN_ID = "UniGUI"; - public static UniGUI INSTANCE; - private final GuiRegistry guiRegistry = new UniGuiRegistry(); - private final GuiHandler guiHandler = new UniGuiHandler(guiRegistry); - - @Override - public void onEnable() { - INSTANCE = this; - getServer().getMessenger().registerOutgoingPluginChannel(this, Channels.UNIGUI_MAIN.getId()); - // TODO incoming listener for default abstract implementations - getServer().getServicesManager().register(GuiRegistry.class, guiRegistry, this, ServicePriority.Normal); - getServer().getServicesManager().register(GuiHandler.class, guiHandler, this, ServicePriority.Normal); - } - - @Override - public void onDisable() { - getServer().getServicesManager().unregister(guiHandler); - } -} diff --git a/src/main/java/de/crazypokemondev/uniGUI/UniGuiFactory.java b/src/main/java/de/crazypokemondev/uniGUI/UniGuiFactory.java deleted file mode 100644 index 8ebc6eb..0000000 --- a/src/main/java/de/crazypokemondev/uniGUI/UniGuiFactory.java +++ /dev/null @@ -1,7 +0,0 @@ -package de.crazypokemondev.uniGUI; - -import de.crazypokemondev.uniGUI.api.GuiFactory; - -public abstract class UniGuiFactory implements GuiFactory { - -} diff --git a/src/main/java/de/crazypokemondev/uniGUI/api/Gui.java b/src/main/java/de/crazypokemondev/uniGUI/api/Gui.java deleted file mode 100644 index 3be0e40..0000000 --- a/src/main/java/de/crazypokemondev/uniGUI/api/Gui.java +++ /dev/null @@ -1,20 +0,0 @@ -package de.crazypokemondev.uniGUI.api; - -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -public interface Gui { - /** - * Should open this GUI for the given player. - * - * @param player The player to open the GUI for. - */ - void open(Player player); - - /** - * Should close the GUI for the player. - * - * @param player The player to close this GUI for. - */ - void close(Player player); -} diff --git a/src/main/java/de/crazypokemondev/uniGUI/api/GuiEventHandler.java b/src/main/java/de/crazypokemondev/uniGUI/api/GuiEventHandler.java deleted file mode 100644 index 59d7191..0000000 --- a/src/main/java/de/crazypokemondev/uniGUI/api/GuiEventHandler.java +++ /dev/null @@ -1,4 +0,0 @@ -package de.crazypokemondev.uniGUI.api; - -public interface GuiEventHandler { -} diff --git a/src/main/java/de/crazypokemondev/uniGUI/api/GuiState.java b/src/main/java/de/crazypokemondev/uniGUI/api/GuiState.java deleted file mode 100644 index 436fcb3..0000000 --- a/src/main/java/de/crazypokemondev/uniGUI/api/GuiState.java +++ /dev/null @@ -1,27 +0,0 @@ -package de.crazypokemondev.uniGUI.api; - -import de.crazypokemondev.uniGUI.UniGUI; -import org.bukkit.Bukkit; -import org.bukkit.scheduler.BukkitScheduler; - -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; - -public interface GuiState { - BukkitScheduler scheduler = Bukkit.getScheduler(); - List updateHandlers = new CopyOnWriteArrayList<>(); - - default void registerUpdateHandler(Runnable updateHandler) { - updateHandlers.add(updateHandler); - } - - default void unregisterUpdateHandler(Runnable updateHandler) { - updateHandlers.remove(updateHandler); - } - - default void notifyStateChanged() { - for (Runnable handler : updateHandlers) { - scheduler.runTask(UniGUI.INSTANCE, handler); - } - } -} diff --git a/src/main/java/de/crazypokemondev/uniGUI/api/error/GuiNotSupportedException.java b/src/main/java/de/crazypokemondev/uniGUI/api/error/GuiNotSupportedException.java deleted file mode 100644 index 23cd6fa..0000000 --- a/src/main/java/de/crazypokemondev/uniGUI/api/error/GuiNotSupportedException.java +++ /dev/null @@ -1,11 +0,0 @@ -package de.crazypokemondev.uniGUI.api.error; - -import org.bukkit.entity.Player; - -public class GuiNotSupportedException extends RuntimeException { - public GuiNotSupportedException(Player player, String guiId) { - super(String.format( - "GUI %s is not compatible with vanilla clients and no supported custom GUI client was reported by player %s", - guiId, player.getUniqueId())); - } -} diff --git a/src/main/java/de/crazypokemondev/uniGUI/network/Channels.java b/src/main/java/de/crazypokemondev/uniGUI/network/Channels.java deleted file mode 100644 index 43b0441..0000000 --- a/src/main/java/de/crazypokemondev/uniGUI/network/Channels.java +++ /dev/null @@ -1,14 +0,0 @@ -package de.crazypokemondev.uniGUI.network; - -import lombok.Getter; - -@Getter -public enum Channels { - UNIGUI_MAIN("unigui:main"); - - private final String id; - - Channels(String id) { - this.id = id; - } -}