Merge branch 'master' into 1.17
This commit is contained in:
commit
092766b820
5 files changed
+83
-21
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)
|
### `__on_tick_ender()` (Deprecated)
|
||||||
Duplicate of `tick`, just automatically located in the end. Use `__on_tick() -> in_dimension('end', ... ` instead.
|
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
|
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
|
to the lowest x and z coords in the chunk. Handling of this event is scheduled as an off-tick task happening after the
|
||||||
at the same time.
|
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)`
|
### `__on_lightning(block, mode)`
|
||||||
Triggered right after a lightning strikes. Lightning entity as well as potential horseman trap would
|
Triggered right after a lightning strikes. Lightning entity as well as potential horseman trap would
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
__command() ->
|
__command() ->
|
||||||
__config() ->
|
__config() ->
|
||||||
__on_chunk_generated(x, z) ->
|
__on_chunk_generated(x, z) ->
|
||||||
|
__on_chunk_loaded(x, z) ->
|
||||||
__on_close() ->
|
__on_close() ->
|
||||||
__on_player_attacks_entity(player, entity) ->
|
__on_player_attacks_entity(player, entity) ->
|
||||||
__on_player_breaks_block(player, block) ->
|
__on_player_breaks_block(player, block) ->
|
||||||
@@ -34,7 +35,7 @@ __on_player_wakes_up(player) ->
|
|||||||
__on_player_escapes_sleep(player) ->
|
__on_player_escapes_sleep(player) ->
|
||||||
__on_statistic(player, category, event, value) ->
|
__on_statistic(player, category, event, value) ->
|
||||||
__on_start() ->
|
__on_start() ->
|
||||||
__on_tick() ->
|
__on_tick() ->
|
||||||
__on_tick_ender() ->
|
__on_tick_ender() ->
|
||||||
__on_tick_nether() ->
|
__on_tick_nether() ->
|
||||||
__on_player_takes_damage(player, amount, source, source_entity) ->
|
__on_player_takes_damage(player, amount, source, source_entity) ->
|
||||||
|
|||||||
@@ -100,6 +100,7 @@
|
|||||||
__command
|
__command
|
||||||
__config
|
__config
|
||||||
__on_chunk_generated
|
__on_chunk_generated
|
||||||
|
__on_chunk_loaded
|
||||||
__on_close
|
__on_close
|
||||||
__on_player_attacks_entity
|
__on_player_attacks_entity
|
||||||
__on_player_breaks_block
|
__on_player_breaks_block
|
||||||
|
|||||||
+55
-12
@@ -12,6 +12,8 @@ import java.util.concurrent.Future;
|
|||||||
import java.util.function.IntFunction;
|
import java.util.function.IntFunction;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.ServerTask;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
@@ -50,6 +52,7 @@ import net.minecraft.world.chunk.WorldChunk;
|
|||||||
import net.minecraft.world.storage.RegionFile;
|
import net.minecraft.world.storage.RegionFile;
|
||||||
|
|
||||||
import static carpet.script.CarpetEventServer.Event.CHUNK_GENERATED;
|
import static carpet.script.CarpetEventServer.Event.CHUNK_GENERATED;
|
||||||
|
import static carpet.script.CarpetEventServer.Event.CHUNK_LOADED;
|
||||||
|
|
||||||
@Mixin(ThreadedAnvilChunkStorage.class)
|
@Mixin(ThreadedAnvilChunkStorage.class)
|
||||||
public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implements ThreadedAnvilChunkStorageInterface
|
public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implements ThreadedAnvilChunkStorageInterface
|
||||||
@@ -98,22 +101,62 @@ public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implem
|
|||||||
@Shadow
|
@Shadow
|
||||||
protected abstract Iterable<ChunkHolder> entryIterator();
|
protected abstract Iterable<ChunkHolder> entryIterator();
|
||||||
|
|
||||||
//in method_20617
|
|
||||||
//method_19534(Lnet/minecraft/server/world/ChunkHolder;Lnet/minecraft/world/chunk/Chunk;)Ljava/util/concurrent/CompletableFuture;
|
ThreadLocal<Boolean> generated = ThreadLocal.withInitial(() -> null);
|
||||||
// incmopatibility with optifine makes this mixin fail.
|
|
||||||
// lambda for convertToFullChunk
|
// in convertToFullChunk
|
||||||
|
// fancier version of the one below, ensuring that the event is triggered when the chunk is actually loaded.
|
||||||
@SuppressWarnings("UnresolvedMixinReference")
|
@SuppressWarnings("UnresolvedMixinReference")
|
||||||
@Inject(method = "method_19534", require = 0, at = @At(
|
@Inject(method = "method_20460", at = @At("HEAD"))
|
||||||
value = "INVOKE",
|
private void onChunkGeneratedStart(ChunkHolder chunkHolder, Either<Chunk, Unloaded> chunk, CallbackInfoReturnable<CompletableFuture<Either<Chunk, Unloaded>>> cir)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
if (CHUNK_GENERATED.isNeeded())
|
if (CHUNK_GENERATED.isNeeded() || CHUNK_LOADED.isNeeded())
|
||||||
this.world.getServer().execute(() -> CHUNK_GENERATED.onChunkGenerated(this.world, chunk));
|
{
|
||||||
|
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
|
@Unique
|
||||||
private void addTicket(final ChunkPos pos, final ChunkStatus status)
|
private void addTicket(final ChunkPos pos, final ChunkStatus status)
|
||||||
{ // UNKNOWN
|
{ // UNKNOWN
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ import net.minecraft.util.registry.RegistryKey;
|
|||||||
import net.minecraft.village.Merchant;
|
import net.minecraft.village.Merchant;
|
||||||
import net.minecraft.village.TradeOffer;
|
import net.minecraft.village.TradeOffer;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.chunk.Chunk;
|
|
||||||
import net.minecraft.world.explosion.Explosion;
|
import net.minecraft.world.explosion.Explosion;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
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)
|
public static final Event CHUNK_GENERATED = new Event("chunk_generated", 2, true)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void onChunkGenerated(ServerWorld world, Chunk chunk)
|
public void onChunkEvent(ServerWorld world, ChunkPos chPos, boolean generated)
|
||||||
{
|
{
|
||||||
handler.call( () ->
|
handler.call( () ->
|
||||||
{
|
{
|
||||||
ChunkPos pos = chunk.getPos();
|
return Arrays.asList(new NumericValue(chPos.x << 4), new NumericValue(chPos.z << 4));
|
||||||
return Arrays.asList(new NumericValue(pos.x << 4), new NumericValue(pos.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)
|
}, () -> CarpetServer.minecraft_server.getCommandSource().withWorld(world)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1054,7 +1064,7 @@ public class CarpetEventServer
|
|||||||
public boolean deprecated() {return false;}
|
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
|
//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 onTick() { }
|
||||||
public void onChunkGenerated(ServerWorld world, Chunk chunk) { }
|
public void onChunkEvent(ServerWorld world, ChunkPos chPos, boolean generated) { }
|
||||||
public void onPlayerEvent(ServerPlayerEntity player) { }
|
public void onPlayerEvent(ServerPlayerEntity player) { }
|
||||||
public void onPlayerMessage(ServerPlayerEntity player, String message) { }
|
public void onPlayerMessage(ServerPlayerEntity player, String message) { }
|
||||||
public void onPlayerStatistic(ServerPlayerEntity player, Stat<?> stat, int amount) { }
|
public void onPlayerStatistic(ServerPlayerEntity player, Stat<?> stat, int amount) { }
|
||||||
|
|||||||
Reference in new issue
Block a user