diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index e73d99ad..9882a423 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -2268,7 +2268,13 @@ It returns a `map` with a report indicating how many chunks were affected, and h * `layer_count_`: number of chunks for which a `` generation step has been performed * `layer_time_`: cumulative time for all chunks spent on generating `` step -# Iterating over larger areas of blocks +### add_chunk_ticket(pos, type, radius) + +Adds a chunk ticket at a position, which makes the game to keep the designated area centered around +`pos` with radius of `radius` loaded for a predefined amount of ticks, defined by `type`. Allowed types +are `portal`: 300 ticks, `teleport`: 5 ticks, and `unknown`: 1 tick. Radius can be from 1 to 32 ticks. + +This function is tentative - will likely change when chunk ticket API is properly fleshed out.# Iterating over larger areas of blocks These functions help scan larger areas of blocks without using generic loop functions, like nested `loop`. @@ -2993,7 +2999,7 @@ __on_tick() // can access blocks and entities in the overworld __on_tick_nether() // can access blocks and entities in the nether __on_tick_ender() // can access blocks and entities in the end __on_chunk_generated(x,z) // called after a chunk is promoted to the full chunk, - // prodiving lowest x and z coords in the chunk + // providing lowest x and z coords in the chunk // event will not work with optifine installed in the game __on_lightning(block, mode) // mode is `true` if lightning caused horse trap to spawn // player specific callbacks @@ -3011,6 +3017,7 @@ __on_player_takes_damage(player, amount, source, source_entity) __on_player_deals_damage(player, amount, entity) __on_player_dies(player) __on_player_respawns(player) +__on_player_changes_dimension(player, from_pos, from_dimension, to_pos, to_dimension) __on_player_rides(player, forward, strafe, jumping, sneaking) __on_player_jumps(player) __on_player_deploys_elytra(player) @@ -3024,6 +3031,11 @@ __on_player_drops_stack(player) __on_statistic(player, category, event, value) // player statistic changes +Couple special cases. +* `__on_player_changes_dimension` returns `null` as `to_pos` when player goes back to the overworld from the end +, since the respawn location of the player is not control by the teleport, or a player can see the end credits. After + the player is eligible to respawn in the overworld, `__on_player_respawns` will be triggered. + ### `/script event` command used to display current events and bounded functions. use `add_to` ro register new event, or `remove_from` to diff --git a/docs/scarpet/api/Events.md b/docs/scarpet/api/Events.md index 6408ac94..39992450 100644 --- a/docs/scarpet/api/Events.md +++ b/docs/scarpet/api/Events.md @@ -19,7 +19,7 @@ __on_tick() // can access blocks and entities in the overworld __on_tick_nether() // can access blocks and entities in the nether __on_tick_ender() // can access blocks and entities in the end __on_chunk_generated(x,z) // called after a chunk is promoted to the full chunk, - // prodiving lowest x and z coords in the chunk + // providing lowest x and z coords in the chunk // event will not work with optifine installed in the game __on_lightning(block, mode) // mode is `true` if lightning caused horse trap to spawn // player specific callbacks @@ -37,6 +37,7 @@ __on_player_takes_damage(player, amount, source, source_entity) __on_player_deals_damage(player, amount, entity) __on_player_dies(player) __on_player_respawns(player) +__on_player_changes_dimension(player, from_pos, from_dimension, to_pos, to_dimension) __on_player_rides(player, forward, strafe, jumping, sneaking) __on_player_jumps(player) __on_player_deploys_elytra(player) @@ -50,6 +51,11 @@ __on_player_drops_stack(player) __on_statistic(player, category, event, value) // player statistic changes +Couple special cases. +* `__on_player_changes_dimension` returns `null` as `to_pos` when player goes back to the overworld from the end +, since the respawn location of the player is not control by the teleport, or a player can see the end credits. After + the player is eligible to respawn in the overworld, `__on_player_respawns` will be triggered. + ### `/script event` command used to display current events and bounded functions. use `add_to` ro register new event, or `remove_from` to diff --git a/docs/scarpet/resources/editors/idea/4.txt b/docs/scarpet/resources/editors/idea/4.txt index 6200e26c..4799c846 100644 --- a/docs/scarpet/resources/editors/idea/4.txt +++ b/docs/scarpet/resources/editors/idea/4.txt @@ -5,6 +5,7 @@ __on_close __on_player_attacks_entity __on_player_breaks_block __on_player_clicks_block +__on_player_changes_dimension __on_player_deploys_elytra __on_player_drops_item __on_player_drops_stack diff --git a/docs/scarpet/resources/editors/npp/scarpet.xml b/docs/scarpet/resources/editors/npp/scarpet.xml index da7e1bf4..c17b3811 100644 --- a/docs/scarpet/resources/editors/npp/scarpet.xml +++ b/docs/scarpet/resources/editors/npp/scarpet.xml @@ -84,6 +84,7 @@ __on_player_attacks_entity __on_player_breaks_block __on_player_clicks_block + __on_player_changes_dimension __on_player_deploys_elytra __on_player_drops_item __on_player_drops_stack diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index 1eebc327..9b837791 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -64,7 +64,19 @@ public class DrawCommand then(argument("height",IntegerArgumentType.integer(1)). then(argument("pointing",StringArgumentType.word()).suggests( (c, b) -> suggestMatching(new String[]{"up","down"},b)). then(argument("orientation",StringArgumentType.word()).suggests( (c, b) -> suggestMatching(new String[]{"y","x","z"},b)) - .then(drawShape(c -> DrawCommand.drawPyramid(c, "circle", true))))))))); + .then(drawShape(c -> DrawCommand.drawPyramid(c, "circle", true))))))))). + then(literal("cylinder"). + then(argument("center", BlockPosArgumentType.blockPos()). + then(argument("radius", IntegerArgumentType.integer(1)). + then(argument("height",IntegerArgumentType.integer(1)). + then(argument("orientation",StringArgumentType.word()).suggests( (c, b) -> suggestMatching(new String[]{"y","x","z"},b)) + .then(drawShape(c -> DrawCommand.drawPrism(c, "circle")))))))). + then(literal("cuboid"). + then(argument("center", BlockPosArgumentType.blockPos()). + then(argument("radius", IntegerArgumentType.integer(1)). + then(argument("height",IntegerArgumentType.integer(1)). + then(argument("orientation",StringArgumentType.word()).suggests( (c, b) -> suggestMatching(new String[]{"y","x","z"},b)) + .then(drawShape(c -> DrawCommand.drawPrism(c, "square")))))))); dispatcher.register(command); } @@ -389,4 +401,55 @@ public class DrawCommand return affected; } + + private static int drawPrism(CommandContext ctx, String base){ + BlockPos pos; + double radius; + int height; + String orientation; + BlockStateArgument block; + Predicate replacement; + try + { + pos = getArg(ctx, BlockPosArgumentType::getBlockPos, "center"); + radius = getArg(ctx, IntegerArgumentType::getInteger, "radius")+0.5D; + height = getArg(ctx, IntegerArgumentType::getInteger, "height"); + orientation = getArg(ctx, StringArgumentType::getString,"orientation"); + block = getArg(ctx, BlockStateArgumentType::getBlockState, "block"); + replacement = getArg(ctx, BlockPredicateArgumentType::getBlockPredicate, "filter", true); + } + catch (ErrorHandled | CommandSyntaxException ignored) { return 0; } + + ServerCommandSource source = ctx.getSource(); + + int affected = 0; + BlockPos.Mutable mbpos = new BlockPos.Mutable(pos); + + List list = Lists.newArrayList(); + + ServerWorld world = source.getWorld(); + + CarpetSettings.impendingFillSkipUpdates = !CarpetSettings.fillUpdates; + + boolean isSquare = base.equalsIgnoreCase("square"); + + for(int i =0; i cir) + { + previousLocation = getPos(); + previousDimension = dimension; + } + + @Inject(method = "changeDimension", at = @At("RETURN")) + private void atChangeDimension(DimensionType newDimension, CallbackInfoReturnable cir) + { + if (PLAYER_CHANGES_DIMENSION.isNeeded()) + { + ServerPlayerEntity player = (ServerPlayerEntity) (Object)this; + Vec3d to = null; + if (!notInAnyWorld || previousDimension != DimensionType.THE_END || newDimension != DimensionType.OVERWORLD) + { + to = getPos(); + } + PLAYER_CHANGES_DIMENSION.onDimensionChange(player, previousLocation, to, previousDimension, newDimension); + } + } + } diff --git a/src/main/java/carpet/script/CarpetEventServer.java b/src/main/java/carpet/script/CarpetEventServer.java index 447396c0..10ca5210 100644 --- a/src/main/java/carpet/script/CarpetEventServer.java +++ b/src/main/java/carpet/script/CarpetEventServer.java @@ -527,6 +527,26 @@ public class CarpetEventServer handler.call( () -> Collections.singletonList(((c, t) -> new EntityValue(player))), player::getCommandSource); } }, + PLAYER_CHANGES_DIMENSION("player_changes_dimension", 5, false) + { + @Override + public void onDimensionChange(ServerPlayerEntity player, Vec3d from, Vec3d to, DimensionType fromDim, DimensionType dimTo) + { + // eligibility already checked in mixin + Value fromValue = ListValue.fromTriple(from.x, from.y, from.z); + Value toValue = (to == null)?Value.NULL:ListValue.fromTriple(to.x, to.y, to.z); + Value fromDimStr = new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.DIMENSION_TYPE.getId(fromDim))); + Value toDimStr = new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.DIMENSION_TYPE.getId(dimTo))); + + handler.call( () -> Arrays.asList( + ((c, t) -> new EntityValue(player)), + ((c, t) -> fromValue), + ((c, t) -> fromDimStr), + ((c, t) -> toValue), + ((c, t) -> toDimStr) + ), player::getCommandSource); + } + }, STATISTICS("statistic", 4, false) { private Identifier getStatId(Stat stat) @@ -599,8 +619,10 @@ public class CarpetEventServer public void onBlockBroken(ServerPlayerEntity player, BlockPos pos, BlockState previousBS) { } public void onBlockPlaced(ServerPlayerEntity player, BlockPos pos, Hand enumhand, ItemStack itemstack) { } public void onEntityAction(ServerPlayerEntity player, Entity entity, Hand enumhand) { } + public void onDimensionChange(ServerPlayerEntity player, Vec3d from, Vec3d to, DimensionType fromDim, DimensionType dimTo) {} public void onDamage(Entity target, float amount, DamageSource source) { } + public void onWorldEvent(ServerWorld world, BlockPos pos) { } public void onWorldEventFlag(ServerWorld world, BlockPos pos, int flag) { } } diff --git a/src/main/resources/assets/carpet/scripts/event_test.sc b/src/main/resources/assets/carpet/scripts/event_test.sc index 8e3d937a..036a0e38 100644 --- a/src/main/resources/assets/carpet/scripts/event_test.sc +++ b/src/main/resources/assets/carpet/scripts/event_test.sc @@ -220,3 +220,13 @@ __on_player_respawns(player) -> print('__on_player_respawns(player)'); print('Player '+player+' respawns.') ); + +__on_player_changes_dimension(player, from_pos, from_dimension, to_pos, to_dimension) -> +( + print(''); + print('__on_player_changes_dimension(player, from_pos, from_dimension, to_pos, to_dimension)'); + print('player changes dimensions:'); + print(' - player: '+player); + print(' - from '+from_dimension+' at '+map(from_pos, str('%.2f',_))); + print(' - to '+to_dimension+if(to_pos == null, '', ' at '+map(to_pos, str('%.2f',_)))); +)