mirror of
https://github.com/webbukkit/dynmap.git
synced 2024-12-24 17:47:40 +01:00
Merge pull request #3567 from kosma/fabric-1.18-onchunkgenerate
Fabric 1.18: Fix onchunkgenerate trigger
This commit is contained in:
commit
ec369e96f8
@ -2,8 +2,6 @@ package org.dynmap.fabric_1_18;
|
||||
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
||||
import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||
@ -20,8 +18,6 @@ import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ChunkHolder;
|
||||
import net.minecraft.server.world.ServerChunkManager;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.collection.IdList;
|
||||
@ -46,11 +42,10 @@ import org.dynmap.fabric_1_18.command.DmarkerCommand;
|
||||
import org.dynmap.fabric_1_18.command.DynmapCommand;
|
||||
import org.dynmap.fabric_1_18.command.DynmapExpCommand;
|
||||
import org.dynmap.fabric_1_18.event.BlockEvents;
|
||||
import org.dynmap.fabric_1_18.event.ChunkDataEvents;
|
||||
import org.dynmap.fabric_1_18.event.CustomServerChunkEvents;
|
||||
import org.dynmap.fabric_1_18.event.CustomServerLifecycleEvents;
|
||||
import org.dynmap.fabric_1_18.event.PlayerEvents;
|
||||
import org.dynmap.fabric_1_18.mixin.BiomeEffectsAccessor;
|
||||
import org.dynmap.fabric_1_18.mixin.ThreadedAnvilChunkStorageAccessor;
|
||||
import org.dynmap.fabric_1_18.permissions.FilePermissions;
|
||||
import org.dynmap.fabric_1_18.permissions.OpPermissions;
|
||||
import org.dynmap.fabric_1_18.permissions.PermissionProvider;
|
||||
@ -126,32 +121,6 @@ public class DynmapPlugin {
|
||||
|
||||
public static DynmapBlockState[] stateByID;
|
||||
|
||||
private Map<String, LongOpenHashSet> knownloadedchunks = new HashMap<String, LongOpenHashSet>();
|
||||
|
||||
private void addKnownChunk(FabricWorld fw, ChunkPos pos) {
|
||||
LongOpenHashSet cset = knownloadedchunks.get(fw.getName());
|
||||
if (cset == null) {
|
||||
cset = new LongOpenHashSet();
|
||||
knownloadedchunks.put(fw.getName(), cset);
|
||||
}
|
||||
cset.add(pos.toLong());
|
||||
}
|
||||
|
||||
private void removeKnownChunk(FabricWorld fw, ChunkPos pos) {
|
||||
LongOpenHashSet cset = knownloadedchunks.get(fw.getName());
|
||||
if (cset != null) {
|
||||
cset.remove(pos.toLong());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkIfKnownChunk(FabricWorld fw, ChunkPos pos) {
|
||||
LongOpenHashSet cset = knownloadedchunks.get(fw.getName());
|
||||
if (cset != null) {
|
||||
return cset.contains(pos.toLong());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize block states (org.dynmap.blockstate.DynmapBlockState)
|
||||
*/
|
||||
@ -658,69 +627,25 @@ public class DynmapPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
public void handleChunkLoad(ServerWorld world, WorldChunk chunk) {
|
||||
public void handleChunkGenerate(ServerWorld world, Chunk chunk) {
|
||||
if (!onchunkgenerate) return;
|
||||
|
||||
if ((chunk != null) && (chunk.getStatus() == ChunkStatus.FULL)) {
|
||||
FabricWorld fw = getWorld(world, false);
|
||||
if (fw != null) {
|
||||
addKnownChunk(fw, chunk.getPos());
|
||||
FabricWorld fw = getWorld(world, false);
|
||||
ChunkPos chunkPos = chunk.getPos();
|
||||
|
||||
int yMax = 0;
|
||||
ChunkSection[] sections = chunk.getSectionArray();
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
if ((sections[i] != null) && (!sections[i].isEmpty())) {
|
||||
yMax = 16 * (i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleChunkUnload(ServerWorld world, WorldChunk chunk) {
|
||||
if (!onchunkgenerate) return;
|
||||
|
||||
if ((chunk != null) && (chunk.getStatus() == ChunkStatus.FULL)) {
|
||||
FabricWorld fw = getWorld(world, false);
|
||||
ChunkPos cp = chunk.getPos();
|
||||
if (fw != null) {
|
||||
if (!checkIfKnownChunk(fw, cp)) {
|
||||
int ymax = 0;
|
||||
ChunkSection[] sections = chunk.getSectionArray();
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
if ((sections[i] != null) && (!sections[i].isEmpty())) {
|
||||
ymax = 16 * (i + 1);
|
||||
}
|
||||
}
|
||||
int x = cp.x << 4;
|
||||
int z = cp.z << 4;
|
||||
// If not empty AND not initial scan
|
||||
if (ymax > 0) {
|
||||
Log.info("New generated chunk detected at " + cp + " for " + fw.getName());
|
||||
mapManager.touchVolume(fw.getName(), x, 0, z, x + 15, ymax, z + 16, "chunkgenerate");
|
||||
}
|
||||
}
|
||||
removeKnownChunk(fw, cp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleChunkDataSave(ServerWorld world, Chunk chunk) {
|
||||
if (!onchunkgenerate) return;
|
||||
|
||||
if ((chunk != null) && (chunk.getStatus() == ChunkStatus.FULL)) {
|
||||
FabricWorld fw = getWorld(world, false);
|
||||
ChunkPos cp = chunk.getPos();
|
||||
if (fw != null) {
|
||||
if (!checkIfKnownChunk(fw, cp)) {
|
||||
int ymax = 0;
|
||||
ChunkSection[] sections = chunk.getSectionArray();
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
if ((sections[i] != null) && (!sections[i].isEmpty())) {
|
||||
ymax = 16 * (i + 1);
|
||||
}
|
||||
}
|
||||
int x = cp.x << 4;
|
||||
int z = cp.z << 4;
|
||||
// If not empty AND not initial scan
|
||||
if (ymax > 0) {
|
||||
mapManager.touchVolume(fw.getName(), x, 0, z, x + 15, ymax, z + 16, "chunkgenerate");
|
||||
}
|
||||
addKnownChunk(fw, cp);
|
||||
}
|
||||
}
|
||||
if (yMax > 0) {
|
||||
mapManager.touchVolume(fw.getName(),
|
||||
chunkPos.getStartX(), 0, chunkPos.getStartZ(),
|
||||
chunkPos.getEndX(), yMax, chunkPos.getEndZ(),
|
||||
"chunkgenerate");
|
||||
//Log.info("New generated chunk detected at %s[%s]".formatted(fw.getName(), chunkPos.getStartPos()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -755,39 +680,17 @@ public class DynmapPlugin {
|
||||
onblockchange_with_id = core.isTrigger("blockupdate-with-id");
|
||||
if (onblockchange_with_id)
|
||||
onblockchange = true;
|
||||
if ((worldTracker == null) && (onblockchange || onchunkpopulate || onchunkgenerate)) {
|
||||
if (worldTracker == null)
|
||||
worldTracker = new WorldTracker();
|
||||
ServerWorldEvents.LOAD.register((server, world) -> worldTracker.handleWorldLoad(server, world));
|
||||
ServerWorldEvents.UNLOAD.register((server, world) -> worldTracker.handleWorldUnload(server, world));
|
||||
ServerChunkEvents.CHUNK_LOAD.register((world, chunk) -> worldTracker.handleChunkLoad(world, chunk));
|
||||
ServerChunkEvents.CHUNK_UNLOAD.register((world, chunk) -> worldTracker.handleChunkUnload(world, chunk));
|
||||
ChunkDataEvents.SAVE.register((world, chunk) -> worldTracker.handleChunkDataSave(world, chunk));
|
||||
if (onchunkpopulate || onchunkgenerate) {
|
||||
CustomServerChunkEvents.CHUNK_GENERATE.register((world, chunk) -> worldTracker.handleChunkGenerate(world, chunk));
|
||||
}
|
||||
if (onblockchange) {
|
||||
BlockEvents.BLOCK_EVENT.register((world, pos) -> worldTracker.handleBlockEvent(world, pos));
|
||||
}
|
||||
// Prime the known full chunks
|
||||
if (onchunkgenerate && (server.getWorlds() != null)) {
|
||||
for (ServerWorld world : server.getWorlds()) {
|
||||
FabricWorld fw = getWorld(world);
|
||||
if (fw == null) continue;
|
||||
ServerChunkManager chunkManager = world.getChunkManager();
|
||||
Long2ObjectLinkedOpenHashMap<ChunkHolder> chunks = ((ThreadedAnvilChunkStorageAccessor) chunkManager.threadedAnvilChunkStorage).getChunkHolders();
|
||||
for (Map.Entry<Long, ChunkHolder> k : chunks.long2ObjectEntrySet()) {
|
||||
ChunkHolder ch = k.getValue();
|
||||
Chunk c = null;
|
||||
try {
|
||||
c = ch.getSavingFuture().getNow(null);
|
||||
} catch (Exception x) {
|
||||
}
|
||||
if (c == null) continue;
|
||||
ChunkStatus cs = c.getStatus();
|
||||
ChunkPos pos = ch.getPos();
|
||||
if (cs == ChunkStatus.FULL) { // Cooked?
|
||||
// Add it as known
|
||||
addKnownChunk(fw, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ServerWorldEvents.LOAD.register((server, world) -> worldTracker.handleWorldLoad(server, world));
|
||||
ServerWorldEvents.UNLOAD.register((server, world) -> worldTracker.handleWorldUnload(server, world));
|
||||
}
|
||||
|
||||
FabricWorld getWorldByName(String name) {
|
||||
@ -890,5 +793,4 @@ public class DynmapPlugin {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package org.dynmap.fabric_1_18.access;
|
||||
|
||||
public interface ProtoChunkAccessor {
|
||||
boolean getTouchedByWorldGen();
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
package org.dynmap.fabric_1_18.event;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
public class ChunkDataEvents {
|
||||
private ChunkDataEvents() {
|
||||
}
|
||||
|
||||
public static Event<Save> SAVE = EventFactory.createArrayBacked(Save.class,
|
||||
(listeners) -> (world, chunk) -> {
|
||||
for (Save callback : listeners) {
|
||||
callback.onSave(world, chunk);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Save {
|
||||
void onSave(ServerWorld world, Chunk chunk);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package org.dynmap.fabric_1_18.event;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
public class CustomServerChunkEvents {
|
||||
public static Event<ChunkGenerate> CHUNK_GENERATE = EventFactory.createArrayBacked(ChunkGenerate.class,
|
||||
(listeners) -> (world, chunk) -> {
|
||||
for (ChunkGenerate callback : listeners) {
|
||||
callback.onChunkGenerate(world, chunk);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ChunkGenerate {
|
||||
void onChunkGenerate(ServerWorld world, Chunk chunk);
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package org.dynmap.fabric_1_18.mixin;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.ProtoChunk;
|
||||
import org.dynmap.fabric_1_18.access.ProtoChunkAccessor;
|
||||
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;
|
||||
|
||||
@Mixin(ProtoChunk.class)
|
||||
public class ProtoChunkMixin implements ProtoChunkAccessor {
|
||||
private boolean touchedByWorldGen = false;
|
||||
|
||||
@Inject(
|
||||
method = "setBlockState",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/chunk/ChunkSection;setBlockState(IIILnet/minecraft/block/BlockState;)Lnet/minecraft/block/BlockState;"
|
||||
)
|
||||
)
|
||||
public void setBlockState(BlockPos pos, BlockState state, boolean moved, CallbackInfoReturnable<BlockState> info) {
|
||||
touchedByWorldGen = true;
|
||||
}
|
||||
|
||||
public boolean getTouchedByWorldGen() {
|
||||
return touchedByWorldGen;
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
package org.dynmap.fabric_1_18.mixin;
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
||||
import net.minecraft.server.world.ChunkHolder;
|
||||
import net.minecraft.server.world.ThreadedAnvilChunkStorage;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(ThreadedAnvilChunkStorage.class)
|
||||
public interface ThreadedAnvilChunkStorageAccessor {
|
||||
@Accessor
|
||||
Long2ObjectLinkedOpenHashMap<ChunkHolder> getChunkHolders();
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
package org.dynmap.fabric_1_18.mixin;
|
||||
|
||||
import net.minecraft.server.world.ChunkHolder;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.server.world.ThreadedAnvilChunkStorage;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import org.dynmap.fabric_1_18.event.ChunkDataEvents;
|
||||
import org.dynmap.fabric_1_18.access.ProtoChunkAccessor;
|
||||
import org.dynmap.fabric_1_18.event.CustomServerChunkEvents;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
@ -11,16 +13,20 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(ThreadedAnvilChunkStorage.class)
|
||||
@Mixin(value = ThreadedAnvilChunkStorage.class, priority = 666 /* fire before Fabric API CHUNK_LOAD event */)
|
||||
public abstract class ThreadedAnvilChunkStorageMixin {
|
||||
@Shadow
|
||||
@Final
|
||||
private ServerWorld world;
|
||||
@Shadow
|
||||
ServerWorld world;
|
||||
|
||||
@Inject(method = "save(Lnet/minecraft/world/chunk/Chunk;)Z", at = @At("RETURN"))
|
||||
private void save(Chunk chunk, CallbackInfoReturnable<Boolean> info) {
|
||||
if (info.getReturnValueZ()) {
|
||||
ChunkDataEvents.SAVE.invoker().onSave(this.world, chunk);
|
||||
@Inject(
|
||||
/* Same place as fabric-lifecycle-events-v1 event CHUNK_LOAD (we will fire before it) */
|
||||
method = "method_17227",
|
||||
at = @At("TAIL")
|
||||
)
|
||||
private void onChunkGenerate(ChunkHolder chunkHolder, Chunk protoChunk, CallbackInfoReturnable<Chunk> callbackInfoReturnable) {
|
||||
if (((ProtoChunkAccessor)protoChunk).getTouchedByWorldGen()) {
|
||||
CustomServerChunkEvents.CHUNK_GENERATE.invoker().onChunkGenerate(this.world, callbackInfoReturnable.getReturnValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -301,8 +301,6 @@ compass-mode: newnorth
|
||||
render-triggers:
|
||||
- blockupdate
|
||||
#- blockupdate-with-id
|
||||
#- lightingupdate
|
||||
- chunkpopulate
|
||||
- chunkgenerate
|
||||
#- none
|
||||
|
||||
|
@ -7,9 +7,9 @@
|
||||
"BiomeEffectsAccessor",
|
||||
"MinecraftServerMixin",
|
||||
"PlayerManagerMixin",
|
||||
"ProtoChunkMixin",
|
||||
"ServerPlayerEntityMixin",
|
||||
"ServerPlayNetworkHandlerMixin",
|
||||
"ThreadedAnvilChunkStorageAccessor",
|
||||
"ThreadedAnvilChunkStorageMixin",
|
||||
"WorldChunkMixin"
|
||||
],
|
||||
|
Loading…
Reference in New Issue
Block a user