diff --git a/build.gradle b/build.gradle index 382e70e..3095e6b 100644 --- a/build.gradle +++ b/build.gradle @@ -54,6 +54,7 @@ dependencies { 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' + implementation 'com.google.guava:guava:31.0.1-jre' //PvP diff --git a/src/main/java/eu/mhsl/minenet/minigames/Resource.java b/src/main/java/eu/mhsl/minenet/minigames/Resource.java index 21e29ca..775748d 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/Resource.java +++ b/src/main/java/eu/mhsl/minenet/minigames/Resource.java @@ -14,6 +14,7 @@ public enum Resource { CONFIG("config.yml", true), HUB_MAP("maps/hub"), LOBBY_MAP("maps/lobby"), + RESULT_DISPLAY("maps/resultdisplay"), GAME_MAP("maps/game"), LOCALES("lang"); diff --git a/src/main/java/eu/mhsl/minenet/minigames/api/Controller.java b/src/main/java/eu/mhsl/minenet/minigames/api/Controller.java index a5f1b6b..40afb34 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/api/Controller.java +++ b/src/main/java/eu/mhsl/minenet/minigames/api/Controller.java @@ -31,5 +31,5 @@ public abstract class Controller implements Route { return new Gson().toJson(handle(req, response)); } - public abstract R handle(Q request, Response response) throws Exception; + public abstract R handle(Q request, Response response); } diff --git a/src/main/java/eu/mhsl/minenet/minigames/api/routes/closeRoom/CloseRoom.java b/src/main/java/eu/mhsl/minenet/minigames/api/routes/closeRoom/CloseRoom.java index bdc9a2e..511723b 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/api/routes/closeRoom/CloseRoom.java +++ b/src/main/java/eu/mhsl/minenet/minigames/api/routes/closeRoom/CloseRoom.java @@ -10,7 +10,7 @@ record Req(UUID room) {} record Resp() {} public class CloseRoom extends Controller { @Override - public Resp handle(Req request, Response response) throws Exception { + public Resp handle(Req request, Response response) { Room.deleteRoom(Room.getRoom(request.room()).orElseThrow()); return new Resp(); } diff --git a/src/main/java/eu/mhsl/minenet/minigames/api/routes/createRoom/CreateRoom.java b/src/main/java/eu/mhsl/minenet/minigames/api/routes/createRoom/CreateRoom.java index eafa36e..aefe365 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/api/routes/createRoom/CreateRoom.java +++ b/src/main/java/eu/mhsl/minenet/minigames/api/routes/createRoom/CreateRoom.java @@ -10,7 +10,7 @@ record Req() {} record Resp(UUID uuid) {} public class CreateRoom extends Controller { @Override - public Resp handle(Req request, Response response) throws Exception { + public Resp handle(Req request, Response response) { Room createdRoom = Room.createOwnerlessRoom(); return new Resp(createdRoom.uuid); } diff --git a/src/main/java/eu/mhsl/minenet/minigames/api/routes/queueRoom/QueueRoom.java b/src/main/java/eu/mhsl/minenet/minigames/api/routes/queueRoom/QueueRoom.java index 6426b5f..a5cf128 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/api/routes/queueRoom/QueueRoom.java +++ b/src/main/java/eu/mhsl/minenet/minigames/api/routes/queueRoom/QueueRoom.java @@ -3,17 +3,22 @@ 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 net.minestom.server.MinecraftServer; import spark.Response; import java.util.UUID; record Req(UUID player, UUID room) {} -record Resp() {} +record Resp(String error) {} public class QueueRoom extends Controller { @Override - public Resp handle(Req request, Response response) throws Exception { - if(Room.getRoom(request.room()).isEmpty()) throw new Exception("Room not found"); + public Resp handle(Req request, Response response) { + if(Room.getRoom(request.room()).isEmpty()) return new Resp("Raum nicht gefunden"); + if(MinecraftServer.getConnectionManager().getOnlinePlayers().size() >= Integer.parseInt(System.getProperty("minenet.playerlimit", "999"))) { + return new Resp("Der Server hat eine Spielerzahllimitierung und ist bereits voll!"); + } + QueuedPlayerRooms.queuePlayer(request.player(), request.room()); - return new Resp(); + return new Resp(null); } } diff --git a/src/main/java/eu/mhsl/minenet/minigames/command/Commands.java b/src/main/java/eu/mhsl/minenet/minigames/command/Commands.java index 860b2c3..a15aba4 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/command/Commands.java +++ b/src/main/java/eu/mhsl/minenet/minigames/command/Commands.java @@ -24,7 +24,15 @@ public enum Commands { FAKEPLAYER(new FakeplayerCommand()), KICK(new KickCommand()), SKIN(new SkinCommand()), - SETOWNER(new SetRoomOwnerCommand()); + SETOWNER(new SetRoomOwnerCommand()), + SETREWARD(new SetRewardCommand()), + PUBLISHREWARD(new PublishRewardCommand()), + ROOMPROXYMOVE(new InstanceProxyMoveCommand()), + GAMESTART(new GameStartCommand()), + GAMESTOP(new GameStopCommand()), + GAMETIMEOUT(new GameTimeoutCommand()), + PLAYERLIMIT(new PlayerLimitCommand()), + SETMEMORIAL(new SetMemorialCommand()); Commands(Command handler) { MinecraftServer.getCommandManager().register(handler); diff --git a/src/main/java/eu/mhsl/minenet/minigames/command/privileged/GameStartCommand.java b/src/main/java/eu/mhsl/minenet/minigames/command/privileged/GameStartCommand.java new file mode 100644 index 0000000..1e591a8 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/command/privileged/GameStartCommand.java @@ -0,0 +1,17 @@ +package eu.mhsl.minenet.minigames.command.privileged; + +import eu.mhsl.minenet.minigames.command.PrivilegedCommand; +import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame; +import net.minestom.server.entity.Player; + +public class GameStartCommand extends PrivilegedCommand { + public GameStartCommand() { + super("gameStart"); + setDefaultExecutor((sender, context) -> { + Player player = (Player) sender; + if(player.getInstance() instanceof StatelessGame game) { + game.startAccessor(); + } + }); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/command/privileged/GameStopCommand.java b/src/main/java/eu/mhsl/minenet/minigames/command/privileged/GameStopCommand.java new file mode 100644 index 0000000..addbcd3 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/command/privileged/GameStopCommand.java @@ -0,0 +1,17 @@ +package eu.mhsl.minenet.minigames.command.privileged; + +import eu.mhsl.minenet.minigames.command.PrivilegedCommand; +import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame; +import net.minestom.server.entity.Player; + +public class GameStopCommand extends PrivilegedCommand { + public GameStopCommand() { + super("gameStop"); + setDefaultExecutor((sender, context) -> { + Player player = (Player) sender; + if(player.getInstance() instanceof StatelessGame game) { + game.stop(); + } + }); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/command/privileged/GameTimeoutCommand.java b/src/main/java/eu/mhsl/minenet/minigames/command/privileged/GameTimeoutCommand.java new file mode 100644 index 0000000..8e3c1b8 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/command/privileged/GameTimeoutCommand.java @@ -0,0 +1,22 @@ +package eu.mhsl.minenet.minigames.command.privileged; + +import eu.mhsl.minenet.minigames.command.PrivilegedCommand; +import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame; +import net.minestom.server.command.builder.arguments.ArgumentType; +import net.minestom.server.command.builder.arguments.number.ArgumentInteger; +import net.minestom.server.entity.Player; + +public class GameTimeoutCommand extends PrivilegedCommand { + public GameTimeoutCommand() { + super("gameTimeout"); + + ArgumentInteger timeout = ArgumentType.Integer("timeout"); + + addSyntax((sender, context) -> { + Player player = (Player) sender; + if(player.getInstance() instanceof StatelessGame game) { + game.setTimeLimit(context.get(timeout)); + } + }, timeout); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/command/privileged/InstanceProxyMoveCommand.java b/src/main/java/eu/mhsl/minenet/minigames/command/privileged/InstanceProxyMoveCommand.java new file mode 100644 index 0000000..084760f --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/command/privileged/InstanceProxyMoveCommand.java @@ -0,0 +1,24 @@ +package eu.mhsl.minenet.minigames.command.privileged; + +import eu.mhsl.minenet.minigames.command.PrivilegedCommand; +import eu.mhsl.minenet.minigames.instance.room.Room; +import eu.mhsl.minenet.minigames.util.PluginMessageUtil; +import net.minestom.server.command.builder.arguments.ArgumentWord; +import net.minestom.server.entity.Player; +import net.minestom.server.instance.Instance; + +public class InstanceProxyMoveCommand extends PrivilegedCommand { + public InstanceProxyMoveCommand() { + super("instanceProxyMove"); + + ArgumentWord serverArgument = new ArgumentWord("server"); + + addSyntax((sender, context) -> { + Instance room = ((Player) sender).getInstance(); + room.getPlayers().forEach(player -> { + Room.unsetRoom(player); + PluginMessageUtil.connect(player, context.get(serverArgument)); + }); + }, serverArgument); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/command/privileged/PlayerLimitCommand.java b/src/main/java/eu/mhsl/minenet/minigames/command/privileged/PlayerLimitCommand.java new file mode 100644 index 0000000..7b50a72 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/command/privileged/PlayerLimitCommand.java @@ -0,0 +1,17 @@ +package eu.mhsl.minenet.minigames.command.privileged; + +import eu.mhsl.minenet.minigames.command.PrivilegedCommand; +import net.minestom.server.command.builder.arguments.ArgumentType; +import net.minestom.server.command.builder.arguments.number.ArgumentInteger; + +public class PlayerLimitCommand extends PrivilegedCommand { + public PlayerLimitCommand() { + super("playerLimit"); + + ArgumentInteger count = ArgumentType.Integer("count"); + + addSyntax((sender, context) -> { + System.setProperty("minenet.playerlimit", String.valueOf(context.get(count))); + }, count); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/command/privileged/PublishRewardCommand.java b/src/main/java/eu/mhsl/minenet/minigames/command/privileged/PublishRewardCommand.java new file mode 100644 index 0000000..b72ea14 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/command/privileged/PublishRewardCommand.java @@ -0,0 +1,39 @@ +package eu.mhsl.minenet.minigames.command.privileged; + +import com.google.gson.Gson; +import eu.mhsl.minenet.minigames.command.PrivilegedCommand; +import eu.mhsl.minenet.minigames.instance.room.Room; +import eu.mhsl.minenet.minigames.score.tournament.TournamentDisplay; +import net.minestom.server.entity.Player; + +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +public class PublishRewardCommand extends PrivilegedCommand { + private final HttpClient rewardPublishClient = HttpClient.newHttpClient(); + public PublishRewardCommand() { + super("publishReward"); + + setDefaultExecutor((sender, context) -> { + try { + Room room = Room.getRoom((Player) sender).orElseThrow(); + TournamentDisplay world = new TournamentDisplay(room.getTournament()); + room.moveMembersToInstance(world); + + String rewardRequestJson = new Gson().toJson(room.getTournament().getRewards()); + HttpRequest giveRewardsRequest = HttpRequest.newBuilder() + .uri(new URI("http://10.20.6.1:8080/api/event/reward")) + .POST(HttpRequest.BodyPublishers.ofString(rewardRequestJson)) + .build(); + + room.getTournament().getRewards(); + HttpResponse rawResponse = rewardPublishClient.send(giveRewardsRequest, HttpResponse.BodyHandlers.discarding()); + sender.sendMessage(String.format("Rewards published: HTTP %s", rawResponse.statusCode())); + } catch (Exception e) { + sender.sendMessage(e.getMessage()); + } + }); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/command/privileged/SetMemorialCommand.java b/src/main/java/eu/mhsl/minenet/minigames/command/privileged/SetMemorialCommand.java new file mode 100644 index 0000000..c18dd63 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/command/privileged/SetMemorialCommand.java @@ -0,0 +1,57 @@ +package eu.mhsl.minenet.minigames.command.privileged; + +import eu.mhsl.minenet.minigames.command.PrivilegedCommand; +import eu.mhsl.minenet.minigames.instance.room.Room; +import eu.mhsl.minenet.minigames.score.tournament.MemorialConfiguration; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.minestom.server.command.builder.arguments.ArgumentString; +import net.minestom.server.command.builder.arguments.ArgumentType; +import net.minestom.server.command.builder.suggestion.SuggestionEntry; +import net.minestom.server.entity.Player; +import net.minestom.server.item.Material; + + +public class SetMemorialCommand extends PrivilegedCommand { + public SetMemorialCommand() { + super("setMemorial"); + + ArgumentString materialArgument = ArgumentType.String("material"); + ArgumentString titleArgument = ArgumentType.String("title"); + ArgumentString loreArgument = ArgumentType.String("lore"); + + materialArgument.setSuggestionCallback((sender, context, suggestion) -> { + Material + .values() + .stream() + .map(material -> new SuggestionEntry(material.name(), Component.text(material.name()))) + .forEach(suggestion::addEntry); + }); + + addSyntax((sender, context) -> { + Room + .getRoom((Player) sender) + .orElseThrow() + .getTournament() + .setMemorialConfiguration( + new MemorialConfiguration( + Material.fromNamespaceId(context.get(materialArgument)), + context.get(titleArgument), + context.get(loreArgument) + ) + ); + + sender.sendMessage( + Component.text() + .append(Component.text("Memorial gesetzt:", NamedTextColor.GOLD)) + .appendNewline() + .append(Component.text(context.get(materialArgument), NamedTextColor.AQUA)) + .appendNewline() + .append(Component.text(context.get(titleArgument), NamedTextColor.RED)) + .appendNewline() + .append(Component.text(context.get(loreArgument), NamedTextColor.DARK_RED)) + .build() + ); + }, materialArgument, titleArgument, loreArgument); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/command/privileged/SetRewardCommand.java b/src/main/java/eu/mhsl/minenet/minigames/command/privileged/SetRewardCommand.java new file mode 100644 index 0000000..659a610 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/command/privileged/SetRewardCommand.java @@ -0,0 +1,56 @@ +package eu.mhsl.minenet.minigames.command.privileged; + +import eu.mhsl.minenet.minigames.command.PrivilegedCommand; +import eu.mhsl.minenet.minigames.instance.room.Room; +import eu.mhsl.minenet.minigames.score.tournament.RewardConfiguration; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.minestom.server.command.builder.arguments.ArgumentStringArray; +import net.minestom.server.command.builder.arguments.ArgumentType; +import net.minestom.server.command.builder.arguments.ArgumentWord; +import net.minestom.server.command.builder.suggestion.SuggestionEntry; +import net.minestom.server.entity.Player; +import net.minestom.server.item.Material; + +import java.util.Arrays; +import java.util.stream.Collectors; + +public class SetRewardCommand extends PrivilegedCommand { + public SetRewardCommand() { + super("setRewards"); + + ArgumentWord materialArgument = ArgumentType.Word("material"); + ArgumentStringArray amountsArgument = ArgumentType.StringArray("amount"); + + materialArgument.setSuggestionCallback((sender, context, suggestion) -> { + Material + .values() + .stream() + .map(material -> new SuggestionEntry(material.name(), Component.text(material.name()))) + .forEach(suggestion::addEntry); + }); + + addSyntax((sender, context) -> { + Room + .getRoom((Player) sender) + .orElseThrow() + .getTournament() + .setRewardConfiguration( + new RewardConfiguration( + Material.fromNamespaceId(context.get(materialArgument)), + Arrays.stream(context.get(amountsArgument)).map(Integer::valueOf).collect(Collectors.toList()) + ) + ); + + sender.sendMessage( + Component.text() + .append(Component.text("Belohnung gesetzt:", NamedTextColor.GOLD)) + .appendNewline() + .append(Component.text(context.get(materialArgument), NamedTextColor.AQUA)) + .appendNewline() + .append(Component.text(String.join(", ", context.get(amountsArgument)), NamedTextColor.RED)) + .build() + ); + }, materialArgument, amountsArgument); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/handler/Listeners.java b/src/main/java/eu/mhsl/minenet/minigames/handler/Listeners.java index c2a86c9..f59fa10 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/handler/Listeners.java +++ b/src/main/java/eu/mhsl/minenet/minigames/handler/Listeners.java @@ -1,9 +1,6 @@ package eu.mhsl.minenet.minigames.handler; -import eu.mhsl.minenet.minigames.handler.global.AddEntityToInstanceEventListener; -import eu.mhsl.minenet.minigames.handler.global.PlayerChatHandler; -import eu.mhsl.minenet.minigames.handler.global.PlayerLeaveHandler; -import eu.mhsl.minenet.minigames.handler.global.PlayerLoginHandler; +import eu.mhsl.minenet.minigames.handler.global.*; import net.minestom.server.MinecraftServer; import net.minestom.server.event.EventListener; diff --git a/src/main/java/eu/mhsl/minenet/minigames/handler/global/PlayerLeaveHandler.java b/src/main/java/eu/mhsl/minenet/minigames/handler/global/PlayerLeaveHandler.java index 7a9658f..fcfc4bb 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/handler/global/PlayerLeaveHandler.java +++ b/src/main/java/eu/mhsl/minenet/minigames/handler/global/PlayerLeaveHandler.java @@ -1,8 +1,5 @@ package eu.mhsl.minenet.minigames.handler.global; -import eu.mhsl.minenet.minigames.message.Icon; -import eu.mhsl.minenet.minigames.message.type.ChatMessage; -import net.minestom.server.MinecraftServer; import net.minestom.server.entity.Player; import net.minestom.server.event.EventListener; import net.minestom.server.event.player.PlayerDisconnectEvent; @@ -17,7 +14,7 @@ public class PlayerLeaveHandler implements EventListener @Override public @NotNull Result run(@NotNull PlayerDisconnectEvent event) { Player p = event.getPlayer(); - new ChatMessage(Icon.SCIENCE).appendStatic("unübersetzter Leavetext: ").appendStatic(p.getDisplayName()).send(MinecraftServer.getConnectionManager().getOnlinePlayers()); +// new ChatMessage(Icon.SCIENCE).appendStatic("unübersetzter Leavetext: ").appendStatic(p.getDisplayName()).send(MinecraftServer.getConnectionManager().getOnlinePlayers()); return Result.SUCCESS; } } diff --git a/src/main/java/eu/mhsl/minenet/minigames/handler/global/PlayerLoginHandler.java b/src/main/java/eu/mhsl/minenet/minigames/handler/global/PlayerLoginHandler.java index 04b0a93..08cc437 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/handler/global/PlayerLoginHandler.java +++ b/src/main/java/eu/mhsl/minenet/minigames/handler/global/PlayerLoginHandler.java @@ -4,8 +4,6 @@ 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.instance.transfer.Transfer; -import eu.mhsl.minenet.minigames.message.Icon; -import eu.mhsl.minenet.minigames.message.type.ChatMessage; import eu.mhsl.minenet.minigames.skin.SkinCache; import eu.mhsl.minenet.minigames.util.MoveInstance; import net.minestom.server.MinecraftServer; @@ -60,7 +58,7 @@ public class PlayerLoginHandler implements EventListener { Logger.getLogger("user").info(p.getUsername() + " joined"); - new ChatMessage(Icon.SCIENCE).appendStatic("unübersetzter Jointext: ").appendStatic(p.getUsername()).send(MinecraftServer.getConnectionManager().getOnlinePlayers()); +// new ChatMessage(Icon.SCIENCE).appendStatic("unübersetzter Jointext: ").appendStatic(p.getUsername()).send(MinecraftServer.getConnectionManager().getOnlinePlayers()); return Result.SUCCESS; } diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/Game.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/Game.java index cf120d6..f06a073 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/Game.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/Game.java @@ -60,7 +60,7 @@ public abstract class Game extends MineNetInstance implements Spawnable { Game game = factory.manufacture(Room.getRoom(owner).orElseThrow(), options); game.load(); - Room.getRoom(owner).orElseThrow().moveMembersToGame(game); + Room.getRoom(owner).orElseThrow().moveMembersToInstance(game); } catch (Exception e) { new ChatMessage(Icon.ERROR).appendStatic("Instance crashed: " + e.getMessage()).send(owner); @@ -76,7 +76,7 @@ public abstract class Game extends MineNetInstance implements Spawnable { scheduler().submitTask(() -> { CompletableFuture callback = new CompletableFuture<>(); this.onLoad(callback); - callback.whenComplete((unused, throwable) -> this.start()); +// callback.whenComplete((unused, throwable) -> this.start()); return TaskSchedule.stop(); }, ExecutionType.ASYNC); diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/StatelessGame.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/StatelessGame.java index 4509c35..fcc9a78 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/StatelessGame.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/StatelessGame.java @@ -22,7 +22,6 @@ public class StatelessGame extends Game { private int timeLimit = 0; private int timePlayed = 0; - private final boolean preventExit = false; public StatelessGame(DimensionType dimensionType, String gameName, Score score) { super(dimensionType); this.score = score; @@ -39,6 +38,25 @@ public class StatelessGame extends Game { public void setTimeLimit(int limit) { this.timeLimit = limit; + if(timeLimit > 0) { + scheduler().submitTask(() -> { + if(!isRunning || timeLimit == 0) return TaskSchedule.stop(); + if(timeLimit <= timePlayed) { + stop(); + return TaskSchedule.stop(); + } + + int timeLeft = timeLimit - timePlayed; + switch (timeLeft) { + case 60, 30, 10, 5, 4, 3, 2, 1 -> + new ChatMessage(Icon.SCIENCE).appendStatic("Noch " + timeLeft + " Sekunden!").send(getPlayers()); + } + + timePlayed++; + + return TaskSchedule.seconds(1); + }, ExecutionType.SYNC); + } } @Override @@ -59,47 +77,29 @@ public class StatelessGame extends Game { } + public void startAccessor() { + this.start(); + } @Override protected void start() { score.setInstance(this); score.attachListeners(); - countdownStart().thenRun(() -> { - super.start(); - - if(timeLimit > 0) { - scheduler().submitTask(() -> { - if(!isRunning || timeLimit == 0) return TaskSchedule.stop(); - if(timeLimit <= timePlayed) { - stop(); - return TaskSchedule.stop(); - } - - int timeLeft = timeLimit - timePlayed; - switch (timeLeft) { - case 60, 30, 10, 5, 4, 3, 2, 1 -> - new ChatMessage(Icon.SCIENCE).appendStatic("Noch " + timeLeft + " Sekunden!").send(getPlayers()); - } - - timePlayed++; - - return TaskSchedule.seconds(1); - }, ExecutionType.SYNC); - } - }); + countdownStart().thenRun(super::start); } @Override public void stop() { isRunning = false; this.onStop(); + getScore().insertRemainingPlayers(getPlayers()); this.publishScore(getScore()); countdownUnload(); } private void countdownUnload() { - new TitleMessage(Duration.ofSeconds(1)).appendStatic("Finish").send(getPlayers()); + new TitleMessage(Duration.ofSeconds(1)).appendTranslated("score#done").send(getPlayers()); scheduler().scheduleTask(this::unload, TaskSchedule.seconds(5), TaskSchedule.stop()); } } diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/room/Room.java b/src/main/java/eu/mhsl/minenet/minigames/instance/room/Room.java index de4392f..a8c29f5 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/room/Room.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/room/Room.java @@ -2,8 +2,6 @@ package eu.mhsl.minenet.minigames.instance.room; import eu.mhsl.minenet.minigames.Resource; import eu.mhsl.minenet.minigames.instance.MineNetInstance; -import eu.mhsl.minenet.minigames.instance.game.Game; -import eu.mhsl.minenet.minigames.message.Icon; import eu.mhsl.minenet.minigames.message.type.ChatMessage; import eu.mhsl.minenet.minigames.score.tournament.Tournament; import eu.mhsl.minenet.minigames.util.CommonEventHandles; @@ -139,8 +137,7 @@ public class Room extends MineNetInstance implements Spawnable { }); } - public void moveMembersToGame(Game game) { - logger.info("Move room group with " + this.getAllMembers().size() + " players to Game " + game.getUniqueId()); + public void moveMembersToInstance(Spawnable game) { this.getAllMembers().forEach(player -> MoveInstance.move(player, game)); } diff --git a/src/main/java/eu/mhsl/minenet/minigames/score/Score.java b/src/main/java/eu/mhsl/minenet/minigames/score/Score.java index 6b758a2..92d7385 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/score/Score.java +++ b/src/main/java/eu/mhsl/minenet/minigames/score/Score.java @@ -55,8 +55,9 @@ public abstract class Score { this.checkGameEnd(); } - private void insertRemainingPlayers(Set players) { + public void insertRemainingPlayers(Set players) { this.insertResultImplementation(players.stream().filter(p -> !hasResult(p)).collect(Collectors.toSet())); + setDone(); } public boolean hasResult(Player p) { diff --git a/src/main/java/eu/mhsl/minenet/minigames/score/tournament/MemorialConfiguration.java b/src/main/java/eu/mhsl/minenet/minigames/score/tournament/MemorialConfiguration.java new file mode 100644 index 0000000..bdb002a --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/score/tournament/MemorialConfiguration.java @@ -0,0 +1,6 @@ +package eu.mhsl.minenet.minigames.score.tournament; + +import net.minestom.server.item.Material; + +public record MemorialConfiguration(Material memorialMaterial, String memorialTitle, String memorialLore) { +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/score/tournament/RewardConfiguration.java b/src/main/java/eu/mhsl/minenet/minigames/score/tournament/RewardConfiguration.java new file mode 100644 index 0000000..0a3fb7c --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/score/tournament/RewardConfiguration.java @@ -0,0 +1,8 @@ +package eu.mhsl.minenet.minigames.score.tournament; + +import net.minestom.server.item.Material; + +import java.util.List; + +public record RewardConfiguration(Material item, List rewardCount) { +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/score/tournament/Rewards.java b/src/main/java/eu/mhsl/minenet/minigames/score/tournament/Rewards.java new file mode 100644 index 0000000..ed62832 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/score/tournament/Rewards.java @@ -0,0 +1,8 @@ +package eu.mhsl.minenet.minigames.score.tournament; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public record Rewards(String memorialMaterial, String memorialTitle, String memorialLore, List memorials, String material, Map rewards) { +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/score/tournament/Tournament.java b/src/main/java/eu/mhsl/minenet/minigames/score/tournament/Tournament.java index 08e086b..8c2cc90 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/score/tournament/Tournament.java +++ b/src/main/java/eu/mhsl/minenet/minigames/score/tournament/Tournament.java @@ -3,26 +3,88 @@ package eu.mhsl.minenet.minigames.score.tournament; import eu.mhsl.minenet.minigames.score.Score; import net.minestom.server.entity.Player; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.util.*; public class Tournament { - private final List scores = new ArrayList<>(); + private final List gameScores = new ArrayList<>(); + private RewardConfiguration rewardConfiguration; + private MemorialConfiguration memorialConfiguration; public void addScore(Score score) { - this.scores.add(score); + this.gameScores.add(score); } public int getScoreCount() { - return this.scores.size(); + return this.gameScores.size(); } public void reset() { - this.scores.clear(); + this.gameScores.clear(); } - public List> getScores() { - return null; + + public Map getGameScores() { + Map data = new HashMap<>(); + gameScores.forEach(game -> { + int count = 0; + for (Set players : game.getScores()) { + count++; + for (Player player : players) { + int points = (game.getScores().size() - count) + boost(count, game.getScores().size()); + + data.computeIfPresent(player, (existingPlayer, existingPoints) -> existingPoints + points); + data.computeIfAbsent(player, newPlayer -> points); + } + } + }); + return data; + } + + public Rewards getRewards() { + Map itemCount = new HashMap<>(); + int count = 0; + for (Player player : getPlaces()) { + if(count >= this.rewardConfiguration.rewardCount().size()) break; + itemCount.put(player.getUuid(), this.rewardConfiguration.rewardCount().get(count)); + count++; + } + + return new Rewards( + this.memorialConfiguration.memorialMaterial().namespace().value(), + this.memorialConfiguration.memorialTitle(), + this.memorialConfiguration.memorialLore(), + getPlaces().stream().map(Player::getUuid).toList(), + this.rewardConfiguration.item().namespace().value(), + itemCount + ); + } + + public List getPlaces() { + List players = new ArrayList<>( + getGameScores().entrySet().stream() + .sorted(Map.Entry.comparingByValue()) + .map(Map.Entry::getKey) + .toList() + ); + + Collections.reverse(players); + return players; + } + + private int boost(int selfPlace, int placeCount) { + return switch (selfPlace) { + case 0 -> placeCount / 3; + case 1 -> placeCount / 4; + case 2 -> placeCount / 5; + default -> 0; + }; + } + + public void setRewardConfiguration(RewardConfiguration rewardConfiguration) { + this.rewardConfiguration = rewardConfiguration; + } + + public void setMemorialConfiguration(MemorialConfiguration memorialConfiguration) { + this.memorialConfiguration = memorialConfiguration; } } diff --git a/src/main/java/eu/mhsl/minenet/minigames/score/tournament/TournamentDisplay.java b/src/main/java/eu/mhsl/minenet/minigames/score/tournament/TournamentDisplay.java new file mode 100644 index 0000000..40b524b --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/score/tournament/TournamentDisplay.java @@ -0,0 +1,67 @@ +package eu.mhsl.minenet.minigames.score.tournament; + +import eu.mhsl.minenet.minigames.Resource; +import eu.mhsl.minenet.minigames.instance.Dimension; +import eu.mhsl.minenet.minigames.instance.MineNetInstance; +import eu.mhsl.minenet.minigames.instance.Spawnable; +import eu.mhsl.minenet.minigames.message.Icon; +import eu.mhsl.minenet.minigames.message.type.ChatMessage; +import net.minestom.server.MinecraftServer; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.entity.*; +import net.minestom.server.event.player.PlayerMoveEvent; +import net.minestom.server.instance.AnvilLoader; + +import java.util.List; + +public class TournamentDisplay extends MineNetInstance implements Spawnable { + private final List places; + private final Tournament tournament; + + private final Pos[] placePositions = new Pos[] { + new Pos(8.5, -57, 21.5, 180, 0), + new Pos(9.5, -58, 21.5, 180, 0), + new Pos(7.5, -59, 21.5, 180, 0) + }; + + public TournamentDisplay(Tournament tournament) { + super(Dimension.OVERWORLD.DIMENSION); + setChunkLoader(new AnvilLoader(Resource.RESULT_DISPLAY.getPath())); + this.places = tournament.getPlaces(); + this.tournament = tournament; + + eventNode().addListener(PlayerMoveEvent.class, playerMoveEvent -> { + if(isOnDisplay(playerMoveEvent.getPlayer()) && !playerMoveEvent.getNewPosition().sameBlock(placePositions[getRankPosition(playerMoveEvent.getPlayer())])) { + playerMoveEvent.setCancelled(true); + } + }); + } + + private boolean isOnDisplay(Player player) { + if(getRankPosition(player) == -1) return false; + return getRankPosition(player) < this.placePositions.length; + } + + private int getRankPosition(Player player) { + return this.places.indexOf(player); + } + + @Override + protected boolean onPlayerJoin(Player p) { + MinecraftServer.getSchedulerManager().scheduleNextTick(() -> { + if(isOnDisplay(p)) { + p.sendMessage("You are on Display!"); + p.teleport(placePositions[getRankPosition(p)]); + } + }); + new ChatMessage(Icon.STAR) + .numberedList(this.places.stream().map(player -> String.format("%s - %s Punkte", player.getUsername(), tournament.getGameScores().get(player))).toList()) + .send(p); + return false; + } + + @Override + public Pos getSpawn() { + return new Pos(8.5, -55, 8.5); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/util/PluginMessageUtil.java b/src/main/java/eu/mhsl/minenet/minigames/util/PluginMessageUtil.java new file mode 100644 index 0000000..a84b488 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/util/PluginMessageUtil.java @@ -0,0 +1,16 @@ +package eu.mhsl.minenet.minigames.util; + +import com.google.common.io.ByteArrayDataOutput; +import com.google.common.io.ByteStreams; +import net.minestom.server.entity.Player; +import net.minestom.server.network.packet.server.play.PluginMessagePacket; + +public class PluginMessageUtil { + private static final String bungeeTargetSelector = "bungeecord:main"; + public static void connect(Player p, String bungeeServerTargetName) { + ByteArrayDataOutput out = ByteStreams.newDataOutput(); + out.writeUTF("Connect"); + out.writeUTF(bungeeServerTargetName); + p.sendPacket(new PluginMessagePacket(bungeeTargetSelector, out.toByteArray())); + } +} diff --git a/src/main/resources/lang/.~lock.locales.map.csv# b/src/main/resources/lang/.~lock.locales.map.csv# deleted file mode 100644 index f8a775c..0000000 --- a/src/main/resources/lang/.~lock.locales.map.csv# +++ /dev/null @@ -1 +0,0 @@ -,elias,ELIAS-PC,07.01.2023 22:39,file:///home/elias/.config/libreoffice/4; \ No newline at end of file diff --git a/src/main/resources/lang/locales.map.csv b/src/main/resources/lang/locales.map.csv index bc31d23..9dc3d69 100644 --- a/src/main/resources/lang/locales.map.csv +++ b/src/main/resources/lang/locales.map.csv @@ -36,9 +36,10 @@ 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 +thanks;Thank you for Playing;Danke für's spielen +finish;You did it;Du hast es geschafft death;You are out;Du hast verloren +done;Finish;Fertig ;; ns:restriction#;; fail;Some requirements are not met;Bedinungen sind nicht erfüllt diff --git a/src/main/resources/maps/resultdisplay/region/r.-1.-1.mca b/src/main/resources/maps/resultdisplay/region/r.-1.-1.mca new file mode 100644 index 0000000..e2f33c3 Binary files /dev/null and b/src/main/resources/maps/resultdisplay/region/r.-1.-1.mca differ diff --git a/src/main/resources/maps/resultdisplay/region/r.-1.-2.mca b/src/main/resources/maps/resultdisplay/region/r.-1.-2.mca new file mode 100644 index 0000000..81c018d Binary files /dev/null and b/src/main/resources/maps/resultdisplay/region/r.-1.-2.mca differ diff --git a/src/main/resources/maps/resultdisplay/region/r.-1.0.mca b/src/main/resources/maps/resultdisplay/region/r.-1.0.mca new file mode 100644 index 0000000..2826910 Binary files /dev/null and b/src/main/resources/maps/resultdisplay/region/r.-1.0.mca differ diff --git a/src/main/resources/maps/resultdisplay/region/r.-1.1.mca b/src/main/resources/maps/resultdisplay/region/r.-1.1.mca new file mode 100644 index 0000000..75a841e Binary files /dev/null and b/src/main/resources/maps/resultdisplay/region/r.-1.1.mca differ diff --git a/src/main/resources/maps/resultdisplay/region/r.-2.-1.mca b/src/main/resources/maps/resultdisplay/region/r.-2.-1.mca new file mode 100644 index 0000000..00a3d48 Binary files /dev/null and b/src/main/resources/maps/resultdisplay/region/r.-2.-1.mca differ diff --git a/src/main/resources/maps/resultdisplay/region/r.-2.-2.mca b/src/main/resources/maps/resultdisplay/region/r.-2.-2.mca new file mode 100644 index 0000000..0275b48 Binary files /dev/null and b/src/main/resources/maps/resultdisplay/region/r.-2.-2.mca differ diff --git a/src/main/resources/maps/resultdisplay/region/r.-2.0.mca b/src/main/resources/maps/resultdisplay/region/r.-2.0.mca new file mode 100644 index 0000000..4293674 Binary files /dev/null and b/src/main/resources/maps/resultdisplay/region/r.-2.0.mca differ diff --git a/src/main/resources/maps/resultdisplay/region/r.-2.1.mca b/src/main/resources/maps/resultdisplay/region/r.-2.1.mca new file mode 100644 index 0000000..4372bc7 Binary files /dev/null and b/src/main/resources/maps/resultdisplay/region/r.-2.1.mca differ diff --git a/src/main/resources/maps/resultdisplay/region/r.0.-1.mca b/src/main/resources/maps/resultdisplay/region/r.0.-1.mca new file mode 100644 index 0000000..9d5244d Binary files /dev/null and b/src/main/resources/maps/resultdisplay/region/r.0.-1.mca differ diff --git a/src/main/resources/maps/resultdisplay/region/r.0.-2.mca b/src/main/resources/maps/resultdisplay/region/r.0.-2.mca new file mode 100644 index 0000000..4112e71 Binary files /dev/null and b/src/main/resources/maps/resultdisplay/region/r.0.-2.mca differ diff --git a/src/main/resources/maps/resultdisplay/region/r.0.0.mca b/src/main/resources/maps/resultdisplay/region/r.0.0.mca new file mode 100644 index 0000000..4450d36 Binary files /dev/null and b/src/main/resources/maps/resultdisplay/region/r.0.0.mca differ diff --git a/src/main/resources/maps/resultdisplay/region/r.0.1.mca b/src/main/resources/maps/resultdisplay/region/r.0.1.mca new file mode 100644 index 0000000..99d3d69 Binary files /dev/null and b/src/main/resources/maps/resultdisplay/region/r.0.1.mca differ diff --git a/src/main/resources/maps/resultdisplay/region/r.1.-1.mca b/src/main/resources/maps/resultdisplay/region/r.1.-1.mca new file mode 100644 index 0000000..7032780 Binary files /dev/null and b/src/main/resources/maps/resultdisplay/region/r.1.-1.mca differ diff --git a/src/main/resources/maps/resultdisplay/region/r.1.-2.mca b/src/main/resources/maps/resultdisplay/region/r.1.-2.mca new file mode 100644 index 0000000..6267663 Binary files /dev/null and b/src/main/resources/maps/resultdisplay/region/r.1.-2.mca differ diff --git a/src/main/resources/maps/resultdisplay/region/r.1.0.mca b/src/main/resources/maps/resultdisplay/region/r.1.0.mca new file mode 100644 index 0000000..27a3067 Binary files /dev/null and b/src/main/resources/maps/resultdisplay/region/r.1.0.mca differ diff --git a/src/main/resources/maps/resultdisplay/region/r.1.1.mca b/src/main/resources/maps/resultdisplay/region/r.1.1.mca new file mode 100644 index 0000000..52490b7 Binary files /dev/null and b/src/main/resources/maps/resultdisplay/region/r.1.1.mca differ