From 4fc16188354aac1ed41ac1c719003c3ab25820c0 Mon Sep 17 00:00:00 2001 From: ScarletRedMan Date: Sun, 22 Dec 2024 23:49:18 +0700 Subject: [PATCH] feat: implemented static entities --- .../ru/dragonestia/msb3/api/Bootstrap.java | 50 +++++++++++++++++++ .../msb3/api/entity/StaticEntity.java | 19 +++++++ .../ru/dragonestia/msb3/api/world/World.java | 44 +++++++++++++++- 3 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 api/src/main/java/ru/dragonestia/msb3/api/entity/StaticEntity.java diff --git a/api/src/main/java/ru/dragonestia/msb3/api/Bootstrap.java b/api/src/main/java/ru/dragonestia/msb3/api/Bootstrap.java index 480d536..3b86dc0 100644 --- a/api/src/main/java/ru/dragonestia/msb3/api/Bootstrap.java +++ b/api/src/main/java/ru/dragonestia/msb3/api/Bootstrap.java @@ -1,10 +1,15 @@ package ru.dragonestia.msb3.api; import lombok.extern.log4j.Log4j2; +import net.minestom.server.MinecraftServer; import net.minestom.server.entity.GameMode; +import net.minestom.server.event.player.PlayerChatEvent; import ru.dragonestia.msb3.api.module.FlatWorldModule; import ru.dragonestia.msb3.api.module.MotdModule; import ru.dragonestia.msb3.api.module.ResourcePackRepositoryModule; +import ru.dragonestia.msb3.api.resource.dialog.ButtonNumber; +import ru.dragonestia.msb3.api.talk.dialogue.DialogueRenderer; +import ru.dragonestia.msb3.api.talk.dialogue.DialogueTheme; @Log4j2 public class Bootstrap { @@ -15,6 +20,51 @@ public class Bootstrap { MotdModule.init("logo.png", "msb3 server"); FlatWorldModule.init(GameMode.ADVENTURE); + MinecraftServer.getGlobalEventHandler().addListener(PlayerChatEvent.class, event -> { + var player = event.getPlayer(); + + var render = new DialogueRenderer(player, DialogueTheme.builder().build()); + render.setText(""" + Абсолютно точно. + Я знаю точнo - невозможное возможно + Сойти с ума, влюбиться так неосторoжно + Найти тебя, не отпускать ни днём, ни ночью + Всё невозможное - возможно, знаю точно! + А где тебя искать, прошу ты мне ответь + В какие города мне за тобой лететь + Я готов на край Земли, я всё должен объяснить + Пойми, что без тебя я не умею жить + Я знаю точно - невозможное возможно + Сойти с ума, влюбиться так неосторожно + Найти тебя, не отпускать ни днём, ни ночью + Всё невозможное - возможно, знаю точно! + На-на-на-на (на-на-на-на), а-а, а-а + На-на-на-на (на-на-на-на), а-а, а-а + Всё готов делить, с тобой я пополам + Ты только мне поверь, я сделал выбор сам + Дай же мне последний шанс, я всё должен объяснить + Пойми, что без тебя я не умею жить + Я знаю точно - невозможное возможно + Сойти с ума, влюбиться так неосторожно + Найти тебя, не отпускать ни днём, ни ночью + Всё невозможное - возможно, знаю точно! + На-на-на-на (на-на-на-на), а-а, а-а + На-на-на-на (на-на-на-на), а-а, а-а + Я знаю точно - невозможное возможно + Сойти с ума, влюбиться так неосторожно + Найти тебя, не отпускать ни днём, ни ночью + Всё невозможное - возможно, знаю точно! + На-на-на-на (на-на-на-на), а-а, а-а + На-на-на-на (на-на-на-на), а-а, а-а"""); + + render.setButtonText(ButtonNumber.BUTTON_1, "Hello world!"); + render.setButtonText(ButtonNumber.BUTTON_2, "I am a teapot"); + render.setButtonText(ButtonNumber.BUTTON_3, "I love pizza\nMamma mia\nPeperoni\nPapa carlo\nZaebumba\nPidoraso ebanino"); + render.setButtonText(ButtonNumber.BUTTON_4, "msb3 is top!"); + + render.show(); + }); + ResourcePackRepositoryModule.init(boot, "0.0.0.0", 7270); boot.start("0.0.0.0", 25565); diff --git a/api/src/main/java/ru/dragonestia/msb3/api/entity/StaticEntity.java b/api/src/main/java/ru/dragonestia/msb3/api/entity/StaticEntity.java new file mode 100644 index 0000000..4dbdcc9 --- /dev/null +++ b/api/src/main/java/ru/dragonestia/msb3/api/entity/StaticEntity.java @@ -0,0 +1,19 @@ +package ru.dragonestia.msb3.api.entity; + +import net.minestom.server.coordinate.Pos; +import net.minestom.server.entity.Entity; +import net.minestom.server.entity.EntityType; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Supplier; + +public class StaticEntity extends Entity { + + public StaticEntity(@NotNull EntityType entityType) { + super(entityType); + + setNoGravity(true); + } + + public record Spot(Pos pos, Supplier supplier) {} +} diff --git a/api/src/main/java/ru/dragonestia/msb3/api/world/World.java b/api/src/main/java/ru/dragonestia/msb3/api/world/World.java index e8bcae9..9ae395e 100644 --- a/api/src/main/java/ru/dragonestia/msb3/api/world/World.java +++ b/api/src/main/java/ru/dragonestia/msb3/api/world/World.java @@ -3,21 +3,43 @@ package ru.dragonestia.msb3.api.world; import lombok.Getter; import lombok.extern.log4j.Log4j2; import net.minestom.server.MinecraftServer; +import net.minestom.server.coordinate.Pos; import net.minestom.server.event.EventListener; +import net.minestom.server.event.instance.InstanceChunkLoadEvent; import net.minestom.server.event.player.PlayerChunkUnloadEvent; +import net.minestom.server.instance.Chunk; import net.minestom.server.instance.EntityTracker; import net.minestom.server.instance.InstanceContainer; +import ru.dragonestia.msb3.api.entity.StaticEntity; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; @Log4j2 @Getter public class World { private final InstanceContainer instance; + private final Map> staticEntitiesSpots = new ConcurrentHashMap<>(); private EventListener chunkUnloadListener; World(InstanceContainer instance) { this.instance = instance; + + instance.eventNode().addListener(InstanceChunkLoadEvent.class, event -> { + var chunkPos = new ChunkPos(event.getChunkX(), event.getChunkZ()); + if (!staticEntitiesSpots.containsKey(chunkPos)) return; + + staticEntitiesSpots.get(chunkPos).forEach(spot -> { + var entity = spot.supplier().get(); + entity.setInstance(instance, spot.pos()); + }); + }); } public synchronized void unload() { @@ -41,7 +63,9 @@ public class World { var chunk = instance.getChunk(event.getChunkX(), event.getChunkZ()); if (chunk == null) return; - if (chunk.getViewers().isEmpty()) { + var instance = event.getInstance(); + + if (chunk.getViewers().isEmpty() && !hasNonStaticEntities(chunk)) { try { instance.unloadChunk(event.getChunkX(), event.getChunkZ()); } catch (NullPointerException ignored) {} @@ -56,4 +80,22 @@ public class World { instance.eventNode().removeListener(chunkUnloadListener); chunkUnloadListener = null; } + + public void spawnStaticEntity(Pos pos, Supplier supplier) { + var chunkPos = new ChunkPos(pos.chunkX(), pos.chunkZ()); + + staticEntitiesSpots.computeIfAbsent(chunkPos, $ -> Collections.synchronizedList(new ArrayList<>())) + .add(new StaticEntity.Spot(pos, supplier)); + + if (instance.isChunkLoaded(pos.chunkX(), pos.chunkZ())) { + supplier.get().setInstance(instance, pos); + } + } + + private boolean hasNonStaticEntities(Chunk chunk) { + return instance.getChunkEntities(chunk).stream() + .anyMatch(entity -> !(entity instanceof StaticEntity)); + } + + private record ChunkPos(int chunkX, int chunkZ) {} }