Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -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'
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Empty file added api/build.gradle
Empty file.
5 changes: 5 additions & 0 deletions api/src/main/java/de/crazypokemondev/unigui/UniGuiApi.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package de.crazypokemondev.unigui;

public class UniGuiApi {
public static final String MOD_ID = "unigui";
}
20 changes: 20 additions & 0 deletions api/src/main/java/de/crazypokemondev/unigui/api/GuiBase.java
Original file line number Diff line number Diff line change
@@ -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<TPlayer> {
/**
* 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);
}
Original file line number Diff line number Diff line change
@@ -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<GuiFactory> {
/**
* A factory for GUI instances.
*/
interface GuiFactoryBase<TPlayer, TState extends GuiStateBase, TGui extends GuiBase<TPlayer>> extends Comparable<GuiFactoryBase<TPlayer, TState, TGui>> {
/**
* Should return an identifier for your specific GUI. Recommended pattern is <code>pluginid:guiname</code>.
* If you have multiple implementations for the same GUI (e.g. one vanilla implementation and one custom
Expand All @@ -30,7 +32,7 @@ public interface GuiFactory extends Comparable<GuiFactory> {
* @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.
Expand All @@ -41,10 +43,10 @@ public interface GuiFactory extends Comparable<GuiFactory> {
* @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<TPlayer, TState, TGui> o) {
return o.getPriority() - this.getPriority();
}
}
Original file line number Diff line number Diff line change
@@ -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<TPlayer, TState extends GuiStateBase, TGui extends GuiBase<TPlayer>> {

/**
* Opens the specified GUI for the specified player.
Expand All @@ -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;
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
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<TPlayer, TState extends GuiStateBase, TGui extends GuiBase<TPlayer>, TFactory extends GuiFactoryBase<TPlayer, TState, TGui>> {
/**
* 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.
*
* @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.
Expand All @@ -29,13 +31,13 @@ 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<GuiFactory> getGui(@NotNull String guiId, @NotNull Player player);
Optional<TFactory> getGui(@NotNull String guiId, @NotNull TPlayer player);

/**
* Returns a list of all implementations supported for this GUI id.
*
* @param guiId The identifier of the GUI requested.
* @return A list of all registered implementations for this GUI identifier.
*/
List<GuiFactory> getAllGuis(@NotNull String guiId);
List<TFactory> getAllGuis(@NotNull String guiId);
}
40 changes: 40 additions & 0 deletions api/src/main/java/de/crazypokemondev/unigui/api/GuiStateBase.java
Original file line number Diff line number Diff line change
@@ -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<Runnable> 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();
}
Original file line number Diff line number Diff line change
@@ -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 <code>guiId</code>.
* 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));
}
}
Original file line number Diff line number Diff line change
@@ -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<TState> {
public static final String PACKET_NAME = "open_gui";
protected String guiId;
@Nullable
protected TState state;
}
Loading
Loading