Skip to content

Commit

Permalink
Merge pull request #111 from InfernalSuite/develop
Browse files Browse the repository at this point in the history
Merge from develop
  • Loading branch information
kyngs authored May 24, 2024
2 parents dc11277 + a339b6b commit 45af324
Show file tree
Hide file tree
Showing 12 changed files with 215 additions and 29 deletions.
15 changes: 11 additions & 4 deletions .docs/api/properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,17 @@ Property "types" are handled by [SlimeProperty][1] instances. Whilst creating [S
// create a new and empty property map
SlimePropertyMap properties = new SlimePropertyMap();

properties.setString(SlimeProperties.DIFFICULTY, "normal");
properties.setInt(SlimeProperties.SPAWN_X, 123);
properties.setInt(SlimeProperties.SPAWN_Y, 112);
properties.setInt(SlimeProperties.SPAWN_Z, 170);
properties.setValue(SlimeProperties.DIFFICULTY, "normal");
properties.setValue(SlimeProperties.SPAWN_X, 123);
properties.setValue(SlimeProperties.SPAWN_Y, 112);
properties.setValue(SlimeProperties.SPAWN_Z, 170);
properties.setValue(SlimeProperties.ALLOW_ANIMALS, false);
properties.setValue(SlimeProperties.ALLOW_MONSTERS, false);
properties.setValue(SlimeProperties.DRAGON_BATTLE, false);
properties.setValue(SlimeProperties.PVP, false);
properties.setValue(SlimeProperties.ENVIRONMENT, "normal");
properties.setValue(SlimeProperties.WORLD_TYPE, "DEFAULT");
properties.setValue(SlimeProperties.DEFAULT_BIOME, "minecraft:plains");
// add as many as you would like
```

Expand Down
18 changes: 18 additions & 0 deletions api/src/main/java/com/infernalsuite/aswm/api/SlimePlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,24 @@ public interface SlimePlugin {
SlimeWorld loadWorld(SlimeLoader loader, String worldName, boolean readOnly, SlimePropertyMap propertyMap) throws
UnknownWorldException, IOException, CorruptedWorldException, NewerFormatException, WorldLockedException;

/**
* Reads a world using a specificied {@link SlimeLoader}.
* <strong>This world won't be loaded into the server's world list.</strong>
*
* @param loader {@link SlimeLoader} used to retrieve the world.
* @param worldName Name of the world.
* @param readOnly Whether read-only mode is enabled.
* @param propertyMap A {@link SlimePropertyMap} object containing all the properties of the world.
* @return A {@link SlimeWorld}, which is the in-memory representation of the world.
* @throws UnknownWorldException if the world cannot be found.
* @throws IOException if the world cannot be obtained from the speficied data source.
* @throws CorruptedWorldException if the world retrieved cannot be parsed into a {@link SlimeWorld} object.
* @throws NewerFormatException if the world uses a newer version of the SRF.
* @throws WorldLockedException if the world is already being used on another server when trying to open it without read-only mode enabled.
*/
SlimeWorld readWorld(SlimeLoader loader, String worldName, boolean readOnly, SlimePropertyMap propertyMap) throws
UnknownWorldException, IOException, CorruptedWorldException, NewerFormatException, WorldLockedException;

/**
* Gets a world which has already been loaded by ASWM.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.infernalsuite.aswm.api.world.properties;

import com.infernalsuite.aswm.api.world.properties.type.SlimePropertyBoolean;
import com.infernalsuite.aswm.api.world.properties.type.SlimePropertyFloat;
import com.infernalsuite.aswm.api.world.properties.type.SlimePropertyInt;
import com.infernalsuite.aswm.api.world.properties.type.SlimePropertyString;
import org.jetbrains.annotations.ApiStatus;
Expand All @@ -25,6 +26,11 @@ public class SlimeProperties {
*/
public static final SlimeProperty<Integer> SPAWN_Z = new SlimePropertyInt("spawnZ", 0);

/**
* The yaw of the world spawn
*/
public static final SlimeProperty<Float> SPAWN_YAW = new SlimePropertyFloat("spawnYaw", 0.0f);

/**
* The difficulty set for the world
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.infernalsuite.aswm.api.world.properties.type;

import com.flowpowered.nbt.CompoundMap;
import com.flowpowered.nbt.FloatTag;
import com.flowpowered.nbt.Tag;
import com.infernalsuite.aswm.api.world.properties.SlimeProperty;

import java.util.function.Function;

/**
* A slime property of type float
*/
public class SlimePropertyFloat extends SlimeProperty<Float> {

public SlimePropertyFloat(String nbtName, Float defaultValue, Function<Float, Boolean> validator) {
super(nbtName, defaultValue, validator);
}

public SlimePropertyFloat(String nbtName, Float defaultValue) {
super(nbtName, defaultValue);
}

@Override
protected void writeValue(CompoundMap compound, Float value) {
compound.put(getNbtName(), new FloatTag(getNbtName(), value));
}

@Override
protected Float readValue(Tag<?> compoundTag) {
return compoundTag.getAsFloatTag()
.map(Tag::getValue)
.orElse(getDefaultValue());
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package com.infernalsuite.aswm.serialization.slime;

import com.flowpowered.nbt.CompoundTag;
import com.flowpowered.nbt.ListTag;
import com.infernalsuite.aswm.api.world.SlimeChunk;
import com.infernalsuite.aswm.api.world.SlimeChunkSection;
import com.infernalsuite.aswm.api.world.SlimeWorld;
import com.infernalsuite.aswm.api.world.properties.SlimeProperties;
import com.infernalsuite.aswm.api.world.properties.SlimePropertyMap;

import java.util.List;

public class ChunkPruner {

public static boolean canBePruned(SlimeWorld world, SlimeChunk chunk) {
Expand Down Expand Up @@ -47,15 +50,22 @@ public static boolean canBePruned(SlimeWorld world, SlimeChunk chunk) {
private static boolean areSectionsEmpty(SlimeChunkSection[] sections) {
for (SlimeChunkSection chunkSection : sections) {
try {
CompoundTag compoundTag = chunkSection.getBlockStatesTag().getAsListTag("palette").get().getAsCompoundTagList().get().getValue().get(0);
if (!compoundTag.getStringValue("Name").get().equals("minecraft:air")) {
List<CompoundTag> palettes = chunkSection.getBlockStatesTag().getAsListTag("palette")
.get().getAsCompoundTagList()
.get().getValue();

if (palettes.size() > 1) return false; // If there is more than one palette, the section is not empty
if (!palettes.get(0).getStringValue("Name").get().equals("minecraft:air")) {
return false;
}
} catch (Exception e) {
return false;
}

// The section is empty, continue to the next one
}

return false;
// All sections are empty, we can omit this chunk
return true;
}
}
4 changes: 4 additions & 0 deletions importer/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ plugins {
dependencies {
implementation(project(":api"))
implementation(project(":core"))
implementation(project(":slimeworldmanager-api"))
}

tasks {
Expand All @@ -13,6 +14,9 @@ tasks {
attributes["Main-Class"] = "com.infernalsuite.aswm.importer.SWMImporter"
}
}
shadowJar {
minimize()
}
}

description = "slimeworldmanager-importer"
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: kyngs <[email protected]>
Date: Sat, 18 May 2024 20:34:06 +0200
Subject: [PATCH] Add default spawn yaw, propagate CraftWorld#setSpawnLocation
to the SlimeProperties.


diff --git a/src/main/java/com/infernalsuite/aswm/level/SlimeLevelInstance.java b/src/main/java/com/infernalsuite/aswm/level/SlimeLevelInstance.java
index a525fa1781535d458c5ecb67e261520692c858ac..1d5547a74042743e388f77f70b9ebbd37be3f1bc 100644
--- a/src/main/java/com/infernalsuite/aswm/level/SlimeLevelInstance.java
+++ b/src/main/java/com/infernalsuite/aswm/level/SlimeLevelInstance.java
@@ -95,7 +95,11 @@ public class SlimeLevelInstance extends ServerLevel {
SlimePropertyMap propertyMap = slimeBootstrap.initial().getPropertyMap();

this.serverLevelData.setDifficulty(Difficulty.valueOf(propertyMap.getValue(SlimeProperties.DIFFICULTY).toUpperCase()));
- this.serverLevelData.setSpawn(new BlockPos(propertyMap.getValue(SlimeProperties.SPAWN_X), propertyMap.getValue(SlimeProperties.SPAWN_Y), propertyMap.getValue(SlimeProperties.SPAWN_Z)), 0);
+ this.serverLevelData.setSpawn(new BlockPos(
+ propertyMap.getValue(SlimeProperties.SPAWN_X),
+ propertyMap.getValue(SlimeProperties.SPAWN_Y),
+ propertyMap.getValue(SlimeProperties.SPAWN_Z)),
+ propertyMap.getValue(SlimeProperties.SPAWN_YAW));
super.setSpawnSettings(propertyMap.getValue(SlimeProperties.ALLOW_MONSTERS), propertyMap.getValue(SlimeProperties.ALLOW_ANIMALS));

this.pvpMode = propertyMap.getValue(SlimeProperties.PVP);
@@ -187,6 +191,17 @@ public class SlimeLevelInstance extends ServerLevel {
}
}

+ @Override
+ public void setDefaultSpawnPos(BlockPos pos, float angle) {
+ super.setDefaultSpawnPos(pos, angle);
+
+ SlimePropertyMap propertyMap = this.slimeInstance.getPropertyMap();
+ propertyMap.setValue(SlimeProperties.SPAWN_X, pos.getX());
+ propertyMap.setValue(SlimeProperties.SPAWN_Y, pos.getY());
+ propertyMap.setValue(SlimeProperties.SPAWN_Z, pos.getZ());
+ propertyMap.setValue(SlimeProperties.SPAWN_YAW, angle);
+ }
+
// @Override
// public void unload(LevelChunk chunk) {
// this.slimeInstance.unload(chunk);
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: kyngs <[email protected]>
Date: Sun, 19 May 2024 19:17:07 +0200
Subject: [PATCH] Fix chunks not getting serialized when reloaded.


diff --git a/src/main/java/com/infernalsuite/aswm/level/SlimeChunkLevel.java b/src/main/java/com/infernalsuite/aswm/level/SlimeChunkLevel.java
index b159fc8751e9840b311cc1eda01e496e2dbc5f2e..2ebabf20c37d2b5c479de5bb241aa334f92a1104 100644
--- a/src/main/java/com/infernalsuite/aswm/level/SlimeChunkLevel.java
+++ b/src/main/java/com/infernalsuite/aswm/level/SlimeChunkLevel.java
@@ -24,4 +24,10 @@ public class SlimeChunkLevel extends LevelChunk {
super.unloadCallback();
this.inMemoryWorld.unload(this);
}
+
+ @Override
+ public void loadCallback() {
+ super.loadCallback();
+ this.inMemoryWorld.ensureChunkMarkedAsLoaded(this);
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/infernalsuite/aswm/level/SlimeInMemoryWorld.java b/src/main/java/com/infernalsuite/aswm/level/SlimeInMemoryWorld.java
index 95133e0ff8a8bdfc84c1dd7ff6b2c7ed7ae9a2f9..b54b231e22967eb0b34e6ba9b7ec9cdf64bad87e 100644
--- a/src/main/java/com/infernalsuite/aswm/level/SlimeInMemoryWorld.java
+++ b/src/main/java/com/infernalsuite/aswm/level/SlimeInMemoryWorld.java
@@ -219,7 +219,7 @@ public class SlimeInMemoryWorld implements SlimeWorld, SlimeWorldInstance {
} else {
chunk = safeNmsChunkWrapper.getWrapper().getChunk();
}
- } else if (clonedChunk instanceof NMSSlimeChunk nmsSlimeChunk) {
+ } else if (clonedChunk instanceof NMSSlimeChunk nmsSlimeChunk) {
chunk = nmsSlimeChunk.getChunk();
}

@@ -279,4 +279,10 @@ public class SlimeInMemoryWorld implements SlimeWorld, SlimeWorldInstance {
public @NotNull PersistentDataContainer getPersistentDataContainer() {
return this.extraPDC;
}
+
+ public void ensureChunkMarkedAsLoaded(SlimeChunkLevel chunk) {
+ if (chunkStorage.get(new ChunkPos(chunk.locX, chunk.locZ)) instanceof SlimeChunkSkeleton skeleton) {
+ chunkStorage.put(new ChunkPos(chunk.locX, chunk.locZ), new NMSSlimeChunk(chunk, skeleton));
+ }
+ }
}
22 changes: 22 additions & 0 deletions plugin/src/main/java/com/grinderwolf/swm/plugin/SWMPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,28 @@ public SlimeWorld loadWorld(SlimeLoader loader, String worldName, boolean readOn
return dataFixed;
}

@Override
public SlimeWorld readWorld(SlimeLoader loader, String worldName, boolean readOnly, SlimePropertyMap propertyMap) throws UnknownWorldException, IOException, CorruptedWorldException, NewerFormatException, WorldLockedException {
Objects.requireNonNull(loader, "Loader cannot be null");
Objects.requireNonNull(worldName, "World name cannot be null");
Objects.requireNonNull(propertyMap, "Properties cannot be null");

long start = System.currentTimeMillis();

Logging.info("Reading world " + worldName + ".");
byte[] serializedWorld = loader.loadWorld(worldName);

SlimeWorld slimeWorld = SlimeWorldReaderRegistry.readWorld(loader, worldName, serializedWorld, propertyMap, readOnly);
Logging.info("Applying datafixers for " + worldName + ".");
SlimeWorld dataFixed = SlimeNMSBridge.instance().applyDataFixers(slimeWorld);

if (!readOnly) loader.saveWorld(worldName, SlimeSerializer.serialize(dataFixed)); // Write dataFixed world back to loader

Logging.info("World " + worldName + " read in " + (System.currentTimeMillis() - start) + "ms.");

return dataFixed;
}

@Override
public SlimeWorld getWorld(String worldName) {
return loadedWorlds.get(worldName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ public boolean onCommand(CommandSender sender, String[] args) {
if (loader == null) {
throw new IllegalArgumentException("invalid data source " + worldData.getDataSource());
}

SlimeWorld slimeWorld = SWMPlugin.getInstance().loadWorld(loader, templateWorldName, true, worldData.toPropertyMap()).clone(worldName);
SlimeWorld templateWorld = SWMPlugin.getInstance().readWorld(loader, templateWorldName, true, worldData.toPropertyMap());
SlimeWorld slimeWorld = templateWorld.clone(worldName);
Bukkit.getScheduler().runTask(SWMPlugin.getInstance(), () -> {
try {
SWMPlugin.getInstance().loadWorld(slimeWorld, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

public class UnloadWorldCmd implements Subcommand {
Expand Down Expand Up @@ -75,19 +74,19 @@ public boolean onCommand(CommandSender sender, String[] args) {
// Teleport all players outside the world before unloading it
var players = world.getPlayers();

AtomicBoolean success = new AtomicBoolean();

if (!players.isEmpty()) {
Location spawnLocation = findValidDefaultSpawn();
CompletableFuture<Void> cf = CompletableFuture.allOf(players.stream().map(player -> player.teleportAsync(spawnLocation)).collect(Collectors.toList()).toArray(CompletableFuture[]::new));
cf.thenRun(() -> {
Bukkit.getScheduler().runTask(SWMPlugin.getInstance(), () -> success.set(Bukkit.unloadWorld(world, true)));
if (!success.get()) {
sender.sendMessage(Logging.COMMAND_PREFIX + ChatColor.RED + "Failed to unload world " + worldName + ".");
} else {
world.save();
}
sender.sendMessage(Logging.COMMAND_PREFIX + ChatColor.GREEN + "World " + ChatColor.YELLOW + worldName + ChatColor.GREEN + " unloaded correctly.");
Bukkit.getScheduler().runTask(SWMPlugin.getInstance(), () -> {
boolean success = Bukkit.unloadWorld(world, true);

if (!success) {
sender.sendMessage(Logging.COMMAND_PREFIX + ChatColor.RED + "Failed to unload world " + worldName + ".");
} else {
sender.sendMessage(Logging.COMMAND_PREFIX + ChatColor.GREEN + "World " + ChatColor.YELLOW + worldName + ChatColor.GREEN + " unloaded correctly.");
}
});
});
} else {
Bukkit.unloadWorld(world, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,21 +54,19 @@ public byte[] loadWorld(String worldName) throws UnknownWorldException, IOExcept
//
// });

RandomAccessFile file = new RandomAccessFile(new File(worldDir, worldName + ".slime"), "rw");
//FIXME: Why are we using a RandomAccessFile here? We're not using it as a RandomAccessFile, we're using it as a normal file.

try (RandomAccessFile file = new RandomAccessFile(new File(worldDir, worldName + ".slime"), "rw")) {
if (file.length() > Integer.MAX_VALUE) {
throw new IndexOutOfBoundsException("World is too big!");
}

if (file != null && file.length() > Integer.MAX_VALUE) {
throw new IndexOutOfBoundsException("World is too big!");
}

byte[] serializedWorld = new byte[0];
if (file != null) {
serializedWorld = new byte[(int) file.length()];
byte[] serializedWorld = new byte[(int) file.length()];
file.seek(0); // Make sure we're at the start of the file
file.readFully(serializedWorld);
}

return serializedWorld;
return serializedWorld;
}
}

@Override
Expand Down

0 comments on commit 45af324

Please sign in to comment.