diff --git a/docs/scarpet/Documentation.md b/docs/scarpet/Documentation.md index 8c57678c..99556222 100644 --- a/docs/scarpet/Documentation.md +++ b/docs/scarpet/Documentation.md @@ -32,6 +32,8 @@ [Events](/docs/scarpet/api/Events.md) +[Scoreboard manipulation](docs/scarpet/api/Scoreboard.md) + [Auxiliary Functions](/docs/scarpet/api/Auxiliary.md) [`/script` Command](/docs/scarpet/api/ScriptCommand.md) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index b816685d..3a04f299 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -1874,61 +1874,6 @@ top('motion', x, y, z) => 63 top('ocean_floor', x, y, z) => 41 -### `loaded(pos)` - -Boolean function, true if the block is accessible for the game mechanics. Normally `scarpet` doesn't check if operates -on loaded area - the game will automatically load missing blocks. We see this as advantage. Vanilla `fill/clone` -commands only check the specified corners for loadness. - -To check if block is truly loaded, I mean in memory, use `generation_status(x) != null`, as chunks can still be loaded -outside of the playable area, just are not used any of the game mechanics processes. - -
-loaded(pos(players()))  => 1
-loaded(100000,100,1000000)  => 0
-
- -### `(Deprecated) loaded_ep(pos)` - -Boolean function, true if the block is loaded and entity processing, as per 1.13.2 - -Deprecated as of scarpet 1.6, use `loaded_status(x) > 0`, or just `loaded(x)` with the same effect - -### `loaded_status(pos)` - -Returns loaded status as per new 1.14 chunk ticket system, 0 for inaccessible, 1 for border chunk, 2 for ticking, -3 for entity ticking - -### `generation_status(pos), generation_status(pos, true)` - -Returns generation status as per new 1.14 chunk ticket system. Can return any value from several available but chunks -can only be valid in a few states: `full`, `features`, `liquid_carvers`, and `structure_starts`. Returns `null` -if the chunk is not in memory unless called with optional `true`. - -### `structures(pos), structures(pos, structure_name)` - -Returns structure information for a given block position. Note that structure information is the same for all the -blocks from the same chunk. `structures` function can be called with a block, or a block and a structure name. In -the first case it returns a map of structures at a given position, keyed by structure name, with values indicating -the bounding box of the structure - a pair of two 3-value coords (see examples). When called with an extra structure -name, returns list of components for that structure, with their name, direction and two sets of coordinates -indicating the bounding box of the structure piece. - -### `structure_references(pos), structure_references(pos, structure_name)` - -Returns structure information that a chunk with a given block position is part of. `structure_references` function -can be called with a block, or a block and a structure name. In the first case it returns a list of structure names -that give chunk belongs to. When called with an extra structure name, returns list of positions pointing to the -lowest block position in chunks that hold structure starts for these structures. You can query that chunk structures -then to get its bounding boxes. - -### `set_structure(pos, structure_name), set_structure(pos, structure_name, null)` - -Creates or removes structure information of a structure associated with a chunk of `pos`. Unlike `plop`, blocks are -not placed in the world, only structure information is set. For the game this is a fully functional structure even -if blocks are not set. To remove structure a given point is in, use `structure_references` to find where current -structure starts. - ### `suffocates(pos)` Boolean function, true if the block causes suffocation. @@ -2064,6 +2009,190 @@ Returns the map colour of a block at position. One of: * `green_terracotta` * `red_terracotta` * `black_terracotta` + + +### `loaded(pos)` + +Boolean function, true if the block is accessible for the game mechanics. Normally `scarpet` doesn't check if operates +on loaded area - the game will automatically load missing blocks. We see this as advantage. Vanilla `fill/clone` +commands only check the specified corners for loadness. + +To check if block is truly loaded, I mean in memory, use `generation_status(x) != null`, as chunks can still be loaded +outside of the playable area, just are not used any of the game mechanics processes. + +
+loaded(pos(players()))  => 1
+loaded(100000,100,1000000)  => 0
+
+ +### `(Deprecated) loaded_ep(pos)` + +Boolean function, true if the block is loaded and entity processing, as per 1.13.2 + +Deprecated as of scarpet 1.6, use `loaded_status(x) > 0`, or just `loaded(x)` with the same effect + +### `loaded_status(pos)` + +Returns loaded status as per new 1.14 chunk ticket system, 0 for inaccessible, 1 for border chunk, 2 for ticking, +3 for entity ticking + +### `is_chunk_generated(pos)`, `is_chunk_generated(pos, force)` + +Returns `true` if the region file for the chunk exists, +`false` otherwise. If optional force is `true` it will also check if the chunk has a non-empty entry in its region file +Can be used to assess if the chunk has been touched by the game or not. + +`generation_status(pos, false)` only works on currently loaded chunks, and `generation_status(pos, true)` will create +an empty loaded chunk, even if it is not needed, so `is_chunk_generated` can be used as a efficient proxy to determine +if the chunk physically exists. + +Running `is_chunk_generated` is has no effects on the world, but since it is an external file operation, it is +considerably more expensive (unless area is loaded) than other generation and loaded checks. + +### `generation_status(pos), generation_status(pos, true)` + +Returns generation status as per the ticket system. Can return any value from several available but chunks +can only be stable in a few states: `full`, `features`, `liquid_carvers`, and `structure_starts`. Returns `null` +if the chunk is not in memory unless called with optional `true`. + +### `structures(pos), structures(pos, structure_name)` + +Returns structure information for a given block position. Note that structure information is the same for all the +blocks from the same chunk. `structures` function can be called with a block, or a block and a structure name. In +the first case it returns a map of structures at a given position, keyed by structure name, with values indicating +the bounding box of the structure - a pair of two 3-value coords (see examples). When called with an extra structure +name, returns list of components for that structure, with their name, direction and two sets of coordinates +indicating the bounding box of the structure piece. + +### `structure_references(pos), structure_references(pos, structure_name)` + +Returns structure information that a chunk with a given block position is part of. `structure_references` function +can be called with a block, or a block and a structure name. In the first case it returns a list of structure names +that give chunk belongs to. When called with an extra structure name, returns list of positions pointing to the +lowest block position in chunks that hold structure starts for these structures. You can query that chunk structures +then to get its bounding boxes. + +### `set_structure(pos, structure_name), set_structure(pos, structure_name, null)` + +Creates or removes structure information of a structure associated with a chunk of `pos`. Unlike `plop`, blocks are +not placed in the world, only structure information is set. For the game this is a fully functional structure even +if blocks are not set. To remove structure a given point is in, use `structure_references` to find where current +structure starts. + +### `plop(pos, what)` + +Plops a structure or a feature at a given `pos`, so block, triple position coordinates or a list of coordinates. +To `what` gets plopped and exactly where it often depends on the feature or structure itself. For example, all +structures are chunk aligned, and often span multiple chunks. Repeated calls to plop a structure in the same chunk +would result either in the same structure generated on top of each other, or with different state, but same position. +Most structures generate at specific altitudes, which are hardcoded, or with certain blocks around them. API will +cancel all extra position / biome / random requirements for structure / feature placement, but some hardcoded +limitations may still cause some of structures/features not to place. Some features require special blocks to be +present, like coral -> water or ice spikes -> snow block, and for some features, like fossils, placement is all sorts +of messed up. This can be partially avoided for structures by setting their structure information via `set_structure`, +which sets it without looking into world blocks, and then use `plop` to fill it with blocks. This may, or may not work. + +All generated structures will retain their properties, like mob spawning, however in many cases the world / dimension +itself has certain rules to spawn mobs, like plopping a nether fortress in the overworld will not spawn nether mobs, +because nether mobs can spawn only in the nether, but plopped in the nether - will behave like a valid nether fortress. + +`plop` will not use world random number generator to generate structures and features, but its own. This has a benefit +that they will generate properly randomly, not the same time every time. + +Structure list: + +* `monument`: Ocean Monument. Generates at fixed Y coordinate, surrounds itself with water. +* `fortress`: Nether Fortress. Altitude varies, but its bounded by the code. +* `mansion`: Woodland Mansion +* `jungle_temple`: Jungle Temple +* `desert_temple`: Desert Temple. Generates at fixed Y altitude. +* `end_city`: End City with Shulkers +* `igloo`: Igloo +* `shipwreck`: Shipwreck, version1? +* `shipwreck2`: Shipwreck, version2? +* `witch_hut` +* `ocean_ruin`, `ocean_ruin_small`, `ocean_ruin_tall`: Stone variants of ocean ruins. +* `ocean_ruin_warm`, `ocean_ruin_warm_small`, `ocean_ruin_warm_tall`: Sandstone variants of ocean ruins. +* `treasure`: A treasure chest. Yes, its a whole structure. +* `pillager_outpost`: A pillager outpost. +* `mineshaft`: A mineshaft. +* `mineshaft_mesa`: A Mesa (Badlands) version of a mineshaft. +* `village`: Plains, oak village. +* `village_desert`: Desert, sandstone village. +* `village_savanna`: Savanna, acacia village. +* `village_taiga`: Taiga, spruce village. +* `village_snowy`: Resolute, Canada. + +Feature list: + +* `oak` +* `oak_beehive`: oak with a hive (1.15+). +* `oak_large`: oak with branches. +* `oak_large_beehive`: oak with branches and a beehive (1.15+). +* `birch` +* `birch_large`: tall variant of birch tree. +* `shrub`: low bushes that grow in jungles. +* `shrub_acacia`: low bush but configured with acacia (1.14 only) +* `shrub_snowy`: low bush with white blocks (1.14 only) +* `jungle`: a tree +* `jungle_large`: 2x2 jungle tree +* `spruce` +* `spruce_large`: 2x2 spruce tree +* `pine`: spruce with minimal leafage (1.15+) +* `pine_large`: 2x2 spruce with minimal leafage (1.15+) +* `spruce_matchstick`: see 1.15 pine (1.14 only). +* `spruce_matchstick_large`: see 1.15 pine_large (1.14 only). +* `dark_oak` +* `acacia` +* `oak_swamp`: oak with more leaves and vines. +* `well`: desert well +* `grass`: a few spots of tall grass +* `grass_jungle`: little bushier grass feature (1.14 only) +* `lush_grass`: grass with patchy ferns (1.15+) +* `tall_grass`: 2-high grass patch (1.15+) +* `fern`: a few random 2-high ferns +* `cactus`: random cacti +* `dead_bush`: a few random dead bushi +* `fossils`: underground fossils, placement little wonky +* `mushroom_brown`: large brown mushroom. +* `mushroom_red`: large red mushroom. +* `ice_spike`: ice spike. Require snow block below to place. +* `glowstone`: glowstone cluster. Required netherrack above it. +* `melon`: a patch of melons +* `melon_pile`: a pile of melons (1.15+) +* `pumpkin`: a patch of pumpkins +* `pumpkin_pile`: a pile of pumpkins (1.15+) +* `sugarcane` +* `lilypad` +* `dungeon`: Dungeon. These are hard to place, and fail often. +* `iceberg`: Iceberg. Generate at sea level. +* `iceberg_blue`: Blue ice iceberg. +* `lake` +* `lava_lake` +* `end_island` +* `chorus`: Chorus plant. Require endstone to place. +* `sea_grass`: a patch of sea grass. Require water. +* `sea_grass_river`: a variant. +* `kelp` +* `coral_tree, coral_mushroom, coral_claw`: various coral types, random color. +* `coral`: random coral structure. Require water to spawn. +* `sea_pickle` +* `boulder`: A rocky, mossy formation from a giant taiga biome. Doesn't update client properly, needs relogging. + +### `reset_chunk(pos)`, `reset_chunk(from_pos, to_pos)`, `reset_chunk(l(pos, ...))` +Removes and resets the chunk, all chunks in the specified area or all chunks in a list at once, removing all previous +blocks and entities, and replacing it with a new generation. For all currently loaded chunks, they will be brought +to their current generation status, and updated to the player. All chunks that are not in the loaded area, will only +be generated to the `'structure_starts'` status, allowing to generate them fully as players are visiting them. +Chunks in the area that has not been touched yet by the game will not be generated / regenerated. + +It returns a `map` with a report indicating how many chunks were affected, and how long each step took: + * `requested_chunks`: total number of chunks in the requested area or list + * `affected_chunks`: number of chunks that will be removed / regenerated + * `loaded_chunks`: number of currently loaded chunks in the requested area / list + * `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 These functions help scan larger areas of blocks without using generic loop functions, like nested `loop`. @@ -2781,9 +2910,9 @@ scoreboard_add('lvl','level') Removes an objective. Returns `true` if objective has existed and has been removed. -### `scoreboard_display(objective, place)` +### `scoreboard_display(place, objective)` -sets display location for a specified `objective`. If `place` is `null`, then display is cleared. +sets display location for a specified `objective`. If `objective` is `null`, then display is cleared. # Auxiliary aspects Collection of other methods that control smaller, yet still important aspects of the game @@ -2929,108 +3058,7 @@ For the options of `entry`, consult your statistics page, or give it a guess. The call will return `null` if the statistics options are incorrect, or player didn't get these in their history. If the player encountered the statistic, or game created for him empty one, it will return a number. Scarpet will not affect the entries of the statistics, even if it is just creating empty ones. With `null` response -it could either mean your input is wrong, or statistic has effectively a value of `0`. - -### `plop(pos, what)` - -Plops a structure or a feature at a given `pos`, so block, triple position coordinates or a list of coordinates. -To `what` gets plopped and exactly where it often depends on the feature or structure itself. For example, all -structures are chunk aligned, and often span multiple chunks. Repeated calls to plop a structure in the same chunk -would result either in the same structure generated on top of each other, or with different state, but same position. -Most structures generate at specific altitudes, which are hardcoded, or with certain blocks around them. API will -cancel all extra position / biome / random requirements for structure / feature placement, but some hardcoded -limitations may still cause some of structures/features not to place. Some features require special blocks to be -present, like coral -> water or ice spikes -> snow block, and for some features, like fossils, placement is all sorts -of messed up. This can be partially avoided for structures by setting their structure information via `set_structure`, -which sets it without looking into world blocks, and then use `plop` to fill it with blocks. This may, or may not work. - -All generated structures will retain their properties, like mob spawning, however in many cases the world / dimension -itself has certain rules to spawn mobs, like plopping a nether fortress in the overworld will not spawn nether mobs, -because nether mobs can spawn only in the nether, but plopped in the nether - will behave like a valid nether fortress. - -`plop` will not use world random number generator to generate structures and features, but its own. This has a benefit -that they will generate properly randomly, not the same time every time. - -Structure list: - -* `monument`: Ocean Monument. Generates at fixed Y coordinate, surrounds itself with water. -* `fortress`: Nether Fortress. Altitude varies, but its bounded by the code. -* `mansion`: Woodland Mansion -* `jungle_temple`: Jungle Temple -* `desert_temple`: Desert Temple. Generates at fixed Y altitude. -* `end_city`: End City with Shulkers -* `igloo`: Igloo -* `shipwreck`: Shipwreck, version1? -* `shipwreck2`: Shipwreck, version2? -* `witch_hut` -* `ocean_ruin`, `ocean_ruin_small`, `ocean_ruin_tall`: Stone variants of ocean ruins. -* `ocean_ruin_warm`, `ocean_ruin_warm_small`, `ocean_ruin_warm_tall`: Sandstone variants of ocean ruins. -* `treasure`: A treasure chest. Yes, its a whole structure. -* `pillager_outpost`: A pillager outpost. -* `mineshaft`: A mineshaft. -* `mineshaft_mesa`: A Mesa (Badlands) version of a mineshaft. -* `village`: Plains, oak village. -* `village_desert`: Desert, sandstone village. -* `village_savanna`: Savanna, acacia village. -* `village_taiga`: Taiga, spruce village. -* `village_snowy`: Resolute, Canada. - -Feature list: - -* `oak` -* `oak_beehive`: oak with a hive (1.15+). -* `oak_large`: oak with branches. -* `oak_large_beehive`: oak with branches and a beehive (1.15+). -* `birch` -* `birch_large`: tall variant of birch tree. -* `shrub`: low bushes that grow in jungles. -* `shrub_acacia`: low bush but configured with acacia (1.14 only) -* `shrub_snowy`: low bush with white blocks (1.14 only) -* `jungle`: a tree -* `jungle_large`: 2x2 jungle tree -* `spruce` -* `spruce_large`: 2x2 spruce tree -* `pine`: spruce with minimal leafage (1.15+) -* `pine_large`: 2x2 spruce with minimal leafage (1.15+) -* `spruce_matchstick`: see 1.15 pine (1.14 only). -* `spruce_matchstick_large`: see 1.15 pine_large (1.14 only). -* `dark_oak` -* `acacia` -* `oak_swamp`: oak with more leaves and vines. -* `well`: desert well -* `grass`: a few spots of tall grass -* `grass_jungle`: little bushier grass feature (1.14 only) -* `lush_grass`: grass with patchy ferns (1.15+) -* `tall_grass`: 2-high grass patch (1.15+) -* `fern`: a few random 2-high ferns -* `cactus`: random cacti -* `dead_bush`: a few random dead bushi -* `fossils`: underground fossils, placement little wonky -* `mushroom_brown`: large brown mushroom. -* `mushroom_red`: large red mushroom. -* `ice_spike`: ice spike. Require snow block below to place. -* `glowstone`: glowstone cluster. Required netherrack above it. -* `melon`: a patch of melons -* `melon_pile`: a pile of melons (1.15+) -* `pumpkin`: a patch of pumpkins -* `pumpkin_pile`: a pile of pumpkins (1.15+) -* `sugarcane` -* `lilypad` -* `dungeon`: Dungeon. These are hard to place, and fail often. -* `iceberg`: Iceberg. Generate at sea level. -* `iceberg_blue`: Blue ice iceberg. -* `lake` -* `lava_lake` -* `end_island` -* `chorus`: Chorus plant. Require endstone to place. -* `sea_grass`: a patch of sea grass. Require water. -* `sea_grass_river`: a variant. -* `kelp` -* `coral_tree, coral_mushroom, coral_claw`: various coral types, random color. -* `coral`: random coral structure. Require water to spawn. -* `sea_pickle` -* `boulder`: A rocky, mossy formation from a giant taiga biome. Doesn't update client properly, needs relogging. -# `/script run` command +it could either mean your input is wrong, or statistic has effectively a value of `0`.# `/script run` command Primary way to input commands. The command executes in the context, position, and dimension of the executing player, commandblock, etc... The command receives 4 variables, `x`, `y`, `z` and `p` indicating position and diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md index 3b152291..17b1d003 100644 --- a/docs/scarpet/api/Auxiliary.md +++ b/docs/scarpet/api/Auxiliary.md @@ -143,104 +143,4 @@ For the options of `entry`, consult your statistics page, or give it a guess. The call will return `null` if the statistics options are incorrect, or player didn't get these in their history. If the player encountered the statistic, or game created for him empty one, it will return a number. Scarpet will not affect the entries of the statistics, even if it is just creating empty ones. With `null` response -it could either mean your input is wrong, or statistic has effectively a value of `0`. - -### `plop(pos, what)` - -Plops a structure or a feature at a given `pos`, so block, triple position coordinates or a list of coordinates. -To `what` gets plopped and exactly where it often depends on the feature or structure itself. For example, all -structures are chunk aligned, and often span multiple chunks. Repeated calls to plop a structure in the same chunk -would result either in the same structure generated on top of each other, or with different state, but same position. -Most structures generate at specific altitudes, which are hardcoded, or with certain blocks around them. API will -cancel all extra position / biome / random requirements for structure / feature placement, but some hardcoded -limitations may still cause some of structures/features not to place. Some features require special blocks to be -present, like coral -> water or ice spikes -> snow block, and for some features, like fossils, placement is all sorts -of messed up. This can be partially avoided for structures by setting their structure information via `set_structure`, -which sets it without looking into world blocks, and then use `plop` to fill it with blocks. This may, or may not work. - -All generated structures will retain their properties, like mob spawning, however in many cases the world / dimension -itself has certain rules to spawn mobs, like plopping a nether fortress in the overworld will not spawn nether mobs, -because nether mobs can spawn only in the nether, but plopped in the nether - will behave like a valid nether fortress. - -`plop` will not use world random number generator to generate structures and features, but its own. This has a benefit -that they will generate properly randomly, not the same time every time. - -Structure list: - -* `monument`: Ocean Monument. Generates at fixed Y coordinate, surrounds itself with water. -* `fortress`: Nether Fortress. Altitude varies, but its bounded by the code. -* `mansion`: Woodland Mansion -* `jungle_temple`: Jungle Temple -* `desert_temple`: Desert Temple. Generates at fixed Y altitude. -* `end_city`: End City with Shulkers -* `igloo`: Igloo -* `shipwreck`: Shipwreck, version1? -* `shipwreck2`: Shipwreck, version2? -* `witch_hut` -* `ocean_ruin`, `ocean_ruin_small`, `ocean_ruin_tall`: Stone variants of ocean ruins. -* `ocean_ruin_warm`, `ocean_ruin_warm_small`, `ocean_ruin_warm_tall`: Sandstone variants of ocean ruins. -* `treasure`: A treasure chest. Yes, its a whole structure. -* `pillager_outpost`: A pillager outpost. -* `mineshaft`: A mineshaft. -* `mineshaft_mesa`: A Mesa (Badlands) version of a mineshaft. -* `village`: Plains, oak village. -* `village_desert`: Desert, sandstone village. -* `village_savanna`: Savanna, acacia village. -* `village_taiga`: Taiga, spruce village. -* `village_snowy`: Resolute, Canada. - -Feature list: - -* `oak` -* `oak_beehive`: oak with a hive (1.15+). -* `oak_large`: oak with branches. -* `oak_large_beehive`: oak with branches and a beehive (1.15+). -* `birch` -* `birch_large`: tall variant of birch tree. -* `shrub`: low bushes that grow in jungles. -* `shrub_acacia`: low bush but configured with acacia (1.14 only) -* `shrub_snowy`: low bush with white blocks (1.14 only) -* `jungle`: a tree -* `jungle_large`: 2x2 jungle tree -* `spruce` -* `spruce_large`: 2x2 spruce tree -* `pine`: spruce with minimal leafage (1.15+) -* `pine_large`: 2x2 spruce with minimal leafage (1.15+) -* `spruce_matchstick`: see 1.15 pine (1.14 only). -* `spruce_matchstick_large`: see 1.15 pine_large (1.14 only). -* `dark_oak` -* `acacia` -* `oak_swamp`: oak with more leaves and vines. -* `well`: desert well -* `grass`: a few spots of tall grass -* `grass_jungle`: little bushier grass feature (1.14 only) -* `lush_grass`: grass with patchy ferns (1.15+) -* `tall_grass`: 2-high grass patch (1.15+) -* `fern`: a few random 2-high ferns -* `cactus`: random cacti -* `dead_bush`: a few random dead bushi -* `fossils`: underground fossils, placement little wonky -* `mushroom_brown`: large brown mushroom. -* `mushroom_red`: large red mushroom. -* `ice_spike`: ice spike. Require snow block below to place. -* `glowstone`: glowstone cluster. Required netherrack above it. -* `melon`: a patch of melons -* `melon_pile`: a pile of melons (1.15+) -* `pumpkin`: a patch of pumpkins -* `pumpkin_pile`: a pile of pumpkins (1.15+) -* `sugarcane` -* `lilypad` -* `dungeon`: Dungeon. These are hard to place, and fail often. -* `iceberg`: Iceberg. Generate at sea level. -* `iceberg_blue`: Blue ice iceberg. -* `lake` -* `lava_lake` -* `end_island` -* `chorus`: Chorus plant. Require endstone to place. -* `sea_grass`: a patch of sea grass. Require water. -* `sea_grass_river`: a variant. -* `kelp` -* `coral_tree, coral_mushroom, coral_claw`: various coral types, random color. -* `coral`: random coral structure. Require water to spawn. -* `sea_pickle` -* `boulder`: A rocky, mossy formation from a giant taiga biome. Doesn't update client properly, needs relogging. +it could either mean your input is wrong, or statistic has effectively a value of `0`. \ No newline at end of file diff --git a/docs/scarpet/api/BlocksAndWorldAccess.md b/docs/scarpet/api/BlocksAndWorldAccess.md index 99b48fe7..7c31b2cd 100644 --- a/docs/scarpet/api/BlocksAndWorldAccess.md +++ b/docs/scarpet/api/BlocksAndWorldAccess.md @@ -338,61 +338,6 @@ top('motion', x, y, z) => 63 top('ocean_floor', x, y, z) => 41 -### `loaded(pos)` - -Boolean function, true if the block is accessible for the game mechanics. Normally `scarpet` doesn't check if operates -on loaded area - the game will automatically load missing blocks. We see this as advantage. Vanilla `fill/clone` -commands only check the specified corners for loadness. - -To check if block is truly loaded, I mean in memory, use `generation_status(x) != null`, as chunks can still be loaded -outside of the playable area, just are not used any of the game mechanics processes. - -
-loaded(pos(players()))  => 1
-loaded(100000,100,1000000)  => 0
-
- -### `(Deprecated) loaded_ep(pos)` - -Boolean function, true if the block is loaded and entity processing, as per 1.13.2 - -Deprecated as of scarpet 1.6, use `loaded_status(x) > 0`, or just `loaded(x)` with the same effect - -### `loaded_status(pos)` - -Returns loaded status as per new 1.14 chunk ticket system, 0 for inaccessible, 1 for border chunk, 2 for ticking, -3 for entity ticking - -### `generation_status(pos), generation_status(pos, true)` - -Returns generation status as per new 1.14 chunk ticket system. Can return any value from several available but chunks -can only be valid in a few states: `full`, `features`, `liquid_carvers`, and `structure_starts`. Returns `null` -if the chunk is not in memory unless called with optional `true`. - -### `structures(pos), structures(pos, structure_name)` - -Returns structure information for a given block position. Note that structure information is the same for all the -blocks from the same chunk. `structures` function can be called with a block, or a block and a structure name. In -the first case it returns a map of structures at a given position, keyed by structure name, with values indicating -the bounding box of the structure - a pair of two 3-value coords (see examples). When called with an extra structure -name, returns list of components for that structure, with their name, direction and two sets of coordinates -indicating the bounding box of the structure piece. - -### `structure_references(pos), structure_references(pos, structure_name)` - -Returns structure information that a chunk with a given block position is part of. `structure_references` function -can be called with a block, or a block and a structure name. In the first case it returns a list of structure names -that give chunk belongs to. When called with an extra structure name, returns list of positions pointing to the -lowest block position in chunks that hold structure starts for these structures. You can query that chunk structures -then to get its bounding boxes. - -### `set_structure(pos, structure_name), set_structure(pos, structure_name, null)` - -Creates or removes structure information of a structure associated with a chunk of `pos`. Unlike `plop`, blocks are -not placed in the world, only structure information is set. For the game this is a fully functional structure even -if blocks are not set. To remove structure a given point is in, use `structure_references` to find where current -structure starts. - ### `suffocates(pos)` Boolean function, true if the block causes suffocation. @@ -528,3 +473,187 @@ Returns the map colour of a block at position. One of: * `green_terracotta` * `red_terracotta` * `black_terracotta` + + +### `loaded(pos)` + +Boolean function, true if the block is accessible for the game mechanics. Normally `scarpet` doesn't check if operates +on loaded area - the game will automatically load missing blocks. We see this as advantage. Vanilla `fill/clone` +commands only check the specified corners for loadness. + +To check if block is truly loaded, I mean in memory, use `generation_status(x) != null`, as chunks can still be loaded +outside of the playable area, just are not used any of the game mechanics processes. + +
+loaded(pos(players()))  => 1
+loaded(100000,100,1000000)  => 0
+
+ +### `(Deprecated) loaded_ep(pos)` + +Boolean function, true if the block is loaded and entity processing, as per 1.13.2 + +Deprecated as of scarpet 1.6, use `loaded_status(x) > 0`, or just `loaded(x)` with the same effect + +### `loaded_status(pos)` + +Returns loaded status as per new 1.14 chunk ticket system, 0 for inaccessible, 1 for border chunk, 2 for ticking, +3 for entity ticking + +### `is_chunk_generated(pos)`, `is_chunk_generated(pos, force)` + +Returns `true` if the region file for the chunk exists, +`false` otherwise. If optional force is `true` it will also check if the chunk has a non-empty entry in its region file +Can be used to assess if the chunk has been touched by the game or not. + +`generation_status(pos, false)` only works on currently loaded chunks, and `generation_status(pos, true)` will create +an empty loaded chunk, even if it is not needed, so `is_chunk_generated` can be used as a efficient proxy to determine +if the chunk physically exists. + +Running `is_chunk_generated` is has no effects on the world, but since it is an external file operation, it is +considerably more expensive (unless area is loaded) than other generation and loaded checks. + +### `generation_status(pos), generation_status(pos, true)` + +Returns generation status as per the ticket system. Can return any value from several available but chunks +can only be stable in a few states: `full`, `features`, `liquid_carvers`, and `structure_starts`. Returns `null` +if the chunk is not in memory unless called with optional `true`. + +### `structures(pos), structures(pos, structure_name)` + +Returns structure information for a given block position. Note that structure information is the same for all the +blocks from the same chunk. `structures` function can be called with a block, or a block and a structure name. In +the first case it returns a map of structures at a given position, keyed by structure name, with values indicating +the bounding box of the structure - a pair of two 3-value coords (see examples). When called with an extra structure +name, returns list of components for that structure, with their name, direction and two sets of coordinates +indicating the bounding box of the structure piece. + +### `structure_references(pos), structure_references(pos, structure_name)` + +Returns structure information that a chunk with a given block position is part of. `structure_references` function +can be called with a block, or a block and a structure name. In the first case it returns a list of structure names +that give chunk belongs to. When called with an extra structure name, returns list of positions pointing to the +lowest block position in chunks that hold structure starts for these structures. You can query that chunk structures +then to get its bounding boxes. + +### `set_structure(pos, structure_name), set_structure(pos, structure_name, null)` + +Creates or removes structure information of a structure associated with a chunk of `pos`. Unlike `plop`, blocks are +not placed in the world, only structure information is set. For the game this is a fully functional structure even +if blocks are not set. To remove structure a given point is in, use `structure_references` to find where current +structure starts. + +### `plop(pos, what)` + +Plops a structure or a feature at a given `pos`, so block, triple position coordinates or a list of coordinates. +To `what` gets plopped and exactly where it often depends on the feature or structure itself. For example, all +structures are chunk aligned, and often span multiple chunks. Repeated calls to plop a structure in the same chunk +would result either in the same structure generated on top of each other, or with different state, but same position. +Most structures generate at specific altitudes, which are hardcoded, or with certain blocks around them. API will +cancel all extra position / biome / random requirements for structure / feature placement, but some hardcoded +limitations may still cause some of structures/features not to place. Some features require special blocks to be +present, like coral -> water or ice spikes -> snow block, and for some features, like fossils, placement is all sorts +of messed up. This can be partially avoided for structures by setting their structure information via `set_structure`, +which sets it without looking into world blocks, and then use `plop` to fill it with blocks. This may, or may not work. + +All generated structures will retain their properties, like mob spawning, however in many cases the world / dimension +itself has certain rules to spawn mobs, like plopping a nether fortress in the overworld will not spawn nether mobs, +because nether mobs can spawn only in the nether, but plopped in the nether - will behave like a valid nether fortress. + +`plop` will not use world random number generator to generate structures and features, but its own. This has a benefit +that they will generate properly randomly, not the same time every time. + +Structure list: + +* `monument`: Ocean Monument. Generates at fixed Y coordinate, surrounds itself with water. +* `fortress`: Nether Fortress. Altitude varies, but its bounded by the code. +* `mansion`: Woodland Mansion +* `jungle_temple`: Jungle Temple +* `desert_temple`: Desert Temple. Generates at fixed Y altitude. +* `end_city`: End City with Shulkers +* `igloo`: Igloo +* `shipwreck`: Shipwreck, version1? +* `shipwreck2`: Shipwreck, version2? +* `witch_hut` +* `ocean_ruin`, `ocean_ruin_small`, `ocean_ruin_tall`: Stone variants of ocean ruins. +* `ocean_ruin_warm`, `ocean_ruin_warm_small`, `ocean_ruin_warm_tall`: Sandstone variants of ocean ruins. +* `treasure`: A treasure chest. Yes, its a whole structure. +* `pillager_outpost`: A pillager outpost. +* `mineshaft`: A mineshaft. +* `mineshaft_mesa`: A Mesa (Badlands) version of a mineshaft. +* `village`: Plains, oak village. +* `village_desert`: Desert, sandstone village. +* `village_savanna`: Savanna, acacia village. +* `village_taiga`: Taiga, spruce village. +* `village_snowy`: Resolute, Canada. + +Feature list: + +* `oak` +* `oak_beehive`: oak with a hive (1.15+). +* `oak_large`: oak with branches. +* `oak_large_beehive`: oak with branches and a beehive (1.15+). +* `birch` +* `birch_large`: tall variant of birch tree. +* `shrub`: low bushes that grow in jungles. +* `shrub_acacia`: low bush but configured with acacia (1.14 only) +* `shrub_snowy`: low bush with white blocks (1.14 only) +* `jungle`: a tree +* `jungle_large`: 2x2 jungle tree +* `spruce` +* `spruce_large`: 2x2 spruce tree +* `pine`: spruce with minimal leafage (1.15+) +* `pine_large`: 2x2 spruce with minimal leafage (1.15+) +* `spruce_matchstick`: see 1.15 pine (1.14 only). +* `spruce_matchstick_large`: see 1.15 pine_large (1.14 only). +* `dark_oak` +* `acacia` +* `oak_swamp`: oak with more leaves and vines. +* `well`: desert well +* `grass`: a few spots of tall grass +* `grass_jungle`: little bushier grass feature (1.14 only) +* `lush_grass`: grass with patchy ferns (1.15+) +* `tall_grass`: 2-high grass patch (1.15+) +* `fern`: a few random 2-high ferns +* `cactus`: random cacti +* `dead_bush`: a few random dead bushi +* `fossils`: underground fossils, placement little wonky +* `mushroom_brown`: large brown mushroom. +* `mushroom_red`: large red mushroom. +* `ice_spike`: ice spike. Require snow block below to place. +* `glowstone`: glowstone cluster. Required netherrack above it. +* `melon`: a patch of melons +* `melon_pile`: a pile of melons (1.15+) +* `pumpkin`: a patch of pumpkins +* `pumpkin_pile`: a pile of pumpkins (1.15+) +* `sugarcane` +* `lilypad` +* `dungeon`: Dungeon. These are hard to place, and fail often. +* `iceberg`: Iceberg. Generate at sea level. +* `iceberg_blue`: Blue ice iceberg. +* `lake` +* `lava_lake` +* `end_island` +* `chorus`: Chorus plant. Require endstone to place. +* `sea_grass`: a patch of sea grass. Require water. +* `sea_grass_river`: a variant. +* `kelp` +* `coral_tree, coral_mushroom, coral_claw`: various coral types, random color. +* `coral`: random coral structure. Require water to spawn. +* `sea_pickle` +* `boulder`: A rocky, mossy formation from a giant taiga biome. Doesn't update client properly, needs relogging. + +### `reset_chunk(pos)`, `reset_chunk(from_pos, to_pos)`, `reset_chunk(l(pos, ...))` +Removes and resets the chunk, all chunks in the specified area or all chunks in a list at once, removing all previous +blocks and entities, and replacing it with a new generation. For all currently loaded chunks, they will be brought +to their current generation status, and updated to the player. All chunks that are not in the loaded area, will only +be generated to the `'structure_starts'` status, allowing to generate them fully as players are visiting them. +Chunks in the area that has not been touched yet by the game will not be generated / regenerated. + +It returns a `map` with a report indicating how many chunks were affected, and how long each step took: + * `requested_chunks`: total number of chunks in the requested area or list + * `affected_chunks`: number of chunks that will be removed / regenerated + * `loaded_chunks`: number of currently loaded chunks in the requested area / list + * `layer_count_`: number of chunks for which a `` generation step has been performed + * `layer_time_`: cumulative time for all chunks spent on generating `` step + diff --git a/docs/scarpet/api/Scoreboard.md b/docs/scarpet/api/Scoreboard.md index 5e64285b..a509bb15 100644 --- a/docs/scarpet/api/Scoreboard.md +++ b/docs/scarpet/api/Scoreboard.md @@ -21,6 +21,6 @@ scoreboard_add('lvl','level') Removes an objective. Returns `true` if objective has existed and has been removed. -### `scoreboard_display(objective, place)` +### `scoreboard_display(place, objective)` -sets display location for a specified `objective`. If `place` is `null`, then display is cleared. +sets display location for a specified `objective`. If `objective` is `null`, then display is cleared. diff --git a/src/main/java/carpet/fakes/ThreadedAnvilChunkStorageInterface.java b/src/main/java/carpet/fakes/ThreadedAnvilChunkStorageInterface.java index 08d070ad..d2fff722 100644 --- a/src/main/java/carpet/fakes/ThreadedAnvilChunkStorageInterface.java +++ b/src/main/java/carpet/fakes/ThreadedAnvilChunkStorageInterface.java @@ -3,8 +3,9 @@ package carpet.fakes; import net.minecraft.util.math.ChunkPos; import java.util.List; +import java.util.Map; public interface ThreadedAnvilChunkStorageInterface { - void regenerateChunkRegion(List requestedChunks); + Map regenerateChunkRegion(List requestedChunks); } diff --git a/src/main/java/carpet/mixins/ThreadedAnvilChunkStorage_scarpetChunkCreationMixin.java b/src/main/java/carpet/mixins/ThreadedAnvilChunkStorage_scarpetChunkCreationMixin.java index 27b4efdf..b391f7d4 100644 --- a/src/main/java/carpet/mixins/ThreadedAnvilChunkStorage_scarpetChunkCreationMixin.java +++ b/src/main/java/carpet/mixins/ThreadedAnvilChunkStorage_scarpetChunkCreationMixin.java @@ -1,8 +1,8 @@ package carpet.mixins; -import carpet.CarpetSettings; import carpet.fakes.ChunkHolderInterface; import carpet.fakes.ThreadedAnvilChunkStorageInterface; +import carpet.script.utils.WorldTools; import com.mojang.datafixers.util.Either; import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.longs.LongSet; @@ -13,11 +13,11 @@ import net.minecraft.server.world.ServerLightingProvider; import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ThreadedAnvilChunkStorage; import net.minecraft.util.math.ChunkPos; -import net.minecraft.util.thread.MessageListener; import net.minecraft.util.thread.ThreadExecutor; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.ChunkStatus; import net.minecraft.world.chunk.WorldChunk; +import net.minecraft.world.storage.RegionFile; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -85,9 +85,10 @@ public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implem } @Override - public void regenerateChunkRegion(List requestedChunks) + public Map regenerateChunkRegion(List requestedChunks) { - + Map report = new HashMap<>(); + report.put("requested_chunks",requestedChunks.size()); //flushning all tasks on the thread executor so all futures are ready - we don't want any deadlocks mainThreadExecutor.runTasks(() -> mainThreadExecutor.getTaskCount() == 0); // save all pending chunks @@ -104,20 +105,21 @@ public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implem if (chunk != null && chunk.getStatus() != ChunkStatus.EMPTY) loadedChunks.add(pos); } - CarpetSettings.LOG.error("Area has "+requestedChunks.size()+" chunks"); - CarpetSettings.LOG.error("Area has "+loadedChunks.size()+" loaded chunks"); + report.put("loaded_chunks", loadedChunks.size()); Map targetStatus = new HashMap<>(); + Map regionCache = new HashMap<>(); for (ChunkPos pos: requestedChunks) { - + if (!WorldTools.canHasChunk(world, pos, regionCache, true)) continue; Chunk chunk = world.getChunk(pos.x, pos.z, ChunkStatus.EMPTY, true); if (chunk == null || chunk.getStatus() == ChunkStatus.EMPTY) continue; //unloaded areas can have unknown skirt chunk area targetStatus.put(pos, loadedChunks.contains(pos)?chunk.getStatus():ChunkStatus.STRUCTURE_STARTS); } - CarpetSettings.LOG.error("Area has "+targetStatus.size()+" chunks for removal"); + regionCache.clear(); + report.put("affected_chunks", targetStatus.size()); for (ChunkPos chpos : targetStatus.keySet()) @@ -128,8 +130,7 @@ public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implem int currentLevel = ThreadedAnvilChunkStorage.MAX_LEVEL; if (chunkHolder != null) { - //CarpetSettings.LOG.error("current_level: "+chunkHolder.getLevel()); - currentLevel = chunkHolder.getLevel(); + currentLevel = chunkHolder.getLevel()-1; //method_20458(id, chunkHolder); // saving chunk // skipping entities etc Chunk chunk = null; try @@ -184,34 +185,25 @@ public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implem for (ChunkStatus status : ChunkStatus.createOrderedList()) { - CarpetSettings.LOG.error("Creating layer: " + status.getId() + " for "+targetStatus.size()+" chunks"); + report.put("layer_count_"+status.getId(),targetStatus.size()); + long start = System.currentTimeMillis(); if (status == ChunkStatus.LIGHT) { - //break; serverLightingProvider.setTaskBatchSize(targetStatus.size() + 20); } for (ChunkPos chpos : new ArrayList<>(targetStatus.keySet())) { if (targetStatus.get(chpos) == status) targetStatus.remove(chpos); - //if (status==ChunkStatus.LIGHT) - //{ - // serverLightingProvider.tick(); - //} - //CarpetSettings.LOG.error("Creating layer: " + status.getId()); world.getChunk(chpos.x, chpos.z, status); if (status == ChunkStatus.FULL) convertToFullChunk(currentChunkHolders.get(chpos.toLong())); - //CarpetSettings.LOG.error(" .. done"); - //if (status==ChunkStatus.LIGHT) - //{ - // serverLightingProvider.tick(); - //} } if (status == ChunkStatus.LIGHT) - { + { // default task batch size after initial generation is done serverLightingProvider.setTaskBatchSize(5); } + report.put("layer_time_"+status.getId(), (int) (System.currentTimeMillis()-start)); } mainThreadExecutor.runTasks(() -> mainThreadExecutor.getTaskCount() == 0); @@ -222,5 +214,6 @@ public abstract class ThreadedAnvilChunkStorage_scarpetChunkCreationMixin implem { runnable.run(); } + return report; } } diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 312c9624..b5132778 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -133,6 +133,7 @@ import java.util.function.BiFunction; import java.util.function.Predicate; import java.util.stream.Collectors; +import static carpet.script.utils.WorldTools.canHasChunk; import static java.lang.Math.abs; import static java.lang.Math.max; import static java.lang.Math.min; @@ -677,6 +678,17 @@ public class CarpetExpression return (c_, t_) -> retval; }); + this.expr.addLazyFunction("is_chunk_generated", -1, (c, t, lv) -> + { + BlockValue.LocatorResult locator = BlockValue.fromParams((CarpetContext)c, lv, 0); + BlockPos pos = locator.block.getPos(); + boolean force = false; + if (lv.size() > locator.offset) + force = lv.get(locator.offset).evalValue(c, Context.BOOLEAN).getBoolean(); + Value retval = new NumericValue(canHasChunk(((CarpetContext)c).s.getWorld(), new ChunkPos(pos), null, force)); + return (c_, t_) -> retval; + }); + this.expr.addLazyFunction("generation_status", -1, (c, t, lv) -> { BlockValue.LocatorResult locatorResult = BlockValue.fromParams((CarpetContext)c, lv, 0); @@ -1248,14 +1260,24 @@ public class CarpetExpression ServerWorld world = cc.s.getWorld(); + Value [] result = new Value[]{Value.NULL}; + ((CarpetContext)c).s.getMinecraftServer().submitAndJoin( () -> { - ((ThreadedAnvilChunkStorageInterface) world.getChunkManager().threadedAnvilChunkStorage).regenerateChunkRegion(requestedChunks); + Map report = ((ThreadedAnvilChunkStorageInterface) world.getChunkManager().threadedAnvilChunkStorage).regenerateChunkRegion(requestedChunks); for (ChunkPos chpos: requestedChunks) + { if (world.getChunk(chpos.x, chpos.z, ChunkStatus.FULL, false) != null) + { this.forceChunkUpdate(chpos.getCenterBlockPos(), world); + } + } + result[0] = MapValue.wrap(report.entrySet().stream().collect(Collectors.toMap( + e -> new StringValue((String)((Map.Entry) e).getKey()), + e -> new NumericValue((Integer)((Map.Entry) e).getValue()) + ))); }); - return LazyValue.NULL; + return (_c, _t) -> result[0]; }); } diff --git a/src/main/java/carpet/script/utils/WorldTools.java b/src/main/java/carpet/script/utils/WorldTools.java new file mode 100644 index 00000000..d33120c5 --- /dev/null +++ b/src/main/java/carpet/script/utils/WorldTools.java @@ -0,0 +1,47 @@ +package carpet.script.utils; + +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.chunk.ChunkStatus; +import net.minecraft.world.storage.RegionFile; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Map; + +public class WorldTools +{ + + public static boolean canHasChunk(ServerWorld world, ChunkPos chpos, Map regionCache, boolean deepcheck) + { + if (world.getChunk(chpos.x, chpos.z, ChunkStatus.STRUCTURE_STARTS, false) != null) + return true; + String currentRegionName = "r." + chpos.getRegionX() + "." + chpos.getRegionZ() + ".mca"; + if (regionCache != null && regionCache.containsKey(currentRegionName)) + { + RegionFile region = regionCache.get(currentRegionName); + if (region == null) return false; + return region.hasChunk(chpos); + } + Path regionPath = world.getDimension().getType().getSaveDirectory( + world.getSaveHandler().getWorldDir() + ).toPath().resolve("region"); + Path regionFilePath = regionPath.resolve(currentRegionName); + File regionFile = regionFilePath.toFile(); + if (!regionFile.exists()) + { + if (regionCache != null) regionCache.put(currentRegionName, null); + return false; + } + if (!deepcheck) return true; // not using cache in this case. + try + { + RegionFile region = new RegionFile(regionFile, regionPath.toFile()); + if (regionCache != null) regionCache.put(currentRegionName, region); + return region.hasChunk(chpos); + } + catch (IOException ignored) { } + return true; + } +}