added chunk_loaded event and fixed handling these events on 1.17
This commit is contained in:
1 parent
7a3ad7f0b8
commit
b1b7956ea9
5 files changed
+82
-20
No files matched your search
@@ -70,10 +70,17 @@ Duplicate of `tick`, just automatically located in the nether. Use `__on_tick()
|
||||
### `__on_tick_ender()` (Deprecated)
|
||||
Duplicate of `tick`, just automatically located in the end. Use `__on_tick() -> in_dimension('end', ... ` instead.
|
||||
|
||||
### `__on_chunk_generated(x,z)`
|
||||
### `__on_chunk_generated(x, z)`
|
||||
Called right after a chunk at a given coordinate is full generated. `x` and `z` correspond
|
||||
to the lowest x and z coords in the chunk. Event may (or may not) work with Optifine installed
|
||||
at the same time.
|
||||
to the lowest x and z coords in the chunk. Handling of this event is scheduled as an off-tick task happening after the
|
||||
chunk is confirmed to be generated and loaded to the game, so
|
||||
handling of this event is not technically guaranteed, if the game crashes while players are moving for example, and can
|
||||
be missed on the next start, if the game successfully saves it and fails to execute all remaining tasks. In normal operation
|
||||
this should not happen, but be warned.
|
||||
|
||||
### `__on_chunk_loaded(x, z)`
|
||||
Called right after a chunk at a given coordinate is loaded. All newly generated chunks are loaded as well.
|
||||
`x` and `z` correspond to the lowest x and z coordinates in the chunk.
|
||||
|
||||
### `__on_lightning(block, mode)`
|
||||
Triggered right after a lightning strikes. Lightning entity as well as potential horseman trap would
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
__command() ->
|
||||
__config() ->
|
||||
__on_chunk_generated(x, z) ->
|
||||
__on_chunk_loaded(x, z) ->
|
||||
__on_close() ->
|
||||
__on_player_attacks_entity(player, entity) ->
|
||||
__on_player_breaks_block(player, block) ->
|
||||
|
||||
@@ -100,6 +100,7 @@
|
||||
__command
|
||||
__config
|
||||
__on_chunk_generated
|
||||
__on_chunk_loaded
|
||||
__on_close
|
||||
__on_player_attacks_entity
|
||||
__on_player_breaks_block
|
||||
|
||||
+55
-12
@@ -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) { }
|
||||
|
||||
Reference in new issue
Block a user