mirror of
https://github.com/architectury/architectury-api.git
synced 2026-03-31 05:15:56 -05:00
* Created Chunk save and load event. Closes #89 * Fixed missing licence * Update common/src/main/java/me/shedaniel/architectury/event/events/ChunkEvent.java * Update common/src/main/java/me/shedaniel/architectury/event/events/ChunkEvent.java * Update common/src/main/java/me/shedaniel/architectury/event/events/ChunkEvent.java * Supply ServerLevel in ChunkEvent.LOAD, style cleanup Signed-off-by: shedaniel <daniel@shedaniel.me> * Add "Data" suffix to Chunk IO Events and mark level as nullable for load * Update common/src/main/java/me/shedaniel/architectury/event/events/ChunkEvent.java * Bump to 1.16 Co-authored-by: shedaniel <daniel@shedaniel.me> Co-authored-by: Max <maxh2709@gmail.com>
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package me.shedaniel.architectury.event.events;
|
||||
|
||||
import me.shedaniel.architectury.event.Event;
|
||||
import me.shedaniel.architectury.event.EventFactory;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface ChunkEvent {
|
||||
/**
|
||||
* @see SaveData#save(ChunkAccess, ServerLevel, CompoundTag)
|
||||
*/
|
||||
Event<SaveData> SAVE_DATA = EventFactory.createLoop();
|
||||
/**
|
||||
* @see LoadData#load(ChunkAccess, ServerLevel, CompoundTag)
|
||||
*/
|
||||
Event<LoadData> LOAD_DATA = EventFactory.createLoop();
|
||||
|
||||
interface SaveData {
|
||||
/**
|
||||
* Invoked when a chunk's data is saved, just before the data is written.
|
||||
* Add your own data to the {@link CompoundTag} parameter to get your data saved as well.
|
||||
* Equivalent to Forge's {@code ChunkDataEvent.Save}.
|
||||
*
|
||||
* @param chunk The chunk that is saved.
|
||||
* @param level The level the chunk is in.
|
||||
* @param nbt The chunk data that is written to the save file.
|
||||
*/
|
||||
void save(ChunkAccess chunk, ServerLevel level, CompoundTag nbt);
|
||||
}
|
||||
|
||||
interface LoadData {
|
||||
/**
|
||||
* Invoked just before a chunk's data is fully read.
|
||||
* You can read out your own data from the {@link CompoundTag} parameter, when you have saved one before.
|
||||
* Equivalent to Forge's {@code ChunkDataEvent.Load}.
|
||||
*
|
||||
* @param chunk The chunk that is loaded.
|
||||
* @param level The level the chunk is in, may be {@code null}.
|
||||
* @param nbt The chunk data that was read from the save file.
|
||||
*/
|
||||
void load(ChunkAccess chunk, @Nullable ServerLevel level, CompoundTag nbt);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package me.shedaniel.architectury.mixin.fabric;
|
||||
|
||||
import me.shedaniel.architectury.event.events.ChunkEvent;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.level.ChunkMap;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
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.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(ChunkMap.class)
|
||||
public class MixinChunkMap {
|
||||
@Shadow
|
||||
@Final
|
||||
private ServerLevel level;
|
||||
|
||||
@Inject(
|
||||
method = "save",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ChunkMap;write(Lnet/minecraft/world/level/ChunkPos;Lnet/minecraft/nbt/CompoundTag;)V", ordinal = 0),
|
||||
locals = LocalCapture.CAPTURE_FAILHARD
|
||||
)
|
||||
private void save(ChunkAccess chunkAccess, CallbackInfoReturnable<Boolean> cir, ChunkPos pos, ChunkStatus chunkStatus, CompoundTag nbt) {
|
||||
ChunkEvent.SAVE_DATA.invoker().save(chunkAccess, this.level, nbt);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package me.shedaniel.architectury.mixin.fabric;
|
||||
|
||||
import me.shedaniel.architectury.event.events.ChunkEvent;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.ai.village.poi.PoiManager;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.chunk.*;
|
||||
import net.minecraft.world.level.chunk.storage.ChunkSerializer;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
|
||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(ChunkSerializer.class)
|
||||
public class MixinChunkSerializer {
|
||||
@Inject(method = "read", at = @At("RETURN"), locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
private static void load(ServerLevel serverLevel, StructureManager structureManager, PoiManager poiManager, ChunkPos chunkPos, CompoundTag compoundTag,
|
||||
CallbackInfoReturnable<ProtoChunk> cir, ChunkGenerator chunkGenerator, BiomeSource biomeSource, CompoundTag compoundTagLevelData,
|
||||
ChunkBiomeContainer chunkBiomeContainer, UpgradeData upgradeData, ProtoTickList<?> protoTickList, ProtoTickList<?> protoTickList2,
|
||||
boolean bl, ListTag listTag, int i, LevelChunkSection[] levelChunkSections, boolean bl2, ChunkSource chunkSource,
|
||||
LevelLightEngine levelLightEngine, long l, ChunkStatus.ChunkType chunkType, ChunkAccess chunk) {
|
||||
ChunkEvent.LOAD_DATA.invoker().load(chunk, serverLevel, compoundTag);
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,8 @@
|
||||
"MixinBlockItem",
|
||||
"MixinBucketItem",
|
||||
"MixinCatSpawner",
|
||||
"MixinChunkMap",
|
||||
"MixinChunkSerializer",
|
||||
"MixinCollisionContext",
|
||||
"MixinCommands",
|
||||
"MixinDedicatedServer",
|
||||
|
||||
@@ -31,6 +31,7 @@ import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.InteractionResultHolder;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraftforge.event.CommandEvent;
|
||||
import net.minecraftforge.event.RegisterCommandsEvent;
|
||||
import net.minecraftforge.event.ServerChatEvent;
|
||||
@@ -49,6 +50,7 @@ import net.minecraftforge.event.entity.player.PlayerEvent.*;
|
||||
import net.minecraftforge.event.world.BlockEvent.BreakEvent;
|
||||
import net.minecraftforge.event.world.BlockEvent.EntityPlaceEvent;
|
||||
import net.minecraftforge.event.world.BlockEvent.FarmlandTrampleEvent;
|
||||
import net.minecraftforge.event.world.ChunkDataEvent;
|
||||
import net.minecraftforge.event.world.ExplosionEvent.Detonate;
|
||||
import net.minecraftforge.event.world.ExplosionEvent.Start;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
@@ -371,6 +373,28 @@ public class EventHandlerImplCommon {
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGH)
|
||||
public static void event(ChunkDataEvent.Save event) {
|
||||
if (event.getWorld() instanceof ServerLevel) {
|
||||
ChunkEvent.SAVE_DATA.invoker().save(event.getChunk(), (ServerLevel) event.getWorld(), event.getData());
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGH)
|
||||
public static void event(ChunkDataEvent.Load event) {
|
||||
LevelAccessor level = event.getChunk().getWorldForge();
|
||||
if (!(level instanceof ServerLevel)) {
|
||||
level = ((WorldEventAttachment) event).architectury$getAttachedLevel();
|
||||
}
|
||||
ChunkEvent.LOAD_DATA.invoker().load(event.getChunk(), level instanceof ServerLevel ? (ServerLevel) level : null, event.getData());
|
||||
}
|
||||
|
||||
public interface WorldEventAttachment {
|
||||
LevelAccessor architectury$getAttachedLevel();
|
||||
|
||||
void architectury$attachLevel(LevelAccessor level);
|
||||
}
|
||||
|
||||
public static class ModBasedEventHandler {
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package me.shedaniel.architectury.mixin.forge;
|
||||
|
||||
import me.shedaniel.architectury.event.forge.EventHandlerImplCommon;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.ai.village.poi.PoiManager;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||
import net.minecraft.world.level.chunk.storage.ChunkSerializer;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
|
||||
import net.minecraftforge.event.world.ChunkDataEvent;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
@Mixin(ChunkSerializer.class)
|
||||
public class MixinChunkSerializer {
|
||||
@Unique
|
||||
private static ThreadLocal<WeakReference<ServerLevel>> level = new ThreadLocal<>();
|
||||
|
||||
@Inject(method = "read", at = @At("HEAD"))
|
||||
private static void read(ServerLevel worldIn, StructureManager templateManagerIn, PoiManager poiManager, ChunkPos pos, CompoundTag compound, CallbackInfoReturnable<ProtoChunk> cir) {
|
||||
level.set(new WeakReference<>(worldIn));
|
||||
}
|
||||
|
||||
@ModifyArg(method = "read", at = @At(value = "INVOKE",
|
||||
ordinal = 1,
|
||||
target = "Lnet/minecraftforge/eventbus/api/IEventBus;post(Lnet/minecraftforge/eventbus/api/Event;)Z"),
|
||||
index = 0)
|
||||
private static Event modifyProtoChunkLevel(Event event) {
|
||||
// We should get this PRed to Forge
|
||||
WeakReference<ServerLevel> levelRef = level.get();
|
||||
if (levelRef != null && event instanceof ChunkDataEvent.Load) {
|
||||
ChunkDataEvent.Load load = (ChunkDataEvent.Load) event;
|
||||
((EventHandlerImplCommon.WorldEventAttachment) load).architectury$attachLevel(levelRef.get());
|
||||
}
|
||||
level.set(null);
|
||||
return event;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 architectury
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package me.shedaniel.architectury.mixin.forge;
|
||||
|
||||
import me.shedaniel.architectury.event.forge.EventHandlerImplCommon;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
@Mixin(WorldEvent.class)
|
||||
public class MixinWorldEvent implements EventHandlerImplCommon.WorldEventAttachment {
|
||||
@Unique
|
||||
private WeakReference<LevelAccessor> level;
|
||||
|
||||
@Override
|
||||
public LevelAccessor architectury$getAttachedLevel() {
|
||||
return level == null ? null : level.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void architectury$attachLevel(LevelAccessor level) {
|
||||
this.level = new WeakReference<>(level);
|
||||
}
|
||||
}
|
||||
@@ -15,9 +15,11 @@
|
||||
"GameRulesAccessor$IntegerValueSimple",
|
||||
"MixinBlockEntity",
|
||||
"MixinBlockEntityExtension",
|
||||
"MixinChunkSerializer",
|
||||
"MixinClientLevel",
|
||||
"MixinItemExtension",
|
||||
"MixinRegistryEntry",
|
||||
"MixinWorldEvent",
|
||||
"MobSpawnSettingsBuilderAccessor"
|
||||
],
|
||||
"injectors": {
|
||||
|
||||
@@ -6,7 +6,7 @@ supported_version=1.16.4/5
|
||||
|
||||
archives_base_name=architectury
|
||||
archives_base_name_snapshot=architectury-snapshot
|
||||
base_version=1.15
|
||||
base_version=1.16
|
||||
maven_group=me.shedaniel
|
||||
|
||||
fabric_loader_version=0.11.1
|
||||
|
||||
@@ -217,6 +217,12 @@ public class DebugEvents {
|
||||
LightningEvent.STRIKE.register((bolt, level, pos, toStrike) -> {
|
||||
SINK.accept(bolt.getScoreboardName() + " struck at " + toShortString(pos) + logSide(level));
|
||||
});
|
||||
ChunkEvent.LOAD_DATA.register((chunk, level, nbt) -> {
|
||||
SINK.accept("Chunk loaded at x=" + chunk.getPos().x + ", z=" + chunk.getPos().z + " in dimension '" + level.dimension().location() + "'");
|
||||
});
|
||||
ChunkEvent.SAVE_DATA.register((chunk, level, nbt) -> {
|
||||
SINK.accept("Chunk saved at x=" + chunk.getPos().x + ", z=" + chunk.getPos().z + " in dimension '" + level.dimension().location() + "'");
|
||||
});
|
||||
}
|
||||
|
||||
public static String toShortString(Vec3i pos) {
|
||||
|
||||
Reference in New Issue
Block a user