added chunk_loaded event and fixed handling these events on 1.17

This commit is contained in:
gnembon committed 2021-06-26 23:20:13 -03:00
1 parent 7a3ad7f0b8
commit b1b7956ea9
5 files changed
+83 -21

No files matched your search

@@ -12,6 +12,8 @@ import java.util.concurrent.Future;
import java.util.function.IntFunction;
import java.util.stream.Collectors;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.ServerTask;
import org.apache.commons.lang3.tuple.Pair;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
@@ -50,6 +52,7 @@ import net.minecraft.world.chunk.WorldChunk;
import net.minecraft.world.storage.RegionFile;
import static carpet.script.CarpetEventServer.Event.CHUNK_GENERATED;
import static carpet.script.CarpetEventServer.Event.CHUNK_LOADED;
@Mixin(ThreadedAnvilChunkStorage.class)
public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implements ThreadedAnvilChunkStorageInterface
@@ -98,22 +101,62 @@ public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implem
@Shadow
protected abstract Iterable<ChunkHolder> entryIterator();
//in method_20617
//method_19534(Lnet/minecraft/server/world/ChunkHolder;Lnet/minecraft/world/chunk/Chunk;)Ljava/util/concurrent/CompletableFuture;
// incmopatibility with optifine makes this mixin fail.
// lambda for convertToFullChunk
ThreadLocal<Boolean> generated = ThreadLocal.withInitial(() -> null);
// in convertToFullChunk
// fancier version of the one below, ensuring that the event is triggered when the chunk is actually loaded.
@SuppressWarnings("UnresolvedMixinReference")
@Inject(method = "method_19534", require = 0, at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/world/ThreadedAnvilChunkStorage;convertToFullChunk(Lnet/minecraft/server/world/ChunkHolder;)Ljava/util/concurrent/CompletableFuture;",
shift = At.Shift.AFTER
))
private void onChunkGenerated(final ChunkHolder chunkHolder, final Chunk chunk, final CallbackInfoReturnable<CompletableFuture> cir)
@Inject(method = "method_20460", at = @At("HEAD"))
private void onChunkGeneratedStart(ChunkHolder chunkHolder, Either<Chunk, Unloaded> chunk, CallbackInfoReturnable<CompletableFuture<Either<Chunk, Unloaded>>> cir)
{
if (CHUNK_GENERATED.isNeeded())
this.world.getServer().execute(() -> CHUNK_GENERATED.onChunkGenerated(this.world, chunk));
if (CHUNK_GENERATED.isNeeded() || CHUNK_LOADED.isNeeded())
{
generated.set(chunkHolder.getCurrentChunk().getStatus() != ChunkStatus.FULL);
}
else
{
generated.set(null);
}
}
@SuppressWarnings("UnresolvedMixinReference")
@Inject(method = "method_20460", at = @At("RETURN"))
private void onChunkGeneratedEnd(ChunkHolder chunkHolder, Either<Chunk, Unloaded> chunk, CallbackInfoReturnable<CompletableFuture<Either<Chunk, Unloaded>>> cir)
{
Boolean localGenerated= generated.get();
if (localGenerated != null)
{
MinecraftServer server = this.world.getServer();
int ticks = server.getTicks();
ChunkPos chpos = chunkHolder.getPos();
// need to send these because if an app does something with that event, it may lock the thread
// so better be safe and schedule it for later, aSaP
if (CHUNK_GENERATED.isNeeded() && localGenerated)
server.send(new ServerTask(ticks, () -> CHUNK_GENERATED.onChunkEvent(this.world, chpos, true)));
if (CHUNK_LOADED.isNeeded())
server.send(new ServerTask(ticks, () -> CHUNK_LOADED.onChunkEvent(this.world, chpos, localGenerated)));
}
}
/* simple but a version that doesn't guarantee that the chunk is actually loaded
@Inject(method = "convertToFullChunk", at = @At("HEAD"))
private void onChunkGeneratedEnd(ChunkHolder chunkHolder, CallbackInfoReturnable<CompletableFuture<Either<Chunk, Unloaded>>> cir)
{
if (CHUNK_GENERATED.isNeeded() && chunkHolder.getCurrentChunk().getStatus() != ChunkStatus.FULL)
{
ChunkPos chpos = chunkHolder.getPos();
this.world.getServer().execute(() -> CHUNK_GENERATED.onChunkEvent(this.world, chpos, true));
}
if (CHUNK_LOADED.isNeeded())
{
boolean generated = chunkHolder.getCurrentChunk().getStatus() != ChunkStatus.FULL;
ChunkPos chpos = chunkHolder.getPos();
this.world.getServer().execute(() -> CHUNK_LOADED.onChunkEvent(this.world, chpos, generated));
}
}
*/
@Unique
private void addTicket(final ChunkPos pos, final ChunkStatus status)
{ // UNKNOWN
@@ -45,7 +45,6 @@ import net.minecraft.util.registry.RegistryKey;
import net.minecraft.village.Merchant;
import net.minecraft.village.TradeOffer;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.explosion.Explosion;
import org.apache.commons.lang3.tuple.Pair;
@@ -417,12 +416,23 @@ public class CarpetEventServer
public static final Event CHUNK_GENERATED = new Event("chunk_generated", 2, true)
{
@Override
public void onChunkGenerated(ServerWorld world, Chunk chunk)
public void onChunkEvent(ServerWorld world, ChunkPos chPos, boolean generated)
{
handler.call( () ->
{
ChunkPos pos = chunk.getPos();
return Arrays.asList(new NumericValue(pos.x << 4), new NumericValue(pos.z << 4));
return Arrays.asList(new NumericValue(chPos.x << 4), new NumericValue(chPos.z << 4));
}, () -> CarpetServer.minecraft_server.getCommandSource().withWorld(world)
);
}
};
public static final Event CHUNK_LOADED = new Event("chunk_loaded", 2, true)
{
@Override
public void onChunkEvent(ServerWorld world, ChunkPos chPos, boolean generated)
{
handler.call( () ->
{
return Arrays.asList(new NumericValue(chPos.x << 4), new NumericValue(chPos.z << 4));
}, () -> CarpetServer.minecraft_server.getCommandSource().withWorld(world)
);
}
@@ -1050,7 +1060,7 @@ public class CarpetEventServer
public boolean deprecated() {return false;}
//stubs for calls just to ease calls in vanilla code so they don't need to deal with scarpet value types
public void onTick() { }
public void onChunkGenerated(ServerWorld world, Chunk chunk) { }
public void onChunkEvent(ServerWorld world, ChunkPos chPos, boolean generated) { }
public void onPlayerEvent(ServerPlayerEntity player) { }
public void onPlayerMessage(ServerPlayerEntity player, String message) { }
public void onPlayerStatistic(ServerPlayerEntity player, Stat<?> stat, int amount) { }