feat: implemented static entities

This commit is contained in:
Andrey Terentev 2024-12-22 23:49:18 +07:00
parent 29ea2ee3d8
commit 4fc1618835
3 changed files with 112 additions and 1 deletions

View File

@ -1,10 +1,15 @@
package ru.dragonestia.msb3.api; package ru.dragonestia.msb3.api;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.GameMode; 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.FlatWorldModule;
import ru.dragonestia.msb3.api.module.MotdModule; import ru.dragonestia.msb3.api.module.MotdModule;
import ru.dragonestia.msb3.api.module.ResourcePackRepositoryModule; 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 @Log4j2
public class Bootstrap { public class Bootstrap {
@ -15,6 +20,51 @@ public class Bootstrap {
MotdModule.init("logo.png", "<gradient:#ff0059:#e06806><bold>msb3 server</bold></gradient>"); MotdModule.init("logo.png", "<gradient:#ff0059:#e06806><bold>msb3 server</bold></gradient>");
FlatWorldModule.init(GameMode.ADVENTURE); 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); ResourcePackRepositoryModule.init(boot, "0.0.0.0", 7270);
boot.start("0.0.0.0", 25565); boot.start("0.0.0.0", 25565);

View File

@ -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<StaticEntity> supplier) {}
}

View File

@ -3,21 +3,43 @@ package ru.dragonestia.msb3.api.world;
import lombok.Getter; import lombok.Getter;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
import net.minestom.server.MinecraftServer; import net.minestom.server.MinecraftServer;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.event.EventListener; import net.minestom.server.event.EventListener;
import net.minestom.server.event.instance.InstanceChunkLoadEvent;
import net.minestom.server.event.player.PlayerChunkUnloadEvent; import net.minestom.server.event.player.PlayerChunkUnloadEvent;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.EntityTracker; import net.minestom.server.instance.EntityTracker;
import net.minestom.server.instance.InstanceContainer; 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 @Log4j2
@Getter @Getter
public class World { public class World {
private final InstanceContainer instance; private final InstanceContainer instance;
private final Map<ChunkPos, List<StaticEntity.Spot>> staticEntitiesSpots = new ConcurrentHashMap<>();
private EventListener<PlayerChunkUnloadEvent> chunkUnloadListener; private EventListener<PlayerChunkUnloadEvent> chunkUnloadListener;
World(InstanceContainer instance) { World(InstanceContainer instance) {
this.instance = 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() { public synchronized void unload() {
@ -41,7 +63,9 @@ public class World {
var chunk = instance.getChunk(event.getChunkX(), event.getChunkZ()); var chunk = instance.getChunk(event.getChunkX(), event.getChunkZ());
if (chunk == null) return; if (chunk == null) return;
if (chunk.getViewers().isEmpty()) { var instance = event.getInstance();
if (chunk.getViewers().isEmpty() && !hasNonStaticEntities(chunk)) {
try { try {
instance.unloadChunk(event.getChunkX(), event.getChunkZ()); instance.unloadChunk(event.getChunkX(), event.getChunkZ());
} catch (NullPointerException ignored) {} } catch (NullPointerException ignored) {}
@ -56,4 +80,22 @@ public class World {
instance.eventNode().removeListener(chunkUnloadListener); instance.eventNode().removeListener(chunkUnloadListener);
chunkUnloadListener = null; chunkUnloadListener = null;
} }
public void spawnStaticEntity(Pos pos, Supplier<StaticEntity> 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) {}
} }