Skip to content

Commit

Permalink
Add basic support for persistent game worlds
Browse files Browse the repository at this point in the history
  • Loading branch information
Patbox committed Nov 23, 2024
1 parent 32ea507 commit a06fa73
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 3 deletions.
5 changes: 4 additions & 1 deletion .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package xyz.nucleoid.plasmid.api.game.world;

import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import xyz.nucleoid.fantasy.RuntimeWorldConfig;
import xyz.nucleoid.plasmid.api.game.GameSpace;
Expand All @@ -21,6 +23,20 @@ public interface GameSpaceWorlds extends Iterable<ServerWorld> {
*/
ServerWorld add(RuntimeWorldConfig worldConfig);


/**
* Creates (or loads) and adds a persistent world to be associated with this {@link GameSpace}.
* When the game is closed, the world will be unloaded, with all chunks saved.
* If world using this id is already loaded, this method will throw an exception.
*
* @param worldConfig a config describing how the new world should be created and how it should behave
* @return the created world instance
* @see RuntimeWorldConfig
*/
@ApiStatus.Experimental
ServerWorld addPersistent(Identifier identifier, RuntimeWorldConfig worldConfig);


/**
* Removes and deletes a temporary world that is associated with this {@link GameSpace}.
* The passed world must have been created through {@link GameSpaceWorlds#add(RuntimeWorldConfig)}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import com.google.common.collect.Iterators;
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier;
import net.minecraft.world.GameRules;
import net.minecraft.world.World;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -37,13 +39,29 @@ public ServerWorld add(RuntimeWorldConfig worldConfig) {
return worldHandle.asWorld();
}

@Override
public ServerWorld addPersistent(Identifier identifier, RuntimeWorldConfig worldConfig) {
var world = this.space.getServer().getWorld(RegistryKey.of(RegistryKeys.WORLD, identifier));
if (world != null) {
throw new RuntimeException("World '" + identifier + "' is already loaded!");
}

applyDefaultsTo(worldConfig);

var worldHandle = Fantasy.get(this.space.getServer()).getOrOpenPersistentWorld(identifier, worldConfig);
this.worlds.put(worldHandle.asWorld().getRegistryKey(), worldHandle);
this.space.onAddWorld(worldHandle);

return worldHandle.asWorld();
}

@Override
public boolean remove(ServerWorld world) {
var dimension = world.getRegistryKey();
var worldHandle = this.worlds.remove(dimension);
if (worldHandle != null) {
this.space.onRemoveWorld(dimension);
worldHandle.delete();
worldHandle.unload();
return true;
} else {
return false;
Expand All @@ -52,7 +70,7 @@ public boolean remove(ServerWorld world) {

void clear() {
for (var worldHandler : this.worlds.values()) {
worldHandler.delete();
worldHandler.unload();
}
this.worlds.clear();
}
Expand Down
55 changes: 55 additions & 0 deletions src/testmod/java/xyz/nucleoid/plasmid/test/PersistentGame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package xyz.nucleoid.plasmid.test;

import net.minecraft.registry.RegistryKeys;
import net.minecraft.util.*;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.GameMode;
import net.minecraft.world.GameRules;
import net.minecraft.world.biome.BiomeKeys;
import net.minecraft.world.gen.chunk.FlatChunkGenerator;
import net.minecraft.world.gen.chunk.FlatChunkGeneratorConfig;
import xyz.nucleoid.fantasy.RuntimeWorldConfig;
import xyz.nucleoid.plasmid.api.game.*;
import xyz.nucleoid.plasmid.api.game.event.GamePlayerEvents;
import xyz.nucleoid.plasmid.api.game.player.JoinOffer;
import xyz.nucleoid.plasmid.api.game.rule.GameRuleType;
import xyz.nucleoid.stimuli.event.EventResult;
import xyz.nucleoid.stimuli.event.player.PlayerDeathEvent;

import java.util.List;
import java.util.Optional;

public final class PersistentGame {
public static GameOpenProcedure open(GameOpenContext<Unit> context) {
var biome = context.server().getRegistryManager().getOrThrow(RegistryKeys.BIOME).getOrThrow(BiomeKeys.CHERRY_GROVE);

var worldConfig = new RuntimeWorldConfig()
.setGenerator(new FlatChunkGenerator(new FlatChunkGeneratorConfig(Optional.empty(), biome, List.of())))
.setTimeOfDay(6000)
.setGameRule(GameRules.KEEP_INVENTORY, true);

return context.open((activity) -> {
var gameSpace = activity.getGameSpace();
var world = gameSpace.getWorlds().addPersistent(Identifier.of("testmod", "persistent_world"), worldConfig);


activity.listen(GamePlayerEvents.OFFER, JoinOffer::accept);
activity.listen(GamePlayerEvents.ACCEPT, acceptor ->
acceptor.teleport(world, new Vec3d(0.0, 65.0, 0.0))
.thenRunForEach(joiningPlayer -> {
joiningPlayer.changeGameMode(GameMode.CREATIVE);
})
);


activity.allow(GameRuleType.PVP).allow(GameRuleType.MODIFY_ARMOR);
activity.deny(GameRuleType.FALL_DAMAGE).deny(GameRuleType.HUNGER);
activity.deny(GameRuleType.THROW_ITEMS);

activity.listen(PlayerDeathEvent.EVENT, (player, source) -> {
player.setPos(0.0, 65.0, 0.0);
return EventResult.DENY;
});
});
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package xyz.nucleoid.plasmid.test;

import com.mojang.serialization.MapCodec;
import eu.pb4.polymer.blocks.api.BlockModelType;
import eu.pb4.polymer.blocks.api.BlockResourceCreator;
import eu.pb4.polymer.blocks.api.PolymerBlockModel;
Expand All @@ -15,6 +16,7 @@
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.util.Identifier;
import net.minecraft.util.Unit;
import xyz.nucleoid.plasmid.api.game.GameType;
import xyz.nucleoid.plasmid.api.game.common.GameResourcePack;

Expand Down Expand Up @@ -45,6 +47,7 @@ public class TestInitializer implements ModInitializer {
@Override
public void onInitialize() {
GameType.register(Identifier.of(ID, "test"), TestConfig.CODEC, TestGame::open);
GameType.register(Identifier.of(ID, "persistent"), MapCodec.unit(Unit.INSTANCE), PersistentGame::open);
GameType.register(Identifier.of(ID, "no_join"), TestConfig.CODEC, PlayerlessGame::open);
GameType.register(Identifier.of(ID, "test_rp"), TestConfig.CODEC, TestGameWithResourcePack::open);
GameType.register(Identifier.of(ID, "jank"), TestConfig.CODEC, JankGame::open);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"type": "testmod:persistent",
"icon": "dirt",
"description": []
}

0 comments on commit a06fa73

Please sign in to comment.