"Refactored BuildBattle game logic and chunk generator: optimized code structure, improved plot assignment, and enhanced rating system."

This commit is contained in:
MineTec committed 2026-10-15 01:25:59 +02:00
1 parent 7e0c126a0d
commit 53b13b6560
2 files changed
+75 -105

No files matched your search

@@ -6,7 +6,7 @@ import eu.mhsl.minenet.minigames.score.PointsWinScore;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.title.Title; import net.kyori.adventure.title.Title;
import net.minestom.server.MinecraftServer; import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Pos; import net.minestom.server.coordinate.Pos;
import net.minestom.server.entity.GameMode; import net.minestom.server.entity.GameMode;
import net.minestom.server.entity.Player; import net.minestom.server.entity.Player;
@@ -19,22 +19,23 @@ import net.minestom.server.timer.TaskSchedule;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.IntStream;
public class BuildBattle extends StatelessGame { public class BuildBattle extends StatelessGame {
private static final int height = 100; private static final int height = 100;
private int spawnPosx = 0; private static final int plotHalf = BuildBattleChunkgenerator.inner / 2;
private int spawnPosz = 0; private static final int rowCount = 5;
private final int spacing = 39;
private final int rowCount = 5;
private Map<Player, Pos> spawnPositions = new WeakHashMap<>();
private int seconds;
private static final int ratingSeconds = 15; private static final int ratingSeconds = 15;
private final Map<Player, Integer> scores = new HashMap<>(); private static final List<Material> ratingMaterials = List.of(
private final Map<Player, Integer> currentVotes = new HashMap<>(); Material.RED_CONCRETE, Material.ORANGE_CONCRETE, Material.YELLOW_CONCRETE,
private Player currentOwner = null; Material.LIME_CONCRETE, Material.GREEN_CONCRETE
private boolean listenerRegistered = false; );
private static final List<ItemStack> ratingItems = IntStream.range(0, ratingMaterials.size())
.mapToObj(i -> ItemStack.builder(ratingMaterials.get(i))
.customName(Component.text((i + 1) + " Punkte"))
.build())
.toList();
private static final List<String> themes = List.of( private static final List<String> themes = List.of(
"Burg", "Raumschiff", "Unterwasserwelt", "Pizzeria", "Spukhaus", "Burg", "Raumschiff", "Unterwasserwelt", "Pizzeria", "Spukhaus",
"Bauernhof", "Dschungel", "Zukunftsstadt", "Piratenschiff", "Vulkan", "Bauernhof", "Dschungel", "Zukunftsstadt", "Piratenschiff", "Vulkan",
@@ -47,96 +48,84 @@ public class BuildBattle extends StatelessGame {
"Ein Dönerladen im Weltall", "Ein Spa für Enderman", "Der Käse-Palast", "Ein Dönerladen im Weltall", "Ein Spa für Enderman", "Der Käse-Palast",
"Mein Zimmer nach 3 Wochen ohne Aufräumen", "Die Hüpfburg des Todes" "Mein Zimmer nach 3 Wochen ohne Aufräumen", "Die Hüpfburg des Todes"
); );
private String theme = "";
private int spawnPosx = 0;
private int spawnPosz = 0;
private final Map<Player, Pos> spawnPositions = new WeakHashMap<>();
private final int seconds;
private final Map<Player, Integer> currentVotes = new HashMap<>();
private Player currentOwner = null;
public BuildBattle(int seconds) { public BuildBattle(int seconds) {
super(Dimension.THE_END.key, "BluidBattle", new PointsWinScore()); super(Dimension.THE_END.key, "BuildBattle", new PointsWinScore());
this.seconds = seconds; this.seconds = seconds;
this.setGenerator(new BuildBattleChunkgenerator(height)); this.setGenerator(new BuildBattleChunkgenerator(height));
this.eventNode().addListener(PlayerUseItemEvent.class, this::onRatingItemUse);
} }
@Override @Override
protected void onStart() { protected void onStart() {
this.theme = themes.get(this.rnd.nextInt(themes.size())); String theme = themes.get(this.rnd.nextInt(themes.size()));
Title title = Title.title( this.showTitle(Title.title(
Component.text("Thema", NamedTextColor.GOLD), Component.text("Thema", NamedTextColor.GOLD),
Component.text(this.theme, NamedTextColor.YELLOW) Component.text(theme, NamedTextColor.YELLOW)
); ));
this.getPlayers().forEach(player -> { this.sendMessage(Component.text("Euer Thema: ", NamedTextColor.GRAY)
player.showTitle(title); .append(Component.text(theme, NamedTextColor.YELLOW)));
player.sendMessage(Component.text("Euer Thema: ", NamedTextColor.GRAY)
.append(Component.text(this.theme, NamedTextColor.YELLOW)));
});
this.getPlayers().forEach(player -> player.setGameMode(GameMode.CREATIVE)); this.getPlayers().forEach(player -> player.setGameMode(GameMode.CREATIVE));
MinecraftServer.getSchedulerManager() this.scheduler().scheduleTask(this::endBuildPhase, TaskSchedule.seconds(this.seconds), TaskSchedule.stop());
.buildTask(() -> { }
this.getPlayers().forEach(player -> player.sendMessage("Die Bauzeit ist beendet!"));
private void endBuildPhase() {
this.sendMessage(Component.text("Die Bauzeit ist beendet!"));
this.getPlayers().forEach(p -> { this.getPlayers().forEach(p -> {
p.setGameMode(GameMode.ADVENTURE); p.setGameMode(GameMode.ADVENTURE);
p.setAllowFlying(true); p.setAllowFlying(true);
p.setFlying(true); p.setFlying(true);
this.scores.put(p, 0);
}); });
MinecraftServer.getSchedulerManager() this.scheduler().scheduleTask(this::rating, TaskSchedule.seconds(3), TaskSchedule.stop());
.buildTask(() -> {
this.rating();
}).delay(TaskSchedule.seconds(3)).schedule();
}).delay(TaskSchedule.seconds(this.seconds)).schedule();
} }
@Override @Override
protected boolean onPlayerJoin(Player player) { protected boolean onPlayerJoin(Player player) {
Pos spawnPos = new Pos(this.spawnPosx * this.spacing, height, this.spawnPosz * this.spacing); Pos plotCenter = new Pos(
this.spawnPositions.put(player, spawnPos.add(16, 0, 16)); this.spawnPosx * BuildBattleChunkgenerator.period + plotHalf,
height,
this.spawnPosz * BuildBattleChunkgenerator.period + plotHalf
);
this.spawnPositions.put(player, plotCenter);
if(this.spawnPosx >= this.rowCount) { if(this.spawnPosx >= rowCount) {
this.spawnPosx = 0; this.spawnPosx = 0;
this.spawnPosz++; this.spawnPosz++;
} }
this.spawnPosx++; this.spawnPosx++;
player.setGameMode(GameMode.ADVENTURE); player.setGameMode(GameMode.ADVENTURE);
MinecraftServer.getSchedulerManager().scheduleNextTick(() -> this.scheduler().scheduleNextTick(() -> player.teleport(plotCenter.add(0, 1.5, 0)));
player.teleport(spawnPos.add(16, 1.5, 16)));
return super.onPlayerJoin(player); return super.onPlayerJoin(player);
} }
@Override @Override
protected void onBlockBreak(@NotNull PlayerBlockBreakEvent event) { protected void onBlockBreak(@NotNull PlayerBlockBreakEvent event) {
var player = event.getPlayer(); event.setCancelled(!this.isInArea(event.getBlockPosition(), event.getPlayer()));
Pos blockPos = event.getBlockPosition().asPos();
event.setCancelled(!this.isInArea(blockPos, player));
} }
@Override @Override
protected void onBlockPlace(@NotNull PlayerBlockPlaceEvent event) { protected void onBlockPlace(@NotNull PlayerBlockPlaceEvent event) {
var player = event.getPlayer(); event.setCancelled(!this.isInArea(event.getBlockPosition(), event.getPlayer()));
Pos blockPos = event.getBlockPosition().asPos();
event.setCancelled(!this.isInArea(blockPos, player));
} }
private void rating() { private void rating() {
List<Player> owners = new ArrayList<>(this.getPlayers()); Queue<Player> owners = new ArrayDeque<>(this.getPlayers());
this.registerRatingListener();
AtomicInteger index = new AtomicInteger(0); this.scheduler().submitTask(() -> {
MinecraftServer.getSchedulerManager().submitTask(() -> {
if (this.currentOwner != null) this.finishRound(); if (this.currentOwner != null) this.finishRound();
Player next = null; Player next = owners.poll();
while (index.get() < owners.size()) { while (next != null && !(next.isOnline() && this.spawnPositions.containsKey(next))) next = owners.poll();
Player candidate = owners.get(index.getAndIncrement()); if (next == null) return TaskSchedule.stop();
if (candidate.isOnline() && this.spawnPositions.containsKey(candidate)) {
next = candidate;
break;
}
}
if (next == null) {
return TaskSchedule.stop();
}
this.startRound(next); this.startRound(next);
return TaskSchedule.seconds(ratingSeconds); return TaskSchedule.seconds(ratingSeconds);
@@ -148,42 +137,30 @@ public class BuildBattle extends StatelessGame {
this.currentVotes.clear(); this.currentVotes.clear();
Pos plot = this.spawnPositions.get(owner).add(0, 1.5, 0); Pos plot = this.spawnPositions.get(owner).add(0, 1.5, 0);
this.sendMessage(Component.text("Bewerte das Grundstück von " + owner.getUsername() + "!"));
this.getPlayers().forEach(p -> { this.getPlayers().forEach(p -> {
p.teleport(plot); p.teleport(plot);
p.sendMessage(Component.text("Bewerte das Grundstück von " + owner.getUsername() + "!")); p.getInventory().clear();
if (p != owner) this.giveRatingItems(p); if (p != owner) this.giveRatingItems(p);
else p.getInventory().clear();
}); });
} }
private void giveRatingItems(Player player) { private void giveRatingItems(Player player) {
Material[] materials = { for (int i = 0; i < ratingItems.size(); i++) {
Material.RED_CONCRETE, Material.ORANGE_CONCRETE, Material.YELLOW_CONCRETE, player.getInventory().setItemStack(i, ratingItems.get(i));
Material.LIME_CONCRETE, Material.GREEN_CONCRETE
};
player.getInventory().clear();
for (int i = 0; i < materials.length; i++) {
player.getInventory().setItemStack(i, ItemStack.builder(materials[i])
.customName(Component.text((i + 1) + " Punkte"))
.build());
} }
} }
private void registerRatingListener() { private void onRatingItemUse(PlayerUseItemEvent event) {
if (this.listenerRegistered) return;
this.listenerRegistered = true;
this.eventNode().addListener(PlayerUseItemEvent.class, event -> {
Player voter = event.getPlayer(); Player voter = event.getPlayer();
if (this.currentOwner == null || voter == this.currentOwner) return; if (this.currentOwner == null || voter == this.currentOwner) return;
int slot = voter.getHeldSlot(); int slot = voter.getHeldSlot();
if (slot > 4) return; if (slot >= ratingItems.size()) return;
event.setCancelled(true); event.setCancelled(true);
this.currentVotes.put(voter, slot + 1); this.currentVotes.put(voter, slot + 1);
voter.sendMessage(Component.text("Du hast " + (slot + 1) + " Punkte vergeben.")); voter.sendMessage(Component.text("Du hast " + (slot + 1) + " Punkte vergeben."));
});
} }
private void finishRound() { private void finishRound() {
@@ -195,11 +172,13 @@ public class BuildBattle extends StatelessGame {
this.getScore().insertResult(owner, sum); this.getScore().insertResult(owner, sum);
} }
private boolean isInArea(Pos blockToCheck, Player player) { private boolean isInArea(Point block, Player player) {
Pos pos1 = this.spawnPositions.get(player).add(15, 1, 15); Pos center = this.spawnPositions.get(player);
Pos pos2 = this.spawnPositions.get(player).add(-16, 300, -16); double dx = block.x() - center.x();
return blockToCheck.x() >= Math.min(pos1.x(), pos2.x()) && blockToCheck.x() <= Math.max(pos1.x(), pos2.x()) double dy = block.y() - center.y();
&& blockToCheck.y() >= Math.min(pos1.y(), pos2.y()) && blockToCheck.y() <= Math.max(pos1.y(), pos2.y()) double dz = block.z() - center.z();
&& blockToCheck.z() >= Math.min(pos1.z(), pos2.z()) && blockToCheck.z() <= Math.max(pos1.z(), pos2.z()); return dx >= -plotHalf && dx < plotHalf
&& dy >= 1 && dy <= 300
&& dz >= -plotHalf && dz < plotHalf;
} }
} }
@@ -5,43 +5,34 @@ import eu.mhsl.minenet.minigames.world.generator.terrain.BaseGenerator;
import net.minestom.server.instance.block.Block; import net.minestom.server.instance.block.Block;
public class BuildBattleChunkgenerator extends BaseGenerator { public class BuildBattleChunkgenerator extends BaseGenerator {
private static final int inner = 32; static final int inner = 32;
private static final int ring = 3; private static final int ring = 3;
private static final int wall = 1; private static final int wall = 1;
private static final int wallHeight = 200; private static final int wallHeight = 200;
static final int period = wall + ring + inner + ring;
private static final int period = wall + ring + inner + ring; private static final int innerStart = wall + ring;
private static final int innerEnd = innerStart + inner;
private static final int offset = wall + ring;
private static final Block middleBlocks = Block.QUARTZ_BLOCK; private static final Block middleBlocks = Block.QUARTZ_BLOCK;
private static final Block outerBlocks = Block.STONE_BRICKS; private static final Block outerBlocks = Block.STONE_BRICKS;
private static final Block wallBlocks = Block.POLISHED_DEEPSLATE; private static final Block wallBlocks = Block.POLISHED_DEEPSLATE;
public BuildBattleChunkgenerator(int height) { public BuildBattleChunkgenerator(int height) {
this.addMixIn(unit -> { this.addMixIn(unit -> GeneratorUtils.foreachXZ(unit, point -> {
GeneratorUtils.foreachXZ(unit, point -> { int lx = Math.floorMod(point.blockX() + innerStart, period);
int lx = Math.floorMod(point.blockX() + offset, period); int lz = Math.floorMod(point.blockZ() + innerStart, period);
int lz = Math.floorMod(point.blockZ() + offset, period);
boolean isWall = lx < wall || lz < wall;
if (isWall) {
for (int y = 0; y <= wallHeight; y++) {
unit.modifier().setBlock(point.withY(height + y), wallBlocks);
}
return;
}
if (lx < wall || lz < wall) {
unit.modifier().fill(point.withY(height), point.add(1, 0, 1).withY(height + wallHeight + 1), wallBlocks);
} else {
unit.modifier().setBlock(point.withY(height), floorBlock(lx, lz)); unit.modifier().setBlock(point.withY(height), floorBlock(lx, lz));
}); }
}); }));
} }
private static Block floorBlock(int lx, int lz) { private static Block floorBlock(int lx, int lz) {
int innerStart = wall + ring;
int innerEnd = innerStart + inner;
boolean inInner = lx >= innerStart && lx < innerEnd boolean inInner = lx >= innerStart && lx < innerEnd
&& lz >= innerStart && lz < innerEnd; && lz >= innerStart && lz < innerEnd;