Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
331efa9ffd | ||
|
|
7424d6b929 | ||
|
|
a18a6b0dca | ||
|
|
8dc165952a | ||
|
|
4bd03c2603 | ||
|
|
75cd304bda | ||
|
|
26eff149d4 | ||
|
|
7734b225eb | ||
|
|
41753f2805 |
No files matched your search
Generated
+7
@@ -3,4 +3,11 @@
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="21" />
|
||||
</component>
|
||||
<component name="JavacSettings">
|
||||
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
|
||||
<module name="Minigames" options="-Xlint:deprecation" />
|
||||
<module name="Minigames.test" options="-Xlint:deprecation" />
|
||||
<module name="eu.mhsl.minenet.Minigames.main" options="-Xlint:deprecation" />
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
@@ -11,6 +11,7 @@ version '1.0-SNAPSHOT'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url = 'https://mvn.everbuild.org/public' }
|
||||
}
|
||||
|
||||
java {
|
||||
@@ -38,6 +39,9 @@ dependencies {
|
||||
|
||||
//PvP
|
||||
implementation 'io.github.togar2:MinestomPvP:2026.05.30-26.1.1'
|
||||
|
||||
//Block placement
|
||||
implementation 'org.everbuild.blocksandstuff:blocksandstuff-blocks:1.10.2-SNAPSHOT'
|
||||
}
|
||||
|
||||
tasks {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package eu.mhsl.minenet.minigames.handler.global;
|
||||
|
||||
import eu.mhsl.minenet.minigames.Main;
|
||||
import eu.mhsl.minenet.minigames.message.Icon;
|
||||
import eu.mhsl.minenet.minigames.message.type.ChatMessage;
|
||||
import net.kyori.adventure.text.Component;
|
||||
@@ -9,6 +10,9 @@ import net.minestom.server.event.player.PlayerChatEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ChatFormatHandler implements EventListener<PlayerChatEvent> {
|
||||
// Verteilt der Proxy den Chat (chat-bridge bei CraftAttack), darf er hier nicht noch einmal erscheinen
|
||||
private final boolean chatViaProxy = Main.globalConfig.node("velocity", "chat-via-proxy").getBoolean(false);
|
||||
|
||||
@Override
|
||||
public @NotNull Class<PlayerChatEvent> eventType() {
|
||||
return PlayerChatEvent.class;
|
||||
@@ -16,6 +20,10 @@ public class ChatFormatHandler implements EventListener<PlayerChatEvent> {
|
||||
|
||||
@Override
|
||||
public @NotNull Result run(@NotNull PlayerChatEvent event) {
|
||||
if(this.chatViaProxy) {
|
||||
event.setCancelled(true);
|
||||
return Result.SUCCESS;
|
||||
}
|
||||
NamedTextColor color = event.getPlayer().getPermissionLevel() > 0 ? NamedTextColor.AQUA : NamedTextColor.GRAY;
|
||||
event.setFormattedMessage(
|
||||
new ChatMessage(Icon.CHAT)
|
||||
|
||||
+2
-1
@@ -26,6 +26,7 @@ import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.timer.ExecutionType;
|
||||
import net.minestom.server.timer.TaskSchedule;
|
||||
import net.minestom.server.world.DimensionType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -41,7 +42,7 @@ public class Bedwars extends StatelessGame {
|
||||
|
||||
public Bedwars() throws IOException {
|
||||
super(Dimension.OVERWORLD.key, "Bedwars", new LastWinsScore());
|
||||
this.setChunkLoader(new AnvilLoader(Resource.GAME_MAP.getPath().resolve("bedwars/test")));
|
||||
this.setChunkLoader(new AnvilLoader(Resource.GAME_MAP.getPath().resolve("bedwars/test"), DimensionType.OVERWORLD.key()));
|
||||
|
||||
Configuration config = ConfigurationProvider.getProvider(YamlConfiguration.class).load(Resource.GAME_MAP.getPath().resolve("bedwars/test/config.yml").toFile());
|
||||
List<String> teamNames = config.getStringList("setup.teams");
|
||||
|
||||
+2
-1
@@ -15,6 +15,7 @@ import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.player.PlayerMoveEvent;
|
||||
import net.minestom.server.instance.anvil.AnvilLoader;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.world.DimensionType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -23,7 +24,7 @@ import java.util.concurrent.CompletableFuture;
|
||||
public class BoatRace extends StatelessGame {
|
||||
public BoatRace() {
|
||||
super(Dimension.OVERWORLD.key, "boatRace", new FirstWinsScore());
|
||||
this.setChunkLoader(new AnvilLoader(Resource.GAME_MAP.getPath().resolve("boatRace/woodlandMansion")));
|
||||
this.setChunkLoader(new AnvilLoader(Resource.GAME_MAP.getPath().resolve("boatRace/woodlandMansion"), DimensionType.OVERWORLD.key()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+58
-16
@@ -11,8 +11,10 @@ import net.minestom.server.coordinate.Pos;
|
||||
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.PlayerBlockInteractEvent;
|
||||
import net.minestom.server.event.player.PlayerBlockPlaceEvent;
|
||||
import net.minestom.server.event.player.PlayerUseItemEvent;
|
||||
import net.minestom.server.event.player.PlayerUseItemOnBlockEvent;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.timer.TaskSchedule;
|
||||
@@ -60,7 +62,12 @@ public class BuildBattle extends StatelessGame {
|
||||
super(Dimension.THE_END.key, "BuildBattle", new PointsWinScore());
|
||||
this.seconds = seconds;
|
||||
this.setGenerator(new BuildBattleChunkgenerator(height));
|
||||
BuildBattleBlockRules.register();
|
||||
this.eventNode().addListener(PlayerUseItemEvent.class, this::onRatingItemUse);
|
||||
this.eventNode().addListener(PlayerUseItemOnBlockEvent.class, e -> FluidFlowHelper.onBucketUse(e, p -> this.isInArea(p, e.getPlayer())));
|
||||
this.eventNode().addListener(PlayerBlockInteractEvent.class, e -> {
|
||||
if (this.isInArea(e.getBlockPosition(), e.getPlayer())) BuildBattleBlockRules.onInteract(e);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -76,6 +83,21 @@ public class BuildBattle extends StatelessGame {
|
||||
this.getPlayers().forEach(player -> player.setGameMode(GameMode.CREATIVE));
|
||||
|
||||
this.scheduler().scheduleTask(this::endBuildPhase, TaskSchedule.seconds(this.seconds), TaskSchedule.stop());
|
||||
this.scheduleCountdown();
|
||||
}
|
||||
|
||||
private void scheduleCountdown() {
|
||||
int[] marks = {30, 10, 5, 4, 3, 2, 1};
|
||||
for (int m : marks) {
|
||||
if (this.seconds <= m) continue;
|
||||
int remaining = m;
|
||||
this.scheduler().scheduleTask(() -> {
|
||||
NamedTextColor color = remaining <= 5 ? NamedTextColor.RED : (remaining <= 10 ? NamedTextColor.GOLD : NamedTextColor.YELLOW);
|
||||
this.sendMessage(Component.text("Noch ", NamedTextColor.GRAY)
|
||||
.append(Component.text(remaining, color))
|
||||
.append(Component.text(" Sekunde" + (remaining == 1 ? "" : "n") + " Bauzeit!", NamedTextColor.GRAY)));
|
||||
}, TaskSchedule.seconds(this.seconds - m), TaskSchedule.stop());
|
||||
}
|
||||
}
|
||||
|
||||
private void endBuildPhase() {
|
||||
@@ -97,11 +119,11 @@ public class BuildBattle extends StatelessGame {
|
||||
);
|
||||
this.spawnPositions.put(player, plotCenter);
|
||||
|
||||
if(this.spawnPosx >= rowCount) {
|
||||
if(this.spawnPosx >= rowCount - 1) {
|
||||
this.spawnPosx = 0;
|
||||
this.spawnPosz++;
|
||||
}
|
||||
this.spawnPosx++;
|
||||
} else this.spawnPosx ++;
|
||||
|
||||
player.setGameMode(GameMode.ADVENTURE);
|
||||
this.scheduler().scheduleNextTick(() -> player.teleport(plotCenter.add(0, 1.5, 0)));
|
||||
return super.onPlayerJoin(player);
|
||||
@@ -109,12 +131,32 @@ public class BuildBattle extends StatelessGame {
|
||||
|
||||
@Override
|
||||
protected void onBlockBreak(@NotNull PlayerBlockBreakEvent event) {
|
||||
event.setCancelled(!this.isInArea(event.getBlockPosition(), event.getPlayer()));
|
||||
if (!this.isInArea(event.getBlockPosition(), event.getPlayer())) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
FluidFlowHelper.onBreak(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBlockPlace(@NotNull PlayerBlockPlaceEvent event) {
|
||||
event.setCancelled(!this.isInArea(event.getBlockPosition(), event.getPlayer()));
|
||||
if (!this.isInArea(event.getBlockPosition(), event.getPlayer())) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
FluidFlowHelper.onPlace(event);
|
||||
}
|
||||
|
||||
private Pos safeSpawn(Player owner) {
|
||||
Pos center = this.spawnPositions.get(owner);
|
||||
int topY = center.blockY();
|
||||
for (int y = 300; y >= center.blockY(); y--) {
|
||||
if (!this.getBlock(center.blockX(), y, center.blockZ()).isAir()) {
|
||||
topY = y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new Pos(center.x(), topY + 3, center.z()).withView(center.yaw(), center.pitch());
|
||||
}
|
||||
|
||||
private void rating() {
|
||||
@@ -136,7 +178,7 @@ public class BuildBattle extends StatelessGame {
|
||||
this.currentOwner = owner;
|
||||
this.currentVotes.clear();
|
||||
|
||||
Pos plot = this.spawnPositions.get(owner).add(0, 1.5, 0);
|
||||
Pos plot = this.safeSpawn(owner);
|
||||
this.sendMessage(Component.text("Bewerte das Grundstück von " + owner.getUsername() + "!"));
|
||||
this.getPlayers().forEach(p -> {
|
||||
p.teleport(plot);
|
||||
@@ -164,21 +206,21 @@ public class BuildBattle extends StatelessGame {
|
||||
}
|
||||
|
||||
private void finishRound() {
|
||||
int sum = this.currentVotes.values().stream().mapToInt(Integer::intValue).sum();
|
||||
this.getPlayers().forEach(p -> p.getInventory().clear());
|
||||
int voteSum = this.currentVotes.values().stream()
|
||||
.mapToInt(Integer::intValue)
|
||||
.sum();
|
||||
int score = (int) Math.round((double) voteSum / this.getPlayers().size());
|
||||
|
||||
Player owner = this.currentOwner;
|
||||
this.getPlayers().forEach(p -> p.getInventory().clear());
|
||||
this.getScore().insertResult(this.currentOwner, score);
|
||||
this.currentOwner = null;
|
||||
this.getScore().insertResult(owner, sum);
|
||||
}
|
||||
|
||||
private boolean isInArea(Point block, Player player) {
|
||||
Pos center = this.spawnPositions.get(player);
|
||||
double dx = block.x() - center.x();
|
||||
double dy = block.y() - center.y();
|
||||
double dz = block.z() - center.z();
|
||||
return dx >= -plotHalf && dx < plotHalf
|
||||
&& dy >= 1 && dy <= 300
|
||||
&& dz >= -plotHalf && dz < plotHalf;
|
||||
if (center == null) return false;
|
||||
Pos min = new Pos(center.x() - plotHalf, center.y() + 1, center.z() - plotHalf);
|
||||
Pos max = new Pos(center.x() + plotHalf - 1, 300, center.z() + plotHalf - 1);
|
||||
return eu.mhsl.minenet.minigames.util.Position.isInArea(block, min, max);
|
||||
}
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.buildBattle;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.event.player.PlayerBlockInteractEvent;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.instance.block.BlockHandler;
|
||||
import net.minestom.server.instance.block.rule.BlockPlacementRule;
|
||||
import org.everbuild.blocksandstuff.blocks.group.VanillaBlockBehaviour;
|
||||
import org.everbuild.blocksandstuff.blocks.group.VanillaPlacementRules;
|
||||
import org.everbuild.blocksandstuff.blocks.group.behaviour.BehaviourGroup;
|
||||
import org.everbuild.blocksandstuff.blocks.group.placement.PlacementGroup;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public final class BuildBattleBlockRules {
|
||||
private BuildBattleBlockRules() {}
|
||||
|
||||
private static final ThreadLocal<Boolean> interactingInBuildBattle = ThreadLocal.withInitial(() -> false);
|
||||
private static final Map<Integer, BlockHandler> behaviours = new HashMap<>();
|
||||
private static boolean registered = false;
|
||||
|
||||
public static synchronized void register() {
|
||||
if (registered) return;
|
||||
registered = true;
|
||||
|
||||
var blockManager = MinecraftServer.getBlockManager();
|
||||
for (PlacementGroup group : VanillaPlacementRules.INSTANCE.getALL()) {
|
||||
for (Block block : group.getBlockGroup().allMatching()) {
|
||||
blockManager.registerBlockPlacementRule(new BuildBattleOnlyRule(group.createRule(block)));
|
||||
}
|
||||
}
|
||||
|
||||
for (BehaviourGroup group : VanillaBlockBehaviour.INSTANCE.getALL()) {
|
||||
for (Block block : group.getBlockGroup().allMatching()) {
|
||||
behaviours.put(block.id(), group.createHandler(block));
|
||||
}
|
||||
}
|
||||
|
||||
MinecraftServer.getGlobalEventHandler().addListener(PlayerBlockInteractEvent.class,
|
||||
e -> interactingInBuildBattle.set(e.getInstance() instanceof BuildBattle));
|
||||
}
|
||||
|
||||
public static void onInteract(PlayerBlockInteractEvent event) {
|
||||
BlockHandler handler = behaviours.get(event.getBlock().id());
|
||||
if (handler == null) return;
|
||||
boolean continueItemUse = handler.onInteract(new BlockHandler.Interaction(
|
||||
event.getBlock(), event.getInstance(), event.getBlockFace(), event.getBlockPosition(),
|
||||
event.getCursorPosition(), event.getPlayer(), event.getHand()
|
||||
));
|
||||
if (!continueItemUse) event.setBlockingItemUse(true);
|
||||
}
|
||||
|
||||
private static final class BuildBattleOnlyRule extends BlockPlacementRule {
|
||||
private final BlockPlacementRule delegate;
|
||||
|
||||
private BuildBattleOnlyRule(BlockPlacementRule delegate) {
|
||||
super(delegate.getBlock());
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Block blockPlace(PlacementState placementState) {
|
||||
if (!(placementState.instance() instanceof BuildBattle)) return placementState.block();
|
||||
return this.delegate.blockPlace(placementState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block blockUpdate(UpdateState updateState) {
|
||||
if (!(updateState.instance() instanceof BuildBattle)) return updateState.currentBlock();
|
||||
return this.delegate.blockUpdate(updateState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelfReplaceable(Replacement replacement) {
|
||||
return interactingInBuildBattle.get() && this.delegate.isSelfReplaceable(replacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int maxUpdateDistance() {
|
||||
return this.delegate.maxUpdateDistance();
|
||||
}
|
||||
}
|
||||
}
|
||||
+267
@@ -0,0 +1,267 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.buildBattle;
|
||||
|
||||
import net.minestom.server.coordinate.BlockVec;
|
||||
import net.minestom.server.coordinate.Point;
|
||||
import net.minestom.server.event.player.PlayerBlockBreakEvent;
|
||||
import net.minestom.server.event.player.PlayerBlockPlaceEvent;
|
||||
import net.minestom.server.event.player.PlayerUseItemOnBlockEvent;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.timer.TaskSchedule;
|
||||
import net.minestom.server.utils.Direction;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public final class FluidFlowHelper {
|
||||
private FluidFlowHelper() {}
|
||||
|
||||
private static final int WATER_TICK = 5;
|
||||
private static final int LAVA_TICK = 30;
|
||||
private static final int WATER_RANGE = 7;
|
||||
private static final int LAVA_RANGE = 3;
|
||||
private static final int FALLING = 8;
|
||||
|
||||
public static void onBucketUse(PlayerUseItemOnBlockEvent event, Predicate<Point> inArea) {
|
||||
Material m = event.getItemStack().material();
|
||||
Instance inst = event.getPlayer().getInstance();
|
||||
if (inst == null) return;
|
||||
Point hit = event.getPosition();
|
||||
var face = event.getBlockFace();
|
||||
BlockVec placePos = new BlockVec(
|
||||
hit.blockX() + face.toDirection().normalX(),
|
||||
hit.blockY() + face.toDirection().normalY(),
|
||||
hit.blockZ() + face.toDirection().normalZ()
|
||||
);
|
||||
if (!inArea.test(placePos)) return;
|
||||
|
||||
if (m == Material.WATER_BUCKET) {
|
||||
inst.setBlock(placePos, Block.WATER.withProperty("level", "0"));
|
||||
scheduleFlow(inst, placePos, true);
|
||||
} else if (m == Material.LAVA_BUCKET) {
|
||||
inst.setBlock(placePos, Block.LAVA.withProperty("level", "0"));
|
||||
scheduleFlow(inst, placePos, false);
|
||||
} else if (m == Material.BUCKET) {
|
||||
Block existing = inst.getBlock(placePos);
|
||||
if (isWater(existing) || isLava(existing)) inst.setBlock(placePos, Block.AIR);
|
||||
}
|
||||
}
|
||||
|
||||
public static void onPlace(PlayerBlockPlaceEvent event) {
|
||||
Block b = event.getBlock();
|
||||
if (isWater(b) || isLava(b)) {
|
||||
Instance inst = event.getInstance();
|
||||
BlockVec pos = event.getBlockPosition();
|
||||
scheduleFlow(inst, pos, isWater(b));
|
||||
}
|
||||
triggerNeighbors(event.getInstance(), event.getBlockPosition());
|
||||
}
|
||||
|
||||
public static void onBreak(PlayerBlockBreakEvent event) {
|
||||
triggerNeighbors(event.getInstance(), event.getBlockPosition());
|
||||
}
|
||||
|
||||
private static void triggerNeighbors(Instance inst, BlockVec pos) {
|
||||
for (Direction d : Direction.values()) {
|
||||
BlockVec np = new BlockVec(pos.blockX() + d.normalX(), pos.blockY() + d.normalY(), pos.blockZ() + d.normalZ());
|
||||
Block nb = inst.getBlock(np);
|
||||
if (isWater(nb) || isLava(nb)) scheduleFlow(inst, np, isWater(nb));
|
||||
}
|
||||
}
|
||||
|
||||
private static void scheduleFlow(Instance inst, BlockVec pos, boolean water) {
|
||||
int delay = water ? WATER_TICK : LAVA_TICK;
|
||||
inst.scheduler().buildTask(() -> step(inst, pos, water)).delay(TaskSchedule.tick(delay)).schedule();
|
||||
}
|
||||
|
||||
private static void step(Instance inst, BlockVec pos, boolean water) {
|
||||
Block self = inst.getBlock(pos);
|
||||
if (water ? !isWater(self) : !isLava(self)) return;
|
||||
|
||||
int level = parseLevel(self);
|
||||
boolean source = level == 0;
|
||||
boolean falling = level >= FALLING;
|
||||
int flowLevel = source ? 1 : (falling ? 1 : level + 1);
|
||||
int maxRange = water ? WATER_RANGE : LAVA_RANGE;
|
||||
|
||||
if (!source && !falling) {
|
||||
int newLevel = computeIncomingLevel(inst, pos, water, maxRange);
|
||||
if (newLevel == -1) {
|
||||
inst.setBlock(pos, Block.AIR);
|
||||
triggerNeighbors(inst, pos);
|
||||
return;
|
||||
}
|
||||
if (newLevel != level) {
|
||||
inst.setBlock(pos, (water ? Block.WATER : Block.LAVA).withProperty("level", String.valueOf(newLevel)));
|
||||
level = newLevel;
|
||||
flowLevel = level + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (water && !source && countAdjacentSources(inst, pos, true) >= 2
|
||||
&& hasSolidBelow(inst, pos)) {
|
||||
inst.setBlock(pos, Block.WATER.withProperty("level", "0"));
|
||||
scheduleFlow(inst, pos, true);
|
||||
triggerNeighbors(inst, pos);
|
||||
return;
|
||||
}
|
||||
|
||||
BlockVec below = new BlockVec(pos.blockX(), pos.blockY() - 1, pos.blockZ());
|
||||
Block belowBlock = inst.getBlock(below);
|
||||
if (isReplaceable(belowBlock) || (water ? isWater(belowBlock) : isLava(belowBlock))) {
|
||||
if (handleFluidCollision(inst, below, water)) {
|
||||
triggerNeighbors(inst, below);
|
||||
return;
|
||||
}
|
||||
Block target = (water ? Block.WATER : Block.LAVA).withProperty("level", String.valueOf(FALLING));
|
||||
if (!belowBlock.compare(target) || !target.getProperty("level").equals(belowBlock.getProperty("level"))) {
|
||||
if (!(isWater(belowBlock) && parseLevel(belowBlock) == 0)
|
||||
&& !(isLava(belowBlock) && parseLevel(belowBlock) == 0)) {
|
||||
inst.setBlock(below, target);
|
||||
scheduleFlow(inst, below, water);
|
||||
triggerNeighbors(inst, below);
|
||||
}
|
||||
}
|
||||
if (!hasSolidBelow(inst, pos) && !source) return;
|
||||
}
|
||||
|
||||
if (flowLevel > maxRange) return;
|
||||
|
||||
Set<Direction> targets = findFlowTargets(inst, pos, water, maxRange - (source ? 0 : level));
|
||||
for (Direction d : Direction.HORIZONTAL) {
|
||||
if (!targets.contains(d)) continue;
|
||||
BlockVec np = new BlockVec(pos.blockX() + d.normalX(), pos.blockY(), pos.blockZ() + d.normalZ());
|
||||
Block nb = inst.getBlock(np);
|
||||
if (handleFluidCollision(inst, np, water)) continue;
|
||||
if (!isReplaceable(nb) && !(water ? isWater(nb) : isLava(nb))) continue;
|
||||
int existingLevel = (water ? isWater(nb) : isLava(nb)) ? parseLevel(nb) : Integer.MAX_VALUE;
|
||||
if (existingLevel == 0) continue;
|
||||
if (flowLevel < existingLevel) {
|
||||
inst.setBlock(np, (water ? Block.WATER : Block.LAVA).withProperty("level", String.valueOf(flowLevel)));
|
||||
scheduleFlow(inst, np, water);
|
||||
triggerNeighbors(inst, np);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int computeIncomingLevel(Instance inst, BlockVec pos, boolean water, int maxRange) {
|
||||
int min = Integer.MAX_VALUE;
|
||||
BlockVec above = new BlockVec(pos.blockX(), pos.blockY() + 1, pos.blockZ());
|
||||
Block ab = inst.getBlock(above);
|
||||
if ((water ? isWater(ab) : isLava(ab))) return FALLING;
|
||||
for (Direction d : Direction.HORIZONTAL) {
|
||||
BlockVec np = new BlockVec(pos.blockX() + d.normalX(), pos.blockY(), pos.blockZ() + d.normalZ());
|
||||
Block nb = inst.getBlock(np);
|
||||
if (water ? isWater(nb) : isLava(nb)) {
|
||||
int nl = parseLevel(nb);
|
||||
if (nl >= FALLING) nl = 0;
|
||||
if (nl < min) min = nl;
|
||||
}
|
||||
}
|
||||
if (min == Integer.MAX_VALUE) return -1;
|
||||
int result = min + 1;
|
||||
if (result > maxRange) return -1;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Set<Direction> findFlowTargets(Instance inst, BlockVec pos, boolean water, int remaining) {
|
||||
Set<Direction> result = new HashSet<>();
|
||||
if (remaining <= 0) return result;
|
||||
int bestDist = Integer.MAX_VALUE;
|
||||
int[] dist = new int[4];
|
||||
Direction[] dirs = {Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST};
|
||||
for (int i = 0; i < 4; i++) {
|
||||
BlockVec np = new BlockVec(pos.blockX() + dirs[i].normalX(), pos.blockY(), pos.blockZ() + dirs[i].normalZ());
|
||||
Block nb = inst.getBlock(np);
|
||||
if (!isReplaceable(nb) && !(water ? isWater(nb) : isLava(nb))) { dist[i] = Integer.MAX_VALUE; continue; }
|
||||
dist[i] = bfsDownhill(inst, np, water, remaining);
|
||||
if (dist[i] < bestDist) bestDist = dist[i];
|
||||
}
|
||||
if (bestDist == Integer.MAX_VALUE) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (dist[i] < Integer.MAX_VALUE) result.add(dirs[i]);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (dist[i] == bestDist) result.add(dirs[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int bfsDownhill(Instance inst, BlockVec start, boolean water, int remaining) {
|
||||
ArrayDeque<int[]> queue = new ArrayDeque<>();
|
||||
Set<Long> visited = new HashSet<>();
|
||||
queue.add(new int[]{start.blockX(), start.blockY(), start.blockZ(), 0});
|
||||
visited.add(key(start.blockX(), start.blockY(), start.blockZ()));
|
||||
while (!queue.isEmpty()) {
|
||||
int[] c = queue.poll();
|
||||
BlockVec cp = new BlockVec(c[0], c[1], c[2]);
|
||||
Block below = inst.getBlock(new BlockVec(c[0], c[1] - 1, c[2]));
|
||||
if (isReplaceable(below) && !(water ? isWater(below) : isLava(below))) return c[3];
|
||||
if (c[3] >= remaining) continue;
|
||||
for (Direction d : Direction.HORIZONTAL) {
|
||||
int nx = c[0] + d.normalX(), nz = c[2] + d.normalZ();
|
||||
long k = key(nx, c[1], nz);
|
||||
if (visited.contains(k)) continue;
|
||||
Block nb = inst.getBlock(new BlockVec(nx, c[1], nz));
|
||||
if (!isReplaceable(nb) && !(water ? isWater(nb) : isLava(nb))) continue;
|
||||
visited.add(k);
|
||||
queue.add(new int[]{nx, c[1], nz, c[3] + 1});
|
||||
}
|
||||
}
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
private static long key(int x, int y, int z) {
|
||||
return ((long) x & 0x3FFFFFFL) | (((long) z & 0x3FFFFFFL) << 26) | (((long) y & 0xFFFL) << 52);
|
||||
}
|
||||
|
||||
private static int countAdjacentSources(Instance inst, BlockVec pos, boolean water) {
|
||||
int c = 0;
|
||||
for (Direction d : Direction.HORIZONTAL) {
|
||||
Block nb = inst.getBlock(new BlockVec(pos.blockX() + d.normalX(), pos.blockY(), pos.blockZ() + d.normalZ()));
|
||||
if ((water ? isWater(nb) : isLava(nb)) && parseLevel(nb) == 0) c++;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private static boolean hasSolidBelow(Instance inst, BlockVec pos) {
|
||||
Block below = inst.getBlock(new BlockVec(pos.blockX(), pos.blockY() - 1, pos.blockZ()));
|
||||
return below.isSolid();
|
||||
}
|
||||
|
||||
private static boolean handleFluidCollision(Instance inst, BlockVec pos, boolean incomingIsWater) {
|
||||
Block target = inst.getBlock(pos);
|
||||
if (incomingIsWater && isLava(target)) {
|
||||
boolean lavaSource = parseLevel(target) == 0;
|
||||
inst.setBlock(pos, lavaSource ? Block.OBSIDIAN : Block.COBBLESTONE);
|
||||
return true;
|
||||
}
|
||||
if (!incomingIsWater && isWater(target)) {
|
||||
inst.setBlock(pos, Block.STONE);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isReplaceable(Block b) {
|
||||
if (b.isAir()) return true;
|
||||
String p = b.key().value();
|
||||
return p.equals("short_grass") || p.equals("tall_grass") || p.equals("fern") || p.equals("large_fern")
|
||||
|| p.equals("dead_bush") || p.equals("seagrass") || p.equals("tall_seagrass") || p.equals("vine")
|
||||
|| p.equals("snow") || p.equals("fire") || p.equals("soul_fire");
|
||||
}
|
||||
|
||||
private static boolean isWater(Block b) { return b.compare(Block.WATER); }
|
||||
private static boolean isLava(Block b) { return b.compare(Block.LAVA); }
|
||||
|
||||
private static int parseLevel(Block b) {
|
||||
String s = b.getProperty("level");
|
||||
if (s == null) return 0;
|
||||
try { return Integer.parseInt(s); } catch (NumberFormatException e) { return 0; }
|
||||
}
|
||||
}
|
||||
@@ -12,8 +12,7 @@ import net.minestom.server.event.player.PlayerBlockBreakEvent;
|
||||
import net.minestom.server.event.player.PlayerBlockInteractEvent;
|
||||
import net.minestom.server.event.player.PlayerBlockPlaceEvent;
|
||||
import net.minestom.server.instance.anvil.AnvilLoader;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import net.minestom.server.world.DimensionType;
|
||||
|
||||
public class Hub extends MineNetInstance implements Spawnable {
|
||||
public static final Hub INSTANCE = new Hub();
|
||||
@@ -21,7 +20,7 @@ public class Hub extends MineNetInstance implements Spawnable {
|
||||
static {
|
||||
MinecraftServer.getInstanceManager().registerInstance(INSTANCE);
|
||||
|
||||
INSTANCE.setChunkLoader(new AnvilLoader(Resource.HUB_MAP.getPath()));
|
||||
INSTANCE.setChunkLoader(new AnvilLoader(Resource.HUB_MAP.getPath(), DimensionType.OVERWORLD.key()));
|
||||
|
||||
INSTANCE.eventNode()
|
||||
.addListener(PlayerBlockBreakEvent.class, CommonEventHandles::cancel)
|
||||
@@ -33,7 +32,6 @@ public class Hub extends MineNetInstance implements Spawnable {
|
||||
|
||||
private Hub() {
|
||||
super(Dimension.THE_END.key);
|
||||
this.setChunkLoader(new AnvilLoader(Path.of("maps/hub")));
|
||||
|
||||
this.setTime(18000);
|
||||
this.defaultClock().pause();
|
||||
|
||||
@@ -18,6 +18,7 @@ import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.player.PlayerBlockBreakEvent;
|
||||
import net.minestom.server.event.player.PlayerDisconnectEvent;
|
||||
import net.minestom.server.instance.anvil.AnvilLoader;
|
||||
import net.minestom.server.world.DimensionType;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.logging.Logger;
|
||||
@@ -102,7 +103,7 @@ public class Room extends MineNetInstance implements Spawnable {
|
||||
|
||||
private void construct() {
|
||||
MinecraftServer.getInstanceManager().registerInstance(this);
|
||||
this.setChunkLoader(new AnvilLoader(Resource.LOBBY_MAP.getPath()));
|
||||
this.setChunkLoader(new AnvilLoader(Resource.LOBBY_MAP.getPath(), DimensionType.OVERWORLD.key()));
|
||||
|
||||
this.gameSelector = new GameSelector();
|
||||
this.gameSelector.setInstance(this, new Pos(0.5, 50, 19.5));
|
||||
|
||||
@@ -12,6 +12,7 @@ import net.minestom.server.entity.GameMode;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.player.PlayerMoveEvent;
|
||||
import net.minestom.server.instance.anvil.AnvilLoader;
|
||||
import net.minestom.server.world.DimensionType;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
@@ -29,7 +30,7 @@ public class TournamentDisplay extends MineNetInstance implements Spawnable {
|
||||
|
||||
public TournamentDisplay(Tournament tournament) {
|
||||
super(Dimension.OVERWORLD.key);
|
||||
this.setChunkLoader(new AnvilLoader(Resource.RESULT_DISPLAY.getPath()));
|
||||
this.setChunkLoader(new AnvilLoader(Resource.RESULT_DISPLAY.getPath(), DimensionType.OVERWORLD.key()));
|
||||
this.places = tournament.getPlaces();
|
||||
this.tournament = tournament;
|
||||
|
||||
|
||||
@@ -44,4 +44,17 @@ public class Position {
|
||||
public static boolean hasPositionChanged(Pos oldPos, Pos newPos) {
|
||||
return !oldPos.withView(0, 0).equals(newPos.withView(0, 0));
|
||||
}
|
||||
|
||||
public static boolean isInArea(Point point, Point pos1, Point pos2) {
|
||||
double minX = Math.min(pos1.x(), pos2.x());
|
||||
double maxX = Math.max(pos1.x(), pos2.x());
|
||||
double minY = Math.min(pos1.y(), pos2.y());
|
||||
double maxY = Math.max(pos1.y(), pos2.y());
|
||||
double minZ = Math.min(pos1.z(), pos2.z());
|
||||
double maxZ = Math.max(pos1.z(), pos2.z());
|
||||
|
||||
return point.x() >= minX && point.x() <= maxX
|
||||
&& point.y() >= minY && point.y() <= maxY
|
||||
&& point.z() >= minZ && point.z() <= maxZ;
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@ bungeecord:
|
||||
|
||||
velocity:
|
||||
enabled: false
|
||||
# Chat nur über den Proxy verteilen, hier verwerfen (chat-bridge)
|
||||
chat-via-proxy: false
|
||||
secret: ''
|
||||
|
||||
api:
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Reference in new issue
Block a user