Added API driven Rooms

This commit is contained in:
Elias Müller 2023-11-12 00:59:17 +01:00
parent 2306308071
commit 5d29c387a3
53 changed files with 313 additions and 25 deletions

2
.gitignore vendored
View File

@ -27,4 +27,4 @@ replay_pid*
.gradle
build/*
resources
/resources/

View File

@ -33,22 +33,16 @@ dependencies {
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.0'
//https://jitpack.io/#Minestom/Minestom
//implementation 'com.github.Minestom:Minestom:aa621021e2'
//implementation 'com.github.Minestom.Minestom:Minestom:4f7ff5b474'
// implementation 'com.github.Minestom.Minestom:Minestom:2cdb3911b0'
// implementation 'com.github.Minestom:MinestomDataGenerator:ddde11056e'
implementation 'com.github.waxeria:Minestom:e0427a36f3'
//Tools
//implementation 'com.github.Articdive.JNoise:jnoise-core:4.0.0'
implementation 'de.articdive:jnoise:3.0.2'
// implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.4.2'
// implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.13.4'
implementation 'org.yaml:snakeyaml:2.0'
implementation 'net.md-5:bungeecord-config:1.19-R0.1-SNAPSHOT'
implementation 'org.apache.commons:commons-text:1.10.0'
implementation 'org.spongepowered:configurate-yaml:4.1.2'
implementation 'com.sparkjava:spark-core:2.9.4'
implementation 'com.google.code.gson:gson:2.10.1'
//PvP

View File

@ -1,5 +1,6 @@
package eu.mhsl.minenet.minigames;
import eu.mhsl.minenet.minigames.api.HttpServer;
import eu.mhsl.minenet.minigames.command.Commands;
import eu.mhsl.minenet.minigames.handler.Listeners;
import eu.mhsl.minenet.minigames.lang.Languages;
@ -23,7 +24,7 @@ public class Main {
* Starts minenet minigames services
*/
private final static Logger logger = Logger.getGlobal();
private static ConfigurationNode globalConfig;
public static ConfigurationNode globalConfig;
public static void main(String[] args) throws ConfigurateException {
//noinspection ResultOfMethodCallIgnored
@ -50,6 +51,7 @@ public class Main {
Commands.values();
Listeners.values();
new HttpServer();
MinecraftServer.getSchedulerManager().scheduleTask(new TablistUpdateTask(), TaskSchedule.tick(20), TaskSchedule.tick(20));

View File

@ -0,0 +1,35 @@
package eu.mhsl.minenet.minigames.api;
import com.google.gson.Gson;
import spark.Request;
import spark.Response;
import spark.Route;
import java.lang.reflect.ParameterizedType;
public abstract class Controller<Q, R> implements Route {
private final Class<Q> requestType;
@SuppressWarnings("unchecked")
public Controller() {
this.requestType = ((Class<Q>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
}
@Override
public Object handle(Request request, Response response) throws Exception {
response.header("Access-Control-Allow-Origin", "*");
response.header("Access-Control-Allow-Methods", "*");
Q req;
if(request.body().isEmpty()) {
req = null;
} else {
req = new Gson().fromJson(request.body(), this.requestType);
}
return new Gson().toJson(handle(req, response));
}
public abstract R handle(Q request, Response response) throws Exception;
}

View File

@ -1,6 +1,35 @@
package eu.mhsl.minenet.minigames.api;
import eu.mhsl.minenet.minigames.Main;
import eu.mhsl.minenet.minigames.api.routes.closeRoom.CloseRoom;
import eu.mhsl.minenet.minigames.api.routes.createRoom.CreateRoom;
import eu.mhsl.minenet.minigames.api.routes.queueRoom.QueueRoom;
import org.spongepowered.configurate.ConfigurationNode;
import static spark.Spark.*;
public class HttpServer {
private static final ConfigurationNode apiConfig = Main.globalConfig.node("api");
public HttpServer() {
if(!apiConfig.node("enabled").getBoolean()) return;
port(apiConfig.node("port").getInt());
initExceptionHandler(e -> e.printStackTrace(System.err));
exception(Exception.class, (exception, request, response) -> {
exception.printStackTrace(System.err);
response.status(500);
});
before((request, response) -> {
String userKey = request.headers("Authorization");
String serverKey = apiConfig.node("secret").getString();
if(userKey != null && !userKey.equals(serverKey)) {
halt(401, "Authorization header missing or wrong");
}
});
post("/room", new CreateRoom());
delete("/room", new CloseRoom());
post("/queueRoom", new QueueRoom());
}
}

View File

@ -0,0 +1,17 @@
package eu.mhsl.minenet.minigames.api;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class QueuedPlayerRooms {
private static final Map<UUID, UUID> playersToRoom = new HashMap<>();
public static void queuePlayer(UUID playerUUID, UUID roomUUID) {
playersToRoom.put(playerUUID, roomUUID);
}
public static UUID pullQueue(UUID playerUUID) {
return playersToRoom.remove(playerUUID);
}
}

View File

@ -0,0 +1,17 @@
package eu.mhsl.minenet.minigames.api.routes.closeRoom;
import eu.mhsl.minenet.minigames.api.Controller;
import eu.mhsl.minenet.minigames.instance.room.Room;
import spark.Response;
import java.util.UUID;
record Req(UUID room) {}
record Resp() {}
public class CloseRoom extends Controller<Req, Resp> {
@Override
public Resp handle(Req request, Response response) throws Exception {
Room.deleteRoom(Room.getRoom(request.room()).orElseThrow());
return new Resp();
}
}

View File

@ -0,0 +1,17 @@
package eu.mhsl.minenet.minigames.api.routes.createRoom;
import eu.mhsl.minenet.minigames.api.Controller;
import eu.mhsl.minenet.minigames.instance.room.Room;
import spark.Response;
import java.util.UUID;
record Req() {}
record Resp(UUID uuid) {}
public class CreateRoom extends Controller<Req, Resp> {
@Override
public Resp handle(Req request, Response response) throws Exception {
Room createdRoom = Room.createOwnerlessRoom();
return new Resp(createdRoom.uuid);
}
}

View File

@ -0,0 +1,19 @@
package eu.mhsl.minenet.minigames.api.routes.queueRoom;
import eu.mhsl.minenet.minigames.api.Controller;
import eu.mhsl.minenet.minigames.api.QueuedPlayerRooms;
import eu.mhsl.minenet.minigames.instance.room.Room;
import spark.Response;
import java.util.UUID;
record Req(UUID player, UUID room) {}
record Resp() {}
public class QueueRoom extends Controller<Req, Resp> {
@Override
public Resp handle(Req request, Response response) throws Exception {
if(Room.getRoom(request.room()).isEmpty()) throw new Exception("Room not found");
QueuedPlayerRooms.queuePlayer(request.player(), request.room());
return new Resp();
}
}

View File

@ -5,6 +5,7 @@ import eu.mhsl.minenet.minigames.message.Icon;
import eu.mhsl.minenet.minigames.message.type.ActionBarMessage;
import eu.mhsl.minenet.minigames.message.type.ChatMessage;
import eu.mhsl.minenet.minigames.message.type.TitleMessage;
import net.minestom.server.entity.Player;
import java.util.ArrayList;
import java.util.List;
@ -33,6 +34,8 @@ public class DebugCommand extends PrivilegedCommand {
.newLine()
.appendTranslated("score#thanks")
.send(sender);
new ChatMessage(Icon.SCIENCE).appendStatic(((Player) sender).getUuid().toString()).send(sender);
});
}

View File

@ -36,6 +36,9 @@ public class SetRoomOwnerCommand extends PrivilegedCommand {
@Override
protected CommandCondition isPrivileged() {
return (sender, commandString) -> super.isPrivileged().canUse(sender, commandString) || Room.getRoom(((Player) sender)).orElseThrow().getOwner() == sender;
return (sender, commandString) -> {
Room playerRoom = Room.getRoom(((Player) sender)).orElse(null);
return super.isPrivileged().canUse(sender, commandString) || (playerRoom != null && playerRoom.getOwner() == sender);
};
}
}

View File

@ -1,5 +1,7 @@
package eu.mhsl.minenet.minigames.handler.global;
import eu.mhsl.minenet.minigames.Main;
import eu.mhsl.minenet.minigames.api.QueuedPlayerRooms;
import eu.mhsl.minenet.minigames.instance.room.Room;
import eu.mhsl.minenet.minigames.message.Icon;
import eu.mhsl.minenet.minigames.message.type.ChatMessage;
@ -11,7 +13,10 @@ import net.minestom.server.event.player.PlayerLoginEvent;
import eu.mhsl.minenet.minigames.instance.hub.Hub;
import net.minestom.server.permission.Permission;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.configurate.serialize.SerializationException;
import java.util.Objects;
import java.util.UUID;
import java.util.logging.Logger;
public class PlayerLoginHandler implements EventListener<PlayerLoginEvent> {
@ -24,15 +29,24 @@ public class PlayerLoginHandler implements EventListener<PlayerLoginEvent> {
public @NotNull Result run(@NotNull PlayerLoginEvent event) {
Player p = event.getPlayer();
p.setRespawnPoint(Hub.INSTANCE.getSpawn());
event.setSpawningInstance(Hub.INSTANCE);
UUID pushQueue = QueuedPlayerRooms.pullQueue(event.getPlayer().getUuid());
if(pushQueue != null) {
Room target = Room.getRoom(pushQueue).orElseThrow();
p.setRespawnPoint(target.getSpawn());
event.setSpawningInstance(Hub.INSTANCE);
MinecraftServer.getSchedulerManager().scheduleNextTick(() -> Room.setRoom(p, target));
} else {
p.setRespawnPoint(Hub.INSTANCE.getSpawn());
event.setSpawningInstance(Hub.INSTANCE);
}
SkinCache.applySkin(p);
if(p.getUsername().equalsIgnoreCase("minetec")) {
p.addPermission(new Permission("admin"));
MinecraftServer.getSchedulerManager().scheduleNextTick(() -> Room.createRoom(p));
}
try {
if(Objects.requireNonNull(Main.globalConfig.node("admins").getList(String.class)).stream().anyMatch(s -> s.equalsIgnoreCase(p.getUsername()))) {
p.addPermission(new Permission("admin"));
}
} catch (SerializationException | NullPointerException ignored) {}
Logger.getLogger("user").info(p.getUsername() + " joined");

View File

@ -17,7 +17,6 @@ import net.minestom.server.entity.GameMode;
import net.minestom.server.entity.Player;
import net.minestom.server.event.player.PlayerBlockBreakEvent;
import net.minestom.server.event.player.PlayerDisconnectEvent;
import net.minestom.server.event.player.PlayerEntityInteractEvent;
import net.minestom.server.instance.AnvilLoader;
import java.util.*;
@ -53,6 +52,10 @@ public class Room extends MineNetInstance implements Spawnable {
return Optional.ofNullable(players.get(p));
}
public static Optional<Room> getRoom(UUID uuid) {
return rooms.stream().filter(room -> room.uuid.equals(uuid)).findFirst();
}
public static void setOwnRoom(Player p) {
setRoom(p, getRoom(p).orElseThrow());
}
@ -144,12 +147,6 @@ public class Room extends MineNetInstance implements Spawnable {
.collect(Collectors.toSet());
}
@Override
protected boolean onPlayerJoin(Player p) {
this.gameSelector.onInteract(new PlayerEntityInteractEvent(p, gameSelector, Player.Hand.MAIN, p.getPosition()));
return super.onPlayerJoin(p);
}
@Override
public Pos getSpawn() {
return new Pos(0.5, 50, 0.5);

View File

@ -0,0 +1,20 @@
server:
port: 25565
view-distance: 12
compression-threshold: 0
open-to-lan: false
bungeecord:
enabled: false
velocity:
enabled: false
secret: ''
api:
enabled: false
secret: ''
port: 8080
admins:
- minetec

View File

@ -0,0 +1 @@
,elias,ELIAS-PC,07.01.2023 22:39,file:///home/elias/.config/libreoffice/4;

View File

@ -0,0 +1,91 @@
map;en_us;de_de
localName;English;Deutsch
name;English;German
symbol;eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2Q5MTQ1Njg3N2Y1NGJmMWFjZTI1MWU0Y2VlNDBkYmE1OTdkMmNjNDAzNjJjYjhmNGVkNzExZTUwYjBiZTViMyJ9fX0=;eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNWU3ODk5YjQ4MDY4NTg2OTdlMjgzZjA4NGQ5MTczZmU0ODc4ODY0NTM3NzQ2MjZiMjRiZDhjZmVjYzc3YjNmIn19fQ==
sample;The quick brown fox jumps over the lazy dog;Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich
;;
ns:common#;;
select_language;Please select your prefered Language;Bitte wähle deine bevorzugte Sprache!
welcome;Welcome!;Willkommen!
back;Back;Zurück
forward;Next;Nächste
;;
ns:tablist#UNUSED;;
title;MineNet Network;MineNet Servernetzwerk
players;Players;Spieler
ram;RAM;RAM
tick;TICK;TICK
;;
;;
ns:GameType#;;
other;Other games;Andere Spiele
other_description;Games which does not fit into other Categories;Spiele welche nicht in die anderen Kategorien passen
pvp;Player vs Player;Spieler gegen Spieler
pvp_description;Fight against other Players;Kämpfe gegen andere Spieler
pve;Player vs Enviroment;Spieler gegen Umwelt
pve_description;Surivie the world or fight entities;Überlebe die Welt oder kämpfe gegen Mobs
;;
ns:hub#;;
invTitle;MineNet Servernetwork;MineNet Servernetzwerk
create;Create your personal Lobby;Erstelle deine persönliche Lobby
create_description;Let other players join your Lobby to play with them;Lasse andere Spieler auf deine Lobby joinen um mit ihnen zusammen zu spielen
join;Join existing Lobby;Betrete eine bestehende Lobby
join_description;All you need is the Username of the Lobby you want to join;Alles was du benötigst ist der Nutzername des Besitzers, dessen Lobby du beitreten möchtest
join_title;Enter Username;Benutzername
join_notFound;Lobby not found: ;Lobby konnte nicht gefunden werden:
;;
ns:score#;;
result;Results;Ergebnisse
thanks;Thank you for Playing;Danke für‘s spielen
finish;Yout did it;Du hast es geschafft
death;You are out;Du hast verloren
;;
ns:restriction#;;
fail;Some requirements are not met;Bedinungen sind nicht erfüllt
success;Play;Spielen
minPlayersInRoom;Minimal amount of Players in Lobby;Minimale Anzahl von Spielern in deiner Lobby
minPlayersInRoomDescription;You need more Players in your room to play this;Die Anzahl der Spieler ist zu gering um dieses Spiel zu starten
maxPlayersInRoom;Maximal amount of Players in Lobby;Maximale Anzahl von Spielern in deiner Lobby
maxPlayersInRoomDescription;There are too many players in your room;Die Anzahl der Spieler in deiner Lobby ist zu hoch für dieses Spiel
;;
ns:optionCommon#;;
value;Value;Wert
width;Width;Breite
length;Length;Länge
height;Height;Höhe
radius;Radius;Radius
;;
ns:room#;;
invTitle;Select a Minigame;Wähle einen Spielmodus
noOption;No options here;Keine Optionen hier
noOptionDescription;There are no options for this Game;Es gibt keine Einstellungen für dieses Spiel
;;
ns:GameFactory#;;
missingDescription;No description;Keine Beschreibung
;;
ns:game_Minerun#;;
name;Minerun;Minenrennen
description;Ditch deadly Mines in the ground an be the first in the goal;Weiche den tödlichen Bodenmienen aus und sei der erste im Ziel
optionPercentageMines;Percentage of Miens;Prozentsatz der Minen
;;
ns:game_Deathcube#;;
name;Deathcube;Todeswürfel
description;Find a way to jump higher and be the first on the top;Finde einen weg nach oben und sei der erste im Ziel
optionPercentageBlocks;Percentage of Blocks;Prozentsatz der Blöcke
;;
ns:game_Stickfight#;;
name;Stickfight;Stockschlacht
description;Push your opponents off the Bridge;Stoße deine Gegener von der Brücke
;;
ns:game_TrafficlightRace#;;
name;Red light green light;Rotes licht, Grünes licht
description;Only go forward if the Trafficlights show green;Gehe nur bei Grün vorran
;;
ns:game_Towerdefense#;;
name;Towerdefense;Towerdefense
description;Protect the path ????;??????
;;
ns:game_Spleef#;;
name;Spleef;Spleef;
description;Spleef other players and be the last survivor;Zerstöre Blöcke unter anderen Spielern und sei der letzte im Feld
shovelName;Snow thrower;Schneeflug
Can't render this file because it has a wrong number of fields in line 89.

View File

@ -0,0 +1,29 @@
setup:
teams:
- 'blue'
- 'orange'
teams:
blue:
name: 'blue'
pos:
spawn: '31.5,11,0.5,90,0'
spawner: '31.5,11,0.5'
bed:
- '32,11,0'
- '33,11,0'
material:
block: 'BLUE_WOOL'
bed: 'BLUE_BED'
orange:
name: "orange"
pos:
spawn: '-31.5,11,0.5,-90,0'
spawner: '-31.5,11,0.5'
bed:
- '-33,11,0'
- '-34,11,0'
material:
block: 'ORANGE_WOOL'
bed: 'ORANGE_BED'

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.