diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 4e224a4..8d2a6b3 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -45,6 +45,10 @@ jobs:
env:
DISPLAY: :99
GITHUB_WORKSPACE: $GITHUB_WORKSPACE
+ - name: start minecraft server
+ run: cd server && ./launch.sh &
+ env:
+ GITHUB_WORKSPACE: $GITHUB_WORKSPACE
- name: checkout tagilmo
uses: actions/checkout@v3
with:
diff --git a/VERSION b/VERSION
index c946ee6..1180819 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.1.6
+0.1.7
diff --git a/build.gradle b/build.gradle
index f2b5efa..ff72923 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,14 +1,20 @@
plugins {
+ id 'java'
+ id 'base'
id 'fabric-loom' version '1.6-SNAPSHOT'
id 'maven-publish'
id("com.github.bjornvester.xjc") version "1.6.0"
}
-sourceCompatibility = JavaVersion.VERSION_21
-targetCompatibility = JavaVersion.VERSION_21
+java {
+ sourceCompatibility = JavaVersion.VERSION_21
+ targetCompatibility = JavaVersion.VERSION_21
+}
version = rootProject.file('VERSION').text.trim()
-archivesBaseName = project.archives_base_name + '-fabric_' + project.fabric_version
+base {
+ archivesName = project.archives_base_name + '-fabric_' + project.fabric_version
+}
group = project.maven_group
@@ -37,6 +43,7 @@ dependencies {
implementation 'jakarta.annotation:jakarta.annotation-api:2.0.0'
implementation 'jakarta.activation:jakarta.activation-api:2.0.1'
implementation 'org.json:json:20230227'
+ compileOnly 'com.mojang:authlib'
xjc "org.glassfish.jaxb:jaxb-runtime:3.0.2"
xjc 'org.glassfish.jaxb:jaxb-xjc:3.0.1'
@@ -80,6 +87,10 @@ jar {
}
jar.duplicatesStrategy = 'WARN'
+loom {
+ accessWidenerPath = file("src/main/resources/vereya.accesswidener")
+}
+
// configure the maven publication
publishing {
publications {
diff --git a/config.xml b/config.xml
index 1384725..2251982 100644
--- a/config.xml
+++ b/config.xml
@@ -15,5 +15,9 @@
+
+
+
+
diff --git a/fabric/fabric-server-mc.1.21-loader.0.16.5-launcher.1.0.1.jar b/fabric/fabric-server-mc.1.21-loader.0.16.5-launcher.1.0.1.jar
new file mode 100644
index 0000000..9061c3c
Binary files /dev/null and b/fabric/fabric-server-mc.1.21-loader.0.16.5-launcher.1.0.1.jar differ
diff --git a/server/config.xml b/server/config.xml
new file mode 120000
index 0000000..06352a5
--- /dev/null
+++ b/server/config.xml
@@ -0,0 +1 @@
+../config.xml
\ No newline at end of file
diff --git a/server/eula.txt b/server/eula.txt
new file mode 100644
index 0000000..226bd2e
--- /dev/null
+++ b/server/eula.txt
@@ -0,0 +1,3 @@
+#By changing the setting below to TRUE you are indicating your agreement to our EULA (https://aka.ms/MinecraftEULA).
+#Thu Dec 29 16:39:29 GMT+04:00 2022
+eula=true
diff --git a/server/launch.sh b/server/launch.sh
new file mode 100755
index 0000000..7933261
--- /dev/null
+++ b/server/launch.sh
@@ -0,0 +1 @@
+java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8006 -Dlog4j.configurationFile=`pwd`/config.xml -Xmx2G -jar mods/fabric-server-mc.1.21-loader.0.16.5-launcher.1.0.1.jar --nogui
diff --git a/server/server.properties b/server/server.properties
new file mode 100644
index 0000000..c6ad89c
--- /dev/null
+++ b/server/server.properties
@@ -0,0 +1,63 @@
+#Minecraft server properties
+#Tue Oct 29 19:57:45 MSK 2024
+accepts-transfers=false
+allow-flight=false
+allow-nether=true
+broadcast-console-to-ops=true
+broadcast-rcon-to-ops=true
+bug-report-link=
+difficulty=easy
+enable-command-block=false
+enable-jmx-monitoring=false
+enable-query=false
+enable-rcon=false
+enable-status=true
+enforce-secure-profile=false
+enforce-whitelist=false
+entity-broadcast-range-percentage=100
+force-gamemode=false
+function-permission-level=2
+gamemode=survival
+generate-structures=true
+generator-settings={"biome"\:"minecraft\:desert","layers"\:[{"block"\:"minecraft\:bedrock","height"\:1},{"block"\:"minecraft\:stone","height"\:3},{"block"\:"minecraft\:sandstone","height"\:116}],"structures"\:{"village"\:{}}}
+hardcore=false
+hide-online-players=false
+initial-disabled-packs=
+initial-enabled-packs=vanilla
+level-name=world
+level-seed=43839877843298
+level-type=minecraft\:normal
+log-ips=true
+max-chained-neighbor-updates=1000000
+max-players=20
+max-tick-time=60000
+max-world-size=29999984
+motd=A Minecraft Server
+network-compression-threshold=256
+online-mode=false
+op-permission-level=4
+player-idle-timeout=0
+prevent-proxy-connections=false
+pvp=true
+query.port=25565
+rate-limit=0
+rcon.password=
+rcon.port=25575
+region-file-compression=deflate
+require-resource-pack=false
+resource-pack=
+resource-pack-id=
+resource-pack-prompt=
+resource-pack-sha1=
+server-ip=
+server-port=25565
+simulation-distance=10
+spawn-animals=true
+spawn-monsters=true
+spawn-npcs=true
+spawn-protection=16
+sync-chunk-writes=true
+text-filtering-config=
+use-native-transport=true
+view-distance=10
+white-list=false
diff --git a/src/main/java/io/singularitynet/Client/ClientStateMachine.java b/src/main/java/io/singularitynet/Client/ClientStateMachine.java
index 5d7f95a..e0bb333 100755
--- a/src/main/java/io/singularitynet/Client/ClientStateMachine.java
+++ b/src/main/java/io/singularitynet/Client/ClientStateMachine.java
@@ -43,7 +43,12 @@
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.screen.GameMenuScreen;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.screen.multiplayer.ConnectScreen;
import net.minecraft.client.network.ClientPlayerEntity;
+import net.minecraft.client.network.ServerAddress;
+import net.minecraft.client.network.ServerInfo;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
import net.minecraft.entity.mob.MobEntity;
@@ -550,6 +555,7 @@ public boolean onCommand(String command, String ipFrom, DataOutputStream dos)
{
LOGGER.info("Received from " + ipFrom + ":" +
command.substring(0, Math.min(command.length(), 1024)));
+
boolean keepProcessing = false;
// Possible commands:
@@ -849,6 +855,7 @@ private void checkForMissionCommand() throws Exception
{
missionInit.getClientAgentConnection().setAgentIPAddress(comip.ipAddress);
LOGGER.info("Mission received: " + missionInit.getMission().getAbout().getSummary());
+ LOGGER.debug(missionMessage);
csMachine.currentMissionInit = missionInit;
ClientStateMachine.this.createMissionControlSocket();
// Move on to next state:
@@ -1178,6 +1185,20 @@ protected void execute() {
boolean needsNewWorld = worldGenerator != null && worldGenerator.shouldCreateWorld(currentMissionInit(), genOptions);
boolean worldCurrentlyExists = world != null;
+ MinecraftServerConnection serverCon = currentMissionInit().getMinecraftServerConnection();
+ LOGGER.debug("checking for server connection in mission init: ", serverCon);
+ if (serverCon != null && serverCon.getAddress() != null && serverCon.getPort() != 0) {
+ LOGGER.debug("server connection info is provided " + serverCon.toString() +
+ " assume world already exists");
+ if (MinecraftClient.getInstance().isIntegratedServerRunning()){
+ LOGGER.debug("stopping integrated server");
+ MinecraftClient.getInstance().getServer().stop(true);
+ }
+ needsNewWorld = false;
+ worldCurrentlyExists = true;
+ episodeHasCompleted(ClientState.WAITING_FOR_SERVER_READY);
+ return;
+ }
List agents = currentMissionInit().getMission().getAgentSection();
String agentName = agents.get(currentMissionInit().getClientRole()).getName();
if (worldCurrentlyExists) {
@@ -1203,10 +1224,10 @@ protected void execute() {
LOGGER.debug("needsNewWorld && worldCurrentlyExists");
episodeHasCompleted(ClientState.PAUSING_OLD_SERVER);
} else {
- // We want a new world, and there is currently nothing running,
- // so jump to world creation:
- LOGGER.debug("needsNewWorld && not worldCurrentlyExists");
- episodeHasCompleted(ClientState.CREATING_NEW_WORLD);
+ // We want a new world, and there is currently nothing running,
+ // so jump to world creation:
+ LOGGER.debug("needsNewWorld && not worldCurrentlyExists");
+ episodeHasCompleted(ClientState.CREATING_NEW_WORLD);
}
} else { // not needNewWorld
LOGGER.debug("not need new world");
@@ -1217,7 +1238,7 @@ protected void execute() {
as.getAgentStart().setPlacement(null);
ClientPlayerEntity player = MinecraftClient.getInstance().player;
- if (player.isDead()) player.requestRespawn();
+ if (player != null && player.isDead()) player.requestRespawn();
/*
if (ClientStateMachine.this.serverHandlers == null) {
// We need to use the server's MissionHandlers here:
@@ -1234,6 +1255,7 @@ protected void execute() {
// boolean isConnectedToRealm = MinecraftClient.getInstance().isConnectedToRealms();
boolean isConnectedToLocal = MinecraftClient.getInstance().isConnectedToLocalServer();
boolean isIntegratedServerRunning = MinecraftClient.getInstance().isIntegratedServerRunning();
+ boolean isConnectedToRemote = !isIntegratedServerRunning && player != null;
// LOGGER.debug("isConnectedToRealm: " + isConnectedToRealm);
LOGGER.debug("isConnectedToLocal: " + isConnectedToLocal);
LOGGER.debug("isIntegratedServerRunning: " + isIntegratedServerRunning);
@@ -1258,21 +1280,8 @@ public void run() {
}
});
// Skip all the map loading stuff and go straight to waiting for the server:
- episodeHasCompleted(ClientState.WAITING_FOR_SERVER_READY);
- } else {
- LOGGER.debug("sending mission to remote Server");
- HashMap map = new HashMap();
- // convert mission init with jaxb serializer
- try {
- String xmlData = SchemaHelper.serialiseObject(currentMissionInit(), MissionInit.class);
- map.put("MissionInit", xmlData);
- } catch (JAXBException e) {
- episodeHasCompletedWithErrors(ClientState.ERROR_NO_WORLD, "exception while converting mission init to xml" + e.getMessage());
- }
- // send mission init to server
- ClientPlayNetworking.send(new MessagePayload(new VereyaMessage(VereyaMessageType.CLIENT_MISSION_INIT, 0, map)));
- episodeHasCompleted(ClientState.WAITING_FOR_SERVER_READY);
}
+ episodeHasCompleted(ClientState.WAITING_FOR_SERVER_READY);
} else { // not needNewWorld and no world: error
// Mission has requested no new world, but there is no current world to play in - this is an error:
episodeHasCompletedWithErrors(ClientState.ERROR_NO_WORLD, "We have no world to play in - check that your ServerHandlers section contains a world generator");
@@ -1294,6 +1303,7 @@ public class WaitingForServerEpisode extends ErrorAwareEpisode implements IVerey
boolean waitingForChunk = false;
boolean waitingForPlayer = true;
private boolean chunkReady = false;
+ private boolean sendToRemote = false;
protected WaitingForServerEpisode(ClientStateMachine machine)
{
@@ -1388,8 +1398,9 @@ public void onClientTick(MinecraftClient client)
if (agents.size() > 1 && currentMissionInit().getClientRole() != 0)
{
+ /*
throw new RuntimeException("Not implemented");
- /*
+
// We are waiting to join an out-of-process server. Need to pay attention to what happens -
// if we can't join, for any reason, we should abort the mission.
GuiScreen screen = Minecraft.getMinecraft().currentScreen;
@@ -1413,8 +1424,7 @@ public void onClientTick(MinecraftClient client)
}
@Override
- protected void execute() throws Exception
- {
+ protected void execute() throws Exception {
totalTicks = 0;
// Minecraft.getMinecraft().displayGuiScreen(null); // Clear any menu screen that might confuse things.
@@ -1423,7 +1433,23 @@ protected void execute() throws Exception
//if (agents == null || agents.size() <= currentMissionInit().getClientRole())
// throw new Exception("No agent section for us!"); // TODO
this.agentName = agents.get(currentMissionInit().getClientRole()).getName();
+ MinecraftServerConnection serverCon = currentMissionInit().getMinecraftServerConnection();
+ PlayerEntity player = MinecraftClient.getInstance().player;
+ boolean isConnectedToRemote = player != null && !MinecraftClient.getInstance().isIntegratedServerRunning();
+ if (!isConnectedToRemote && serverCon != null && serverCon.getAddress() != null && serverCon.getPort() != 0) {
+ ServerAddress srv = new ServerAddress(serverCon.getAddress(), serverCon.getPort());
+ LOGGER.debug("connecting to " + srv.getAddress() + ":" + srv.getPort());
+ Screen parentScreen = new GameMenuScreen(true);
+ ServerInfo srvInfo = new ServerInfo("local", srv.getAddress(), ServerInfo.ServerType.LAN);
+ ConnectScreen.connect(parentScreen, MinecraftClient.getInstance(), srv, srvInfo, true, null);
+ this.sendToRemote = true;
+ }
+
+ if (isConnectedToRemote && currentMissionInit().getClientRole() == 0) {
+ this.sendToRemote = true;
+ }
+ /*
if (agents.size() > 1 && currentMissionInit().getClientRole() != 0)
{
// Multi-agent mission, we should be joining a server.
@@ -1445,11 +1471,25 @@ protected void execute() throws Exception
}
this.waitingForPlayer = false;
LOGGER.info("player exists and names match");
- }
+ }*/
}
protected void handleLan()
{
+ if (this.sendToRemote) {
+ LOGGER.debug("sending mission to remote Server");
+ HashMap map = new HashMap();
+ // convert mission init with jaxb serializer
+ try {
+ String xmlData = SchemaHelper.serialiseObject(currentMissionInit(), MissionInit.class);
+ map.put("MissionInit", xmlData);
+ } catch (JAXBException e) {
+ episodeHasCompletedWithErrors(ClientState.ERROR_NO_WORLD, "exception while converting mission init to xml" + e.getMessage());
+ }
+ // send mission init to server
+ ClientPlayNetworking.send(new MessagePayload(new VereyaMessage(VereyaMessageType.CLIENT_MISSION_INIT, 0, map)));
+ sendToRemote = false;
+ }
// Get our name from the Mission:
/*List agents = currentMissionInit().getMission().getAgentSection();
this.agentName = agents.get(currentMissionInit().getClientRole()).getName();
diff --git a/src/main/java/io/singularitynet/Client/VereyaModClient.java b/src/main/java/io/singularitynet/Client/VereyaModClient.java
index 5de3af9..6e2b8d0 100644
--- a/src/main/java/io/singularitynet/Client/VereyaModClient.java
+++ b/src/main/java/io/singularitynet/Client/VereyaModClient.java
@@ -149,11 +149,12 @@ public void onKey(long window, int key, int scancode, int action, int modifiers)
@Override
public void onInitializeClient() {
+ LOGGER.info("initialising vereya mod client");
this.stateMachine = new ClientStateMachine(ClientState.WAITING_FOR_MOD_READY, (IMalmoModClient) this);
// subscribe to setScreen event
ScreenEvents.SET_SCREEN.register(this);
- PayloadTypeRegistry.playS2C().register(MessagePayload.ID, MessagePayload.CODEC);
- // register the instance for messages from Server to the Client
+ // this is registered in VereyaModServer even on client
+ // PayloadTypeRegistry.playS2C().register(MessagePayload.ID, MessagePayload.CODEC);
ClientPlayNetworking.registerGlobalReceiver(MessagePayload.ID,
(payload, context) -> { SidesMessageHandler.server2client.onMessage(payload, context) ; });
}
diff --git a/src/main/java/io/singularitynet/Server/ServerStateMachine.java b/src/main/java/io/singularitynet/Server/ServerStateMachine.java
index df00e71..8efcd40 100644
--- a/src/main/java/io/singularitynet/Server/ServerStateMachine.java
+++ b/src/main/java/io/singularitynet/Server/ServerStateMachine.java
@@ -27,12 +27,14 @@
import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.JAXBException;
+import net.fabricmc.fabric.mixin.event.lifecycle.*;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerEntityEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
+import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.entity.player.PlayerEntity;
@@ -77,6 +79,7 @@ public class ServerStateMachine extends StateMachine implements IVereyaMessageLi
private ArrayList userConnectionWatchList = new ArrayList();
private ArrayList userTurnSchedule = new ArrayList();
public Map controllableEntities = new HashMap();
+ protected Set mobsInGame;
/** Called to initialise a state machine for a specific Mission request.
* Most likely caused by the client creating an integrated server.
@@ -93,6 +96,7 @@ public ServerStateMachine(ServerState initialState, MissionInit minit, Minecraft
LOGGER.debug("ServerStateMachine: " + this + " server " + server);
this.server = new WeakReference(server);
+ this.mobsInGame = new HashSet();
// Register ourself on the event busses, so we can harness the server tick:
ServerTickEvents.END_SERVER_TICK.register(this::onServerTick);
ServerLifecycleEvents.SERVER_STOPPING.register(this::onServerStopping);
@@ -111,6 +115,7 @@ private void onEntityUnload(Entity entity, ServerWorld serverWorld) {
LOGGER.debug("removing controlled mob uuid: " + uuid);
controllableEntities.remove(uuid);
}
+ if (this.mobsInGame.contains(entity)) this.mobsInGame.remove(entity);
}
}
@@ -122,12 +127,12 @@ private void onEntityLoad(Entity entity, ServerWorld serverWorld) {
controllableEntities.put(uuid, mobEntity);
LOGGER.debug("sending new controlled mob message to client uuid: " + uuid);
sendToAll(new VereyaMessage(VereyaMessageType.SERVER_CONTROLLED_MOB, uuid));
+ } else {
+ this.mobsInGame.add((MobEntity) entity);
}
}
}
-
-
/** Used to prevent spawning in our world.*/
public ActionResult onGetPotentialSpawns(Entity entity, ServerWorld world)
{
@@ -144,7 +149,6 @@ public ActionResult onGetPotentialSpawns(Entity entity, ServerWorld world)
ServerInitialConditions sic = (ss != null) ? ss.getServerInitialConditions() : null;
if (sic != null)
allowSpawning = (sic.isAllowSpawning() == Boolean.TRUE);
-
if (allowSpawning && sic.getAllowedMobs() != null && !sic.getAllowedMobs().isEmpty())
{
// Spawning is allowed, but restricted to our list:
@@ -285,11 +289,13 @@ private void sendToAll(VereyaMessage msg){
return;
}
for(ServerPlayerEntity player: server.getPlayerManager().getPlayerList()){
+ LOGGER.debug("send " + msg.getMessageType().toString() + " to " + player.getName());
ServerPlayNetworking.send(player, new MessagePayload(msg));
}
}
private void sendToPlayer(VereyaMessage msg, ServerPlayerEntity player){
+ LOGGER.debug("send " + msg.getMessageType().toString() + " to " + player.getName());
ServerPlayNetworking.send(player, new MessagePayload(msg));
}
@@ -1032,7 +1038,6 @@ private void initialiseEnderInventory(PlayerEntity player, AgentStart.EnderBoxIn
}
}
-
//---------------------------------------------------------------------------------------------------------
/** Mission running state.
*/
diff --git a/src/main/java/io/singularitynet/Server/VereyaModServer.java b/src/main/java/io/singularitynet/Server/VereyaModServer.java
index d924643..ad313e7 100644
--- a/src/main/java/io/singularitynet/Server/VereyaModServer.java
+++ b/src/main/java/io/singularitynet/Server/VereyaModServer.java
@@ -55,15 +55,21 @@ public boolean hasServer(){
@Override
public void onInitialize() {
+ Logger LOGGER = LogManager.getLogger();
+ LOGGER.info("initialising vereya mod server");
instance = this;
PayloadTypeRegistry.playC2S().register(MessagePayload.ID, MessagePayload.CODEC);
+ PayloadTypeRegistry.playS2C().register(MessagePayload.ID, MessagePayload.CODEC);
// register the instance for messages from Client to the Server
ServerPlayNetworking.registerGlobalReceiver(MessagePayload.ID, (payload, context) -> {
SidesMessageHandler.client2server.onMessage(payload, context);
});
ServerLifecycleEvents.SERVER_STARTED.register((MinecraftServer server) -> {
- Logger LOGGER = LogManager.getLogger();
- LOGGER.info("Server started");
+ String msg = "integrated ";
+ if (server.isDedicated()){
+ msg = "dedicated ";
+ }
+ LOGGER.info(msg + "Server started");
if (stateMachine == null ) {
this.stateMachine = new ServerStateMachine(ServerState.WAITING_FOR_MOD_READY, null, server);
} else {
diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json
index d9e74d8..5291df1 100644
--- a/src/main/resources/fabric.mod.json
+++ b/src/main/resources/fabric.mod.json
@@ -9,8 +9,8 @@
"Anatoly Belikov"
],
"contact": {
- "homepage": "https://fabricmc.net/",
- "sources": "https://github.com/FabricMC/fabric-example-mod"
+ "homepage": "https://github.com/trueagi-io/Vereya",
+ "sources": "https://github.com/trueagi-io/Vereya"
},
"license": "CC0-1.0",
diff --git a/src/main/resources/vereya.accesswidener b/src/main/resources/vereya.accesswidener
new file mode 100644
index 0000000..e823f6b
--- /dev/null
+++ b/src/main/resources/vereya.accesswidener
@@ -0,0 +1,5 @@
+accessWidener v2 named
+
+accessible class net/minecraft/client/network/ClientLoginNetworkHandler$State
+accessible field net/minecraft/client/network/ClientLoginNetworkHandler$State name Lnet/minecraft/text/Text;
+accessible field net/minecraft/client/network/ClientLoginNetworkHandler$State prevStates Ljava/util/Set;
\ No newline at end of file
diff --git a/src/main/resources/vereya.mixins.json b/src/main/resources/vereya.mixins.json
index c2c6d03..e73ef26 100644
--- a/src/main/resources/vereya.mixins.json
+++ b/src/main/resources/vereya.mixins.json
@@ -6,12 +6,11 @@
"mixins": [],
"client": [
"TitleScreenMixin", "SessionMixin", "MinecraftClientMixin", "GameOptionsMixin",
- "KeyBindingMixin", "MouseMixin", "MouseAccessorMixin", "InGameHudMixin", "ServerWorldEntityLoaderMixin",
- "ServerEntityManagerMixin", "ServerWorldMixin", "LevelStorageMixin",
+ "KeyBindingMixin", "MouseMixin", "MouseAccessorMixin", "InGameHudMixin", "LevelStorageMixin",
"MinecraftClientEventsMixin", "LootTableProviderMixin", "MobEntityMixin", "MobEntityAccessorMixin",
- "ClientWorldMixinAccess", "EntityMixin"
+ "ClientWorldMixinAccess", "EntityMixin", "ServerEntityManagerMixin", "ServerWorldMixin", "ServerWorldEntityLoaderMixin"
],
- "server": [],
+ "server": ["ServerEntityManagerMixin", "ServerWorldMixin", "ServerWorldEntityLoaderMixin"],
"injectors": {
"defaultRequire": 1
}