Skip to content

Commit

Permalink
Save custom data for ServerWorldProperties
Browse files Browse the repository at this point in the history
  • Loading branch information
aromaa committed Feb 2, 2025
1 parent 49fe76a commit 3a2be1f
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
import net.minecraft.world.level.storage.PrimaryLevelData;
import net.minecraft.world.ticks.SavedTick;
import net.minecraft.world.ticks.ScheduledTick;
import org.spongepowered.api.data.DataHolder;
Expand All @@ -58,7 +59,8 @@
MapItemSavedData.class,
LevelChunk.class,
ScheduledTick.class,
SavedTick.class})
SavedTick.class,
PrimaryLevelData.class})
public abstract class SpongeDataHolderMixin implements SpongeDataHolderBridge {

private DataManipulator.Mutable impl$manipulator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,21 @@
*/
package org.spongepowered.common.mixin.core.world.level.storage;

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.WorldData;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.common.bridge.data.DataCompoundHolder;
import org.spongepowered.common.bridge.world.level.storage.PrimaryLevelDataBridge;
import org.spongepowered.common.data.DataUtil;
import org.spongepowered.common.util.Constants;

@Mixin(LevelStorageSource.LevelStorageAccess.class)
Expand All @@ -51,16 +54,19 @@ private String modifyMinecraftExceptionOutputIfNotInitializationTime(final Strin
return "Lock for world " + this.levelDirectory.path() + " is no longer valid!";
}

@Redirect(
@WrapOperation(
method = "saveDataTag(Lnet/minecraft/core/RegistryAccess;Lnet/minecraft/world/level/storage/WorldData;Lnet/minecraft/nbt/CompoundTag;)V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/nbt/CompoundTag;put(Ljava/lang/String;Lnet/minecraft/nbt/Tag;)Lnet/minecraft/nbt/Tag;"
target = "Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;saveLevelData(Lnet/minecraft/nbt/CompoundTag;)V"
)
)
private Tag impl$saveSpongeLevelData(final CompoundTag root, final String path, final Tag data, final RegistryAccess p_237288_1_,
final WorldData levelData) {
private void impl$saveSpongeLevelData(final LevelStorageSource.LevelStorageAccess instance, final CompoundTag root, final Operation<Void> original,
final RegistryAccess $$0, final WorldData levelData, final @Nullable CompoundTag $$2) {
root.put(Constants.Sponge.Data.V2.SPONGE_DATA, ((PrimaryLevelDataBridge) levelData).bridge$writeSpongeLevelData());
return root.put(path, data);
if (DataUtil.syncDataToTag(levelData)) {
root.merge(((DataCompoundHolder) levelData).data$getCompound());
}
original.call(instance, root);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,12 @@
import org.spongepowered.common.accessor.server.MinecraftServerAccessor;
import org.spongepowered.common.accessor.world.level.LevelSettingsAccessor;
import org.spongepowered.common.bridge.ResourceKeyBridge;
import org.spongepowered.common.bridge.data.DataCompoundHolder;
import org.spongepowered.common.bridge.world.level.dimension.LevelStemBridge;
import org.spongepowered.common.bridge.world.level.storage.PrimaryLevelDataBridge;
import org.spongepowered.common.config.inheritable.InheritableConfigHandle;
import org.spongepowered.common.config.inheritable.WorldConfig;
import org.spongepowered.common.data.DataUtil;
import org.spongepowered.common.data.fixer.LegacyUUIDCodec;
import org.spongepowered.common.util.Constants;
import org.spongepowered.common.util.MapUtil;
Expand All @@ -80,7 +82,7 @@
import java.util.UUID;

@Mixin(PrimaryLevelData.class)
public abstract class PrimaryLevelDataMixin implements WorldData, PrimaryLevelDataBridge, ResourceKeyBridge {
public abstract class PrimaryLevelDataMixin implements WorldData, PrimaryLevelDataBridge, ResourceKeyBridge, DataCompoundHolder {

// @formatter:off
@Shadow private LevelSettings settings;
Expand All @@ -105,6 +107,7 @@ public abstract class PrimaryLevelDataMixin implements WorldData, PrimaryLevelDa
private boolean impl$customDifficulty = false, impl$customGameType = false, impl$customSpawnPosition = false, impl$loadOnStartup, impl$performsSpawnLogic;

private BiMap<Integer, UUID> impl$mapUUIDIndex = HashBiMap.create();
private @Nullable CompoundTag impl$compound;

@Override
public boolean bridge$isVanilla() {
Expand Down Expand Up @@ -362,21 +365,27 @@ public ServerLevelData overworldData() {
@Override
@SuppressWarnings("deprecated")
public void bridge$readSpongeLevelData(final Dynamic<Tag> dynamic) {
dynamic.get(Constants.Sponge.World.UNIQUE_ID).read(UUIDUtil.CODEC).result().ifPresent(value -> this.impl$uniqueId = value);

dynamic.get(Constants.Map.MAP_UUID_INDEX).readMap(Codec.STRING, UUIDUtil.CODEC).result().ifPresent(value -> {
final BiMap<Integer, UUID> mapIndex = HashBiMap.create();
for (final Pair<String, UUID> pair : value) {
final int id = Integer.parseInt(pair.getFirst());
mapIndex.put(id, pair.getSecond());
}
this.impl$mapUUIDIndex = mapIndex;
dynamic.get(Constants.Sponge.Data.V2.SPONGE_DATA).get().ifSuccess(v2 -> {
v2.get(Constants.Sponge.World.UNIQUE_ID).read(UUIDUtil.CODEC).result().ifPresent(value -> this.impl$uniqueId = value);

v2.get(Constants.Map.MAP_UUID_INDEX).readMap(Codec.STRING, UUIDUtil.CODEC).result().ifPresent(value -> {
final BiMap<Integer, UUID> mapIndex = HashBiMap.create();
for (final Pair<String, UUID> pair : value) {
final int id = Integer.parseInt(pair.getFirst());
mapIndex.put(id, pair.getSecond());
}
this.impl$mapUUIDIndex = mapIndex;
});

// TODO Move this to Schema
v2.get(Constants.Sponge.LEGACY_SPONGE_PLAYER_UUID_TABLE).readList(LegacyUUIDCodec.CODEC).result().orElseGet(() ->
v2.get(Constants.Sponge.SPONGE_PLAYER_UUID_TABLE).readList(UUIDUtil.CODEC).result().orElse(Collections.emptyList())
).forEach(uuid -> this.impl$playerUniqueIdMap.inverse().putIfAbsent(uuid, this.impl$playerUniqueIdMap.size()));
});

// TODO Move this to Schema
dynamic.get(Constants.Sponge.LEGACY_SPONGE_PLAYER_UUID_TABLE).readList(LegacyUUIDCodec.CODEC).result().orElseGet(() ->
dynamic.get(Constants.Sponge.SPONGE_PLAYER_UUID_TABLE).readList(UUIDUtil.CODEC).result().orElse(Collections.emptyList())
).forEach(uuid -> this.impl$playerUniqueIdMap.inverse().putIfAbsent(uuid, this.impl$playerUniqueIdMap.size()));
this.data$setCompound((CompoundTag) dynamic.getValue());
DataUtil.syncTagToData(this);
this.data$setCompound(null);
}

@Override
Expand Down Expand Up @@ -423,4 +432,14 @@ public String toString() {
cir.setReturnValue(false);
}
}

@Override
public CompoundTag data$getCompound() {
return this.impl$compound;
}

@Override
public void data$setCompound(final CompoundTag nbt) {
this.impl$compound = nbt;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
import org.spongepowered.api.util.Ticks;
import org.spongepowered.api.world.chunk.WorldChunk;
import org.spongepowered.api.world.server.ServerLocation;
import org.spongepowered.api.world.server.storage.ServerWorldProperties;
import org.spongepowered.math.vector.Vector3i;
import org.spongepowered.plugin.PluginContainer;
import org.spongepowered.plugin.builtin.jvm.Plugin;
Expand Down Expand Up @@ -99,7 +100,8 @@ private enum Type {
PLAYER,
USER,
BLOCK,
CHUNK
CHUNK,
LEVEL
}

@Listener
Expand Down Expand Up @@ -165,6 +167,11 @@ private void onRegisterSpongeCommand(final RegisterCommandEvent<Command.Paramete
player.sendActionBar(Component.text(oldNumber2));
player.world().chunk(player.location().chunkPosition()).offer(this.myDataKey, oldNumber2 + number);
break;
case LEVEL:
final Integer oldNumber3 = player.world().properties().get(this.myDataKey).orElse(0);
player.sendActionBar(Component.text(oldNumber3));
player.world().properties().offer(this.myDataKey, oldNumber3 + number);
break;
}
return CommandResult.success();
})
Expand All @@ -183,7 +190,7 @@ private void onRegisterData(final RegisterDataEvent event) {
.build();


final DataStore dataStore = DataStore.of(this.myDataKey, DataQuery.of("mykey"), ItemStack.class, User.class, ServerPlayer.class, BlockEntity.class, Entity.class, WorldChunk.class);
final DataStore dataStore = DataStore.of(this.myDataKey, DataQuery.of("mykey"), ItemStack.class, User.class, ServerPlayer.class, BlockEntity.class, Entity.class, WorldChunk.class, ServerWorldProperties.class);
final DataRegistration myRegistration = DataRegistration.builder()
.dataKey(this.myDataKey)
.store(dataStore)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
*/
package org.spongepowered.vanilla.mixin.core.world.level.storage;

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.mojang.serialization.Dynamic;
import com.mojang.serialization.Lifecycle;
import net.minecraft.nbt.CompoundTag;
Expand All @@ -35,40 +37,37 @@
import net.minecraft.world.level.storage.PrimaryLevelData;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.common.bridge.world.level.storage.PrimaryLevelDataBridge;
import org.spongepowered.common.util.Constants;

@Mixin(LevelStorageSource.class)
public abstract class LevelStorageSourceMixin_Vanilla {

private static Dynamic<Tag> impl$spongeLevelData;

@SuppressWarnings("deprecation")
@Redirect(
@WrapOperation(
method = "readLevelDataTagFixed",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/nbt/CompoundTag;getCompound(Ljava/lang/String;)Lnet/minecraft/nbt/CompoundTag;",
ordinal = 0
)
)
private static CompoundTag impl$createSpongeLevelData(final CompoundTag compoundNBT, final String path) {
LevelStorageSourceMixin_Vanilla.impl$spongeLevelData = new Dynamic<>(NbtOps.INSTANCE, compoundNBT.getCompound(Constants.Sponge.Data.V2.SPONGE_DATA));
return compoundNBT.getCompound(path);
private static CompoundTag impl$createSpongeLevelData(final CompoundTag compoundNBT, final String path, final Operation<CompoundTag> original) {
LevelStorageSourceMixin_Vanilla.impl$spongeLevelData = new Dynamic<>(NbtOps.INSTANCE, compoundNBT);
return original.call(compoundNBT, path);
}

@Redirect(
@WrapOperation(
method = "getLevelDataAndDimensions",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/storage/PrimaryLevelData;parse(Lcom/mojang/serialization/Dynamic;Lnet/minecraft/world/level/LevelSettings;Lnet/minecraft/world/level/storage/PrimaryLevelData$SpecialWorldProperty;Lnet/minecraft/world/level/levelgen/WorldOptions;Lcom/mojang/serialization/Lifecycle;)Lnet/minecraft/world/level/storage/PrimaryLevelData;"
)
)
private static PrimaryLevelData impl$readSpongeLevelData(final Dynamic<?> $$0, final LevelSettings $$1,
final PrimaryLevelData.SpecialWorldProperty $$2, final WorldOptions $$3, final Lifecycle $$4)
final PrimaryLevelData.SpecialWorldProperty $$2, final WorldOptions $$3, final Lifecycle $$4, final Operation<PrimaryLevelData> original)
{
final PrimaryLevelData levelData = PrimaryLevelData.parse($$0, $$1, $$2, $$3, $$4);
final PrimaryLevelData levelData = original.call($$0, $$1, $$2, $$3, $$4);

((PrimaryLevelDataBridge) levelData).bridge$readSpongeLevelData(LevelStorageSourceMixin_Vanilla.impl$spongeLevelData);

Expand Down

0 comments on commit 3a2be1f

Please sign in to comment.