Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

initial support for multiple agents on dedicated server #79

Merged
merged 12 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.6
0.1.7
17 changes: 14 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -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


Expand Down Expand Up @@ -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'
Expand Down Expand Up @@ -80,6 +87,10 @@ jar {
}
jar.duplicatesStrategy = 'WARN'

loom {
accessWidenerPath = file("src/main/resources/vereya.accesswidener")
}

// configure the maven publication
publishing {
publications {
Expand Down
4 changes: 4 additions & 0 deletions config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,9 @@
<AppenderRef ref="Console" level="info"/>
<AppenderRef ref="file" level="debug"/>
</Root>
<Logger name="net.minecraft" level="info" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="file"/>
</Logger>
</Loggers>
</Configuration>
Binary file not shown.
1 change: 1 addition & 0 deletions server/config.xml
3 changes: 3 additions & 0 deletions server/eula.txt
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions server/launch.sh
Original file line number Diff line number Diff line change
@@ -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
63 changes: 63 additions & 0 deletions server/server.properties
Original file line number Diff line number Diff line change
@@ -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
86 changes: 63 additions & 23 deletions src/main/java/io/singularitynet/Client/ClientStateMachine.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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<AgentSection> agents = currentMissionInit().getMission().getAgentSection();
String agentName = agents.get(currentMissionInit().getClientRole()).getName();
if (worldCurrentlyExists) {
Expand All @@ -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");
Expand All @@ -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:
Expand All @@ -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);
Expand All @@ -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<String, String> map = new HashMap<String, String>();
// 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");
Expand All @@ -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)
{
Expand Down Expand Up @@ -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;
Expand All @@ -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.
Expand All @@ -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.
Expand All @@ -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<String, String> map = new HashMap<String, String>();
// 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<AgentSection> agents = currentMissionInit().getMission().getAgentSection();
this.agentName = agents.get(currentMissionInit().getClientRole()).getName();
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/io/singularitynet/Client/VereyaModClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -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) ; });
}
Expand Down
Loading
Loading