Merge branch 'master' into 1.17
This commit is contained in:
commit
ed4afa15ff
49 files changed
+593
-211
No files matched your search
+29
-18
@@ -7,7 +7,7 @@ sourceCompatibility = JavaVersion.VERSION_1_8
|
|||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
|
||||||
archivesBaseName = project.archives_base_name
|
archivesBaseName = project.archives_base_name
|
||||||
version = project.minecraft_version+'-'+project.mod_version
|
version = project.minecraft_version+'-'+project.mod_version+'+v'+new Date().format('yyMMdd')
|
||||||
group = project.maven_group
|
group = project.maven_group
|
||||||
|
|
||||||
minecraft {
|
minecraft {
|
||||||
@@ -15,7 +15,7 @@ minecraft {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
//to change the versions see the gradle.properties file
|
// To change the versions see the gradle.properties file
|
||||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
||||||
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
||||||
modCompile "net.fabricmc:fabric-loader:${project.loader_version}"
|
modCompile "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||||
@@ -32,7 +32,7 @@ processResources {
|
|||||||
|
|
||||||
from(sourceSets.main.resources.srcDirs) {
|
from(sourceSets.main.resources.srcDirs) {
|
||||||
include "fabric.mod.json"
|
include "fabric.mod.json"
|
||||||
expand "version": project.version
|
expand "version": project.mod_version
|
||||||
}
|
}
|
||||||
|
|
||||||
from(sourceSets.main.resources.srcDirs) {
|
from(sourceSets.main.resources.srcDirs) {
|
||||||
@@ -40,23 +40,34 @@ processResources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure that the encoding is set to UTF-8, no matter what the system default is
|
|
||||||
// this fixes some edge cases with special characters not displaying correctly
|
tasks.withType(JavaCompile).configureEach {
|
||||||
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
|
// ensure that the encoding is set to UTF-8, no matter what the system default is
|
||||||
tasks.withType(JavaCompile) {
|
// this fixes some edge cases with special characters not displaying correctly
|
||||||
options.encoding = "UTF-8"
|
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
|
||||||
|
// If Javadoc is generated, this must be specified in that task too.
|
||||||
|
it.options.encoding = "UTF-8"
|
||||||
|
|
||||||
|
// The Minecraft launcher currently installs Java 8 for users, so your mod probably wants to target Java 8 too
|
||||||
|
// JDK 9 introduced a new way of specifying this that will make sure no newer classes or methods are used.
|
||||||
|
// We'll use that if it's available, but otherwise we'll use the older option.
|
||||||
|
def targetVersion = 8
|
||||||
|
if (JavaVersion.current().isJava9Compatible()) {
|
||||||
|
it.options.release = targetVersion
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
|
java {
|
||||||
// if it is present.
|
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
|
||||||
// If you remove this task, sources will not be generated.
|
// if it is present.
|
||||||
task sourcesJar(type: Jar, dependsOn: classes) {
|
// If you remove this line, sources will not be generated.
|
||||||
classifier = "sources"
|
withSourcesJar()
|
||||||
from sourceSets.main.allSource
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
from "LICENSE"
|
from("LICENSE") {
|
||||||
|
rename { "${it}_${project.archivesBaseName}"}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// configure the maven publication
|
// configure the maven publication
|
||||||
@@ -73,10 +84,10 @@ publishing {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// select the repositories you want to publish to
|
// Select the repositories you want to publish to
|
||||||
|
// To publish to maven local, no extra repositories are necessary. Just use the task `publishToMavenLocal`.
|
||||||
repositories {
|
repositories {
|
||||||
// uncomment to publish to the local maven
|
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
|
||||||
// mavenLocal()
|
|
||||||
maven {
|
maven {
|
||||||
url "$projectDir/publish"
|
url "$projectDir/publish"
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-13
@@ -1665,14 +1665,21 @@ split('\\.','foo.bar') => [foo, bar]
|
|||||||
### `slice(expr, from, to?)`
|
### `slice(expr, from, to?)`
|
||||||
|
|
||||||
extracts a substring, or sublist (based on the type of the result of the expression under expr with
|
extracts a substring, or sublist (based on the type of the result of the expression under expr with
|
||||||
starting index of `from`, and ending at `to` if provided, or the end, if omitted
|
starting index of `from`, and ending at `to` if provided, or the end, if omitted. Can use negative indices to
|
||||||
|
indicate counting form the back of the list, so `-1 <=> length(_)`.
|
||||||
|
|
||||||
|
Special case is made for iterators (`range`, `rect` etc), which does require non-negative indices (negative `from` is treated as
|
||||||
|
`0`, and negative `to` as `inf`), but allows retrieving parts of the sequence and ignore
|
||||||
|
other parts. In that case consecutive calls to `slice` will refer to index `0` the current iteration position since iterators
|
||||||
|
cannot go back nor track where they are in the sequence (see examples).
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
slice(l(0,1,2,3,4,5), 1, 3) => [1, 2, 3]
|
slice([0,1,2,3,4,5], 1, 3) => [1, 2, 3]
|
||||||
slice('foobar', 0, 1) => 'f'
|
slice('foobar', 0, 1) => 'f'
|
||||||
slice('foobar', 3) => 'bar'
|
slice('foobar', 3) => 'bar'
|
||||||
slice(range(10), 3, 5) => [3, 4, 5]
|
slice(range(10), 3, 5) => [3, 4, 5]
|
||||||
slice(range(10), 5) => [5, 6, 7, 8, 9]
|
slice(range(10), 5) => [5, 6, 7, 8, 9]
|
||||||
|
r = range(100); [slice(r, 5, 7), slice(r, 1, 3)] => [[5, 6], [8, 9]]
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
### `sort(list), sort(values ...)`
|
### `sort(list), sort(values ...)`
|
||||||
@@ -2893,7 +2900,10 @@ In this case - entities would need to be re-fetched, or the code should account
|
|||||||
|
|
||||||
### `player(), player(type), player(name)`
|
### `player(), player(type), player(name)`
|
||||||
|
|
||||||
With no arguments, it returns the calling player or the player closest to the caller. Note that the main context
|
With no arguments, it returns the calling player or the player closest to the caller.
|
||||||
|
For player-scoped apps (which is a default) its always the owning player or `null` if it not present even if some code
|
||||||
|
still runs in their name.
|
||||||
|
Note that the main context
|
||||||
will receive `p` variable pointing to this player. With `type` or `name` specified, it will try first to match a type,
|
will receive `p` variable pointing to this player. With `type` or `name` specified, it will try first to match a type,
|
||||||
returning a list of players matching a type, and if this fails, will assume its player name query retuning player with
|
returning a list of players matching a type, and if this fails, will assume its player name query retuning player with
|
||||||
that name, or `null` if no player was found. With `'all'`, list of all players in the game, in all dimensions, so end
|
that name, or `null` if no player was found. With `'all'`, list of all players in the game, in all dimensions, so end
|
||||||
@@ -4109,8 +4119,10 @@ about players death and applying external effects (like mob anger etc).
|
|||||||
|
|
||||||
### `__on_player_respawns(player)`
|
### `__on_player_respawns(player)`
|
||||||
Triggered when a player respawns. This includes spawning after death, or landing in the overworld after leaving the end.
|
Triggered when a player respawns. This includes spawning after death, or landing in the overworld after leaving the end.
|
||||||
When the event is handled, a player is still in its previous location and dimension - will be repositioned right after.
|
When the event is handled, a player is still in its previous location and dimension - will be repositioned right after. In
|
||||||
|
case player died, its previous inventory as already been scattered, and its current inventory will not be copied to the respawned
|
||||||
|
entity, so any manipulation to player data is
|
||||||
|
best to be scheduled at the end of the tick, but you can still use its current reference to query its status as of the respawn event.
|
||||||
|
|
||||||
### `__on_player_changes_dimension(player, from_pos, from_dimension, to_pos, to_dimension)`
|
### `__on_player_changes_dimension(player, from_pos, from_dimension, to_pos, to_dimension)`
|
||||||
Called when a player moves from one dimension to another. Event is handled still when the player is in its previous
|
Called when a player moves from one dimension to another. Event is handled still when the player is in its previous
|
||||||
@@ -4299,8 +4311,9 @@ With specified `objective` and
|
|||||||
|
|
||||||
### `scoreboard_add(objective, criterion?)`
|
### `scoreboard_add(objective, criterion?)`
|
||||||
|
|
||||||
Adds a new objective to scoreboard. If `criterion` is not specified, assumes `'dummy'`. Returns `false` if objective
|
Adds a new objective to scoreboard. If `criterion` is not specified, assumes `'dummy'`.
|
||||||
already existed, `true` otherwise.
|
If the objective already exists, changes the criterion of that objective and returns `false`. If the criterion was not specified but the objective already exists, returns the current criterion.
|
||||||
|
If the objective was added, returns `true`. If nothing is affected, returns `null`
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
scoreboard_add('counter')
|
scoreboard_add('counter')
|
||||||
@@ -4451,7 +4464,6 @@ for(bossbar(),bossbar(_,'remove')) -> remove all bossbars
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Auxiliary aspects
|
# Auxiliary aspects
|
||||||
|
|
||||||
Collection of other methods that control smaller, yet still important aspects of the game
|
Collection of other methods that control smaller, yet still important aspects of the game
|
||||||
@@ -4759,12 +4771,15 @@ for folder listing.
|
|||||||
|
|
||||||
Supported values for resource `type` are:
|
Supported values for resource `type` are:
|
||||||
* `nbt` - NBT tag
|
* `nbt` - NBT tag
|
||||||
|
* `json` - JSON file
|
||||||
* `text` - text resource with automatic newlines added
|
* `text` - text resource with automatic newlines added
|
||||||
* `raw` - text resource without implied newlines
|
* `raw` - text resource without implied newlines
|
||||||
* `folder` - for `list_files` only - indicting folder listing instead of files
|
* `folder` - for `list_files` only - indicating folder listing instead of files
|
||||||
* `shared_nbt`, `shared_text`, `shared_raw`, `shared_folder` - shared versions of the above
|
* `shared_nbt`, `shared_text`, `shared_raw`, `shared_folder`, `shared_json` - shared versions of the above
|
||||||
|
|
||||||
NBT files have extension `.nbt`, store one NBT tag, and return a NBT type value. Text files have `.txt` extension,
|
NBT files have extension `.nbt`, store one NBT tag, and return a NBT type value. JSON files have `.json` extension, store
|
||||||
|
Scarpet numbers, strings, lists, maps and `null` values. Anything else will be saved as a string (including NBT).
|
||||||
|
Text files have `.txt` extension,
|
||||||
stores multiple lines of text and returns lists of all lines from the file. With `write_file`, multiple lines can be
|
stores multiple lines of text and returns lists of all lines from the file. With `write_file`, multiple lines can be
|
||||||
sent to the file at once. The only difference between `raw` and `text` types are automatic newlines added after each
|
sent to the file at once. The only difference between `raw` and `text` types are automatic newlines added after each
|
||||||
record to the file. Since files are closed after each write, sending multiple lines of data to
|
record to the file. Since files are closed after each write, sending multiple lines of data to
|
||||||
@@ -4942,7 +4957,7 @@ it could either mean your input is wrong, or statistic effectively has a value o
|
|||||||
### `system_info()`, `system_info(property)`
|
### `system_info()`, `system_info(property)`
|
||||||
Fetches the value of a system property or returns all inforation as a map when called without any arguments. It can be used to
|
Fetches the value of a system property or returns all inforation as a map when called without any arguments. It can be used to
|
||||||
fetch various information, mostly not changing, or only available via low level
|
fetch various information, mostly not changing, or only available via low level
|
||||||
system calls. In all cirumstances, these are only provided as read-only.
|
system calls. In all circumstances, these are only provided as read-only.
|
||||||
|
|
||||||
Available options in the scarpet app space:
|
Available options in the scarpet app space:
|
||||||
* `app_name` - current app name or `null` if its a default app
|
* `app_name` - current app name or `null` if its a default app
|
||||||
@@ -4960,7 +4975,7 @@ Available options in the scarpet app space:
|
|||||||
|
|
||||||
|
|
||||||
Relevant gameplay related properties
|
Relevant gameplay related properties
|
||||||
* `game_difficulty` - current difficulty of the game: `'peacefu'`, `'easy'`, `'normal'`, or `'hard'`
|
* `game_difficulty` - current difficulty of the game: `'peaceful'`, `'easy'`, `'normal'`, or `'hard'`
|
||||||
* `game_hardcore` - boolean whether the game is in hardcore mode
|
* `game_hardcore` - boolean whether the game is in hardcore mode
|
||||||
* `game_storage_format` - format of the world save files, either `'McRegion'` or `'Anvil'`
|
* `game_storage_format` - format of the world save files, either `'McRegion'` or `'Anvil'`
|
||||||
* `game_default_gamemode` - default gamemode for new players
|
* `game_default_gamemode` - default gamemode for new players
|
||||||
@@ -4968,6 +4983,7 @@ Available options in the scarpet app space:
|
|||||||
* `game_view_distance` - the view distance
|
* `game_view_distance` - the view distance
|
||||||
* `game_mod_name` - the name of the base mod. Expect `'fabric'`
|
* `game_mod_name` - the name of the base mod. Expect `'fabric'`
|
||||||
* `game_version` - base version of the game
|
* `game_version` - base version of the game
|
||||||
|
* `game_data_version` - data version of the game. Returns an integer, so it can be compared.
|
||||||
|
|
||||||
Server related properties
|
Server related properties
|
||||||
* `server_motd` - the motd of the server visible when joining
|
* `server_motd` - the motd of the server visible when joining
|
||||||
|
|||||||
@@ -305,12 +305,15 @@ for folder listing.
|
|||||||
|
|
||||||
Supported values for resource `type` are:
|
Supported values for resource `type` are:
|
||||||
* `nbt` - NBT tag
|
* `nbt` - NBT tag
|
||||||
|
* `json` - JSON file
|
||||||
* `text` - text resource with automatic newlines added
|
* `text` - text resource with automatic newlines added
|
||||||
* `raw` - text resource without implied newlines
|
* `raw` - text resource without implied newlines
|
||||||
* `folder` - for `list_files` only - indicting folder listing instead of files
|
* `folder` - for `list_files` only - indicating folder listing instead of files
|
||||||
* `shared_nbt`, `shared_text`, `shared_raw`, `shared_folder` - shared versions of the above
|
* `shared_nbt`, `shared_text`, `shared_raw`, `shared_folder`, `shared_json` - shared versions of the above
|
||||||
|
|
||||||
NBT files have extension `.nbt`, store one NBT tag, and return a NBT type value. Text files have `.txt` extension,
|
NBT files have extension `.nbt`, store one NBT tag, and return a NBT type value. JSON files have `.json` extension, store
|
||||||
|
Scarpet numbers, strings, lists, maps and `null` values. Anything else will be saved as a string (including NBT).
|
||||||
|
Text files have `.txt` extension,
|
||||||
stores multiple lines of text and returns lists of all lines from the file. With `write_file`, multiple lines can be
|
stores multiple lines of text and returns lists of all lines from the file. With `write_file`, multiple lines can be
|
||||||
sent to the file at once. The only difference between `raw` and `text` types are automatic newlines added after each
|
sent to the file at once. The only difference between `raw` and `text` types are automatic newlines added after each
|
||||||
record to the file. Since files are closed after each write, sending multiple lines of data to
|
record to the file. Since files are closed after each write, sending multiple lines of data to
|
||||||
@@ -488,7 +491,7 @@ it could either mean your input is wrong, or statistic effectively has a value o
|
|||||||
### `system_info()`, `system_info(property)`
|
### `system_info()`, `system_info(property)`
|
||||||
Fetches the value of a system property or returns all inforation as a map when called without any arguments. It can be used to
|
Fetches the value of a system property or returns all inforation as a map when called without any arguments. It can be used to
|
||||||
fetch various information, mostly not changing, or only available via low level
|
fetch various information, mostly not changing, or only available via low level
|
||||||
system calls. In all cirumstances, these are only provided as read-only.
|
system calls. In all circumstances, these are only provided as read-only.
|
||||||
|
|
||||||
Available options in the scarpet app space:
|
Available options in the scarpet app space:
|
||||||
* `app_name` - current app name or `null` if its a default app
|
* `app_name` - current app name or `null` if its a default app
|
||||||
@@ -506,7 +509,7 @@ Available options in the scarpet app space:
|
|||||||
|
|
||||||
|
|
||||||
Relevant gameplay related properties
|
Relevant gameplay related properties
|
||||||
* `game_difficulty` - current difficulty of the game: `'peacefu'`, `'easy'`, `'normal'`, or `'hard'`
|
* `game_difficulty` - current difficulty of the game: `'peaceful'`, `'easy'`, `'normal'`, or `'hard'`
|
||||||
* `game_hardcore` - boolean whether the game is in hardcore mode
|
* `game_hardcore` - boolean whether the game is in hardcore mode
|
||||||
* `game_storage_format` - format of the world save files, either `'McRegion'` or `'Anvil'`
|
* `game_storage_format` - format of the world save files, either `'McRegion'` or `'Anvil'`
|
||||||
* `game_default_gamemode` - default gamemode for new players
|
* `game_default_gamemode` - default gamemode for new players
|
||||||
@@ -514,6 +517,7 @@ Available options in the scarpet app space:
|
|||||||
* `game_view_distance` - the view distance
|
* `game_view_distance` - the view distance
|
||||||
* `game_mod_name` - the name of the base mod. Expect `'fabric'`
|
* `game_mod_name` - the name of the base mod. Expect `'fabric'`
|
||||||
* `game_version` - base version of the game
|
* `game_version` - base version of the game
|
||||||
|
* `game_data_version` - data version of the game. Returns an integer, so it can be compared.
|
||||||
|
|
||||||
Server related properties
|
Server related properties
|
||||||
* `server_motd` - the motd of the server visible when joining
|
* `server_motd` - the motd of the server visible when joining
|
||||||
|
|||||||
@@ -8,7 +8,10 @@ In this case - entities would need to be re-fetched, or the code should account
|
|||||||
|
|
||||||
### `player(), player(type), player(name)`
|
### `player(), player(type), player(name)`
|
||||||
|
|
||||||
With no arguments, it returns the calling player or the player closest to the caller. Note that the main context
|
With no arguments, it returns the calling player or the player closest to the caller.
|
||||||
|
For player-scoped apps (which is a default) its always the owning player or `null` if it not present even if some code
|
||||||
|
still runs in their name.
|
||||||
|
Note that the main context
|
||||||
will receive `p` variable pointing to this player. With `type` or `name` specified, it will try first to match a type,
|
will receive `p` variable pointing to this player. With `type` or `name` specified, it will try first to match a type,
|
||||||
returning a list of players matching a type, and if this fails, will assume its player name query retuning player with
|
returning a list of players matching a type, and if this fails, will assume its player name query retuning player with
|
||||||
that name, or `null` if no player was found. With `'all'`, list of all players in the game, in all dimensions, so end
|
that name, or `null` if no player was found. With `'all'`, list of all players in the game, in all dimensions, so end
|
||||||
@@ -243,6 +246,10 @@ Boolean, true if the entity is silent.
|
|||||||
|
|
||||||
Boolean, true if the entity is affected by gravity, like most entities are.
|
Boolean, true if the entity is affected by gravity, like most entities are.
|
||||||
|
|
||||||
|
### `query(e, 'invulnerable')`
|
||||||
|
|
||||||
|
Boolean, true if the entity is invulnerable.
|
||||||
|
|
||||||
### `query(e, 'immune_to_fire')`
|
### `query(e, 'immune_to_fire')`
|
||||||
|
|
||||||
Boolean, true if the entity is immune to fire.
|
Boolean, true if the entity is immune to fire.
|
||||||
@@ -723,6 +730,10 @@ Silences or unsilences the entity.
|
|||||||
|
|
||||||
Toggles gravity for the entity.
|
Toggles gravity for the entity.
|
||||||
|
|
||||||
|
### `modify(e, 'invulnerable', boolean)`
|
||||||
|
|
||||||
|
Toggles invulnerability for the entity.
|
||||||
|
|
||||||
### `modify(e, 'fire', ticks)`
|
### `modify(e, 'fire', ticks)`
|
||||||
|
|
||||||
Will set entity on fire for `ticks` ticks. Set to 0 to extinguish.
|
Will set entity on fire for `ticks` ticks. Set to 0 to extinguish.
|
||||||
|
|||||||
@@ -160,8 +160,10 @@ about players death and applying external effects (like mob anger etc).
|
|||||||
|
|
||||||
### `__on_player_respawns(player)`
|
### `__on_player_respawns(player)`
|
||||||
Triggered when a player respawns. This includes spawning after death, or landing in the overworld after leaving the end.
|
Triggered when a player respawns. This includes spawning after death, or landing in the overworld after leaving the end.
|
||||||
When the event is handled, a player is still in its previous location and dimension - will be repositioned right after.
|
When the event is handled, a player is still in its previous location and dimension - will be repositioned right after. In
|
||||||
|
case player died, its previous inventory as already been scattered, and its current inventory will not be copied to the respawned
|
||||||
|
entity, so any manipulation to player data is
|
||||||
|
best to be scheduled at the end of the tick, but you can still use its current reference to query its status as of the respawn event.
|
||||||
|
|
||||||
### `__on_player_changes_dimension(player, from_pos, from_dimension, to_pos, to_dimension)`
|
### `__on_player_changes_dimension(player, from_pos, from_dimension, to_pos, to_dimension)`
|
||||||
Called when a player moves from one dimension to another. Event is handled still when the player is in its previous
|
Called when a player moves from one dimension to another. Event is handled still when the player is in its previous
|
||||||
|
|||||||
@@ -10,8 +10,9 @@ With specified `objective` and
|
|||||||
|
|
||||||
### `scoreboard_add(objective, criterion?)`
|
### `scoreboard_add(objective, criterion?)`
|
||||||
|
|
||||||
Adds a new objective to scoreboard. If `criterion` is not specified, assumes `'dummy'`. Returns `false` if objective
|
Adds a new objective to scoreboard. If `criterion` is not specified, assumes `'dummy'`.
|
||||||
already existed, `true` otherwise.
|
If the objective already exists, changes the criterion of that objective and returns `false`. If the criterion was not specified but the objective already exists, returns the current criterion.
|
||||||
|
If the objective was added, returns `true`. If nothing is affected, returns `null`
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
scoreboard_add('counter')
|
scoreboard_add('counter')
|
||||||
@@ -162,4 +163,3 @@ for(bossbar(),bossbar(_,'remove')) -> remove all bossbars
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -170,14 +170,21 @@ split('\\.','foo.bar') => [foo, bar]
|
|||||||
### `slice(expr, from, to?)`
|
### `slice(expr, from, to?)`
|
||||||
|
|
||||||
extracts a substring, or sublist (based on the type of the result of the expression under expr with
|
extracts a substring, or sublist (based on the type of the result of the expression under expr with
|
||||||
starting index of `from`, and ending at `to` if provided, or the end, if omitted
|
starting index of `from`, and ending at `to` if provided, or the end, if omitted. Can use negative indices to
|
||||||
|
indicate counting form the back of the list, so `-1 <=> length(_)`.
|
||||||
|
|
||||||
|
Special case is made for iterators (`range`, `rect` etc), which does require non-negative indices (negative `from` is treated as
|
||||||
|
`0`, and negative `to` as `inf`), but allows retrieving parts of the sequence and ignore
|
||||||
|
other parts. In that case consecutive calls to `slice` will refer to index `0` the current iteration position since iterators
|
||||||
|
cannot go back nor track where they are in the sequence (see examples).
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
slice(l(0,1,2,3,4,5), 1, 3) => [1, 2, 3]
|
slice([0,1,2,3,4,5], 1, 3) => [1, 2, 3]
|
||||||
slice('foobar', 0, 1) => 'f'
|
slice('foobar', 0, 1) => 'f'
|
||||||
slice('foobar', 3) => 'bar'
|
slice('foobar', 3) => 'bar'
|
||||||
slice(range(10), 3, 5) => [3, 4, 5]
|
slice(range(10), 3, 5) => [3, 4, 5]
|
||||||
slice(range(10), 5) => [5, 6, 7, 8, 9]
|
slice(range(10), 5) => [5, 6, 7, 8, 9]
|
||||||
|
r = range(100); [slice(r, 5, 7), slice(r, 1, 3)] => [[5, 6], [8, 9]]
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
### `sort(list), sort(values ...)`
|
### `sort(list), sort(values ...)`
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@ org.gradle.jvmargs=-Xmx1G
|
|||||||
loader_version=0.10.8
|
loader_version=0.10.8
|
||||||
|
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version = 1.4.21+v201216
|
mod_version = 1.4.21
|
||||||
maven_group = carpet
|
maven_group = carpet
|
||||||
archives_base_name = fabric-carpet
|
archives_base_name = fabric-carpet
|
||||||
|
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
@@ -125,10 +125,11 @@ if $darwin; then
|
|||||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# For Cygwin, switch paths to Windows format before running java
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
if $cygwin ; then
|
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
|
||||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
# We build the pattern for arguments to be converted via cygpath
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
@@ -154,19 +155,19 @@ if $cygwin ; then
|
|||||||
else
|
else
|
||||||
eval `echo args$i`="\"$arg\""
|
eval `echo args$i`="\"$arg\""
|
||||||
fi
|
fi
|
||||||
i=$((i+1))
|
i=`expr $i + 1`
|
||||||
done
|
done
|
||||||
case $i in
|
case $i in
|
||||||
(0) set -- ;;
|
0) set -- ;;
|
||||||
(1) set -- "$args0" ;;
|
1) set -- "$args0" ;;
|
||||||
(2) set -- "$args0" "$args1" ;;
|
2) set -- "$args0" "$args1" ;;
|
||||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -175,14 +176,9 @@ save () {
|
|||||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
echo " "
|
echo " "
|
||||||
}
|
}
|
||||||
APP_ARGS=$(save "$@")
|
APP_ARGS=`save "$@"`
|
||||||
|
|
||||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
|
||||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
|
||||||
cd "$(dirname "$0")"
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec "$JAVACMD" "$@"
|
exec "$JAVACMD" "$@"
|
||||||
Vendored
+7
-18
@@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=.
|
|||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
@@ -37,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
|||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if "%ERRORLEVEL%" == "0" goto init
|
if "%ERRORLEVEL%" == "0" goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
@@ -51,7 +54,7 @@ goto fail
|
|||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto init
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
@@ -61,28 +64,14 @@ echo location of your Java installation.
|
|||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:init
|
|
||||||
@rem Get command-line arguments, handling Windows variants
|
|
||||||
|
|
||||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
|
||||||
|
|
||||||
:win9xME_args
|
|
||||||
@rem Slurp the command line arguments.
|
|
||||||
set CMD_LINE_ARGS=
|
|
||||||
set _SKIP=2
|
|
||||||
|
|
||||||
:win9xME_args_slurp
|
|
||||||
if "x%~1" == "x" goto execute
|
|
||||||
|
|
||||||
set CMD_LINE_ARGS=%*
|
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute Gradle
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ public class CarpetServer implements ClientModInitializer,DedicatedServerModInit
|
|||||||
|
|
||||||
public static void tick(MinecraftServer server)
|
public static void tick(MinecraftServer server)
|
||||||
{
|
{
|
||||||
TickSpeed.tick(server);
|
TickSpeed.tick();
|
||||||
HUDController.update_hud(server);
|
HUDController.update_hud(server);
|
||||||
scriptServer.tick();
|
scriptServer.tick();
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package carpet.commands;
|
|||||||
|
|
||||||
import carpet.CarpetSettings;
|
import carpet.CarpetSettings;
|
||||||
import carpet.helpers.TickSpeed;
|
import carpet.helpers.TickSpeed;
|
||||||
|
import carpet.network.ServerNetworkHandler;
|
||||||
import carpet.settings.SettingsManager;
|
import carpet.settings.SettingsManager;
|
||||||
import carpet.utils.CarpetProfiler;
|
import carpet.utils.CarpetProfiler;
|
||||||
import carpet.utils.Messenger;
|
import carpet.utils.Messenger;
|
||||||
@@ -95,16 +96,13 @@ public class TickCommand
|
|||||||
|
|
||||||
private static int toggleFreeze(ServerCommandSource source, boolean isDeep)
|
private static int toggleFreeze(ServerCommandSource source, boolean isDeep)
|
||||||
{
|
{
|
||||||
TickSpeed.is_paused = !TickSpeed.is_paused;
|
TickSpeed.setFrozenState(!TickSpeed.isPaused(), isDeep);
|
||||||
if (TickSpeed.is_paused)
|
if (TickSpeed.isPaused())
|
||||||
{
|
{
|
||||||
TickSpeed.deepFreeze = isDeep;
|
|
||||||
Messenger.m(source, "gi Game is "+(isDeep?"deeply ":"")+"frozen");
|
Messenger.m(source, "gi Game is "+(isDeep?"deeply ":"")+"frozen");
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TickSpeed.deepFreeze = false;
|
|
||||||
Messenger.m(source, "gi Game runs normally");
|
Messenger.m(source, "gi Game runs normally");
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@@ -119,9 +117,10 @@ public class TickCommand
|
|||||||
private static int toggleSuperHot(ServerCommandSource source)
|
private static int toggleSuperHot(ServerCommandSource source)
|
||||||
{
|
{
|
||||||
TickSpeed.is_superHot = !TickSpeed.is_superHot;
|
TickSpeed.is_superHot = !TickSpeed.is_superHot;
|
||||||
|
ServerNetworkHandler.updateSuperHotStateToConnectedPlayers();
|
||||||
if (TickSpeed.is_superHot)
|
if (TickSpeed.is_superHot)
|
||||||
{
|
{
|
||||||
Messenger.m(source,"gi Superhot enabled");
|
Messenger.m(source, "gi Superhot enabled");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,4 +5,7 @@ import carpet.helpers.EntityPlayerActionPack;
|
|||||||
public interface ServerPlayerEntityInterface
|
public interface ServerPlayerEntityInterface
|
||||||
{
|
{
|
||||||
EntityPlayerActionPack getActionPack();
|
EntityPlayerActionPack getActionPack();
|
||||||
|
void invalidateEntityObjectReference();
|
||||||
|
boolean isInvalidEntityObject();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,6 @@ import java.util.function.BiConsumer;
|
|||||||
import carpet.CarpetServer;
|
import carpet.CarpetServer;
|
||||||
import carpet.network.ServerNetworkHandler;
|
import carpet.network.ServerNetworkHandler;
|
||||||
import carpet.utils.Messenger;
|
import carpet.utils.Messenger;
|
||||||
import net.minecraft.server.MinecraftServer;
|
|
||||||
import net.minecraft.server.command.CommandManager;
|
import net.minecraft.server.command.CommandManager;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
@@ -26,10 +25,43 @@ public class TickSpeed
|
|||||||
public static ServerCommandSource tick_warp_sender = null;
|
public static ServerCommandSource tick_warp_sender = null;
|
||||||
public static int player_active_timeout = 0;
|
public static int player_active_timeout = 0;
|
||||||
public static boolean process_entities = true;
|
public static boolean process_entities = true;
|
||||||
public static boolean deepFreeze = false;
|
private static boolean deepFreeze = false;
|
||||||
public static boolean is_paused = false;
|
private static boolean is_paused = false;
|
||||||
public static boolean is_superHot = false;
|
public static boolean is_superHot = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Whether or not the game is in a frozen state.
|
||||||
|
* You should normally use {@link #process_entities} instead,
|
||||||
|
* since that one accounts for tick steps and superhot
|
||||||
|
*/
|
||||||
|
public static boolean isPaused() {
|
||||||
|
return is_paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the game is deeply frozen.
|
||||||
|
* This can be used for things that you may not normally want
|
||||||
|
* to freeze, but may need to in some situations.
|
||||||
|
* This should be checked with {@link #process_entities} to make sure the
|
||||||
|
* current tick is actually frozen, not only the game
|
||||||
|
* @return Whether or not the game is deeply frozen.
|
||||||
|
*/
|
||||||
|
public static boolean deeplyFrozen() {
|
||||||
|
return deepFreeze;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to update the frozen state of the game.
|
||||||
|
* Handles connected clients as well.
|
||||||
|
* @param isPaused Whether or not the game is paused
|
||||||
|
* @param isDeepFreeze Whether or not the game is deeply frozen
|
||||||
|
*/
|
||||||
|
public static void setFrozenState(boolean isPaused, boolean isDeepFreeze) {
|
||||||
|
is_paused = isPaused;
|
||||||
|
deepFreeze = isPaused ? isDeepFreeze : false;
|
||||||
|
ServerNetworkHandler.updateFrozenStateToConnectedPlayers();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Functional interface that listens for tickrate changes. This is
|
* Functional interface that listens for tickrate changes. This is
|
||||||
* implemented to allow tickrate compatibility with other mods etc.
|
* implemented to allow tickrate compatibility with other mods etc.
|
||||||
@@ -66,6 +98,7 @@ public class TickSpeed
|
|||||||
public static void add_ticks_to_run_in_pause(int ticks)
|
public static void add_ticks_to_run_in_pause(int ticks)
|
||||||
{
|
{
|
||||||
player_active_timeout = PLAYER_GRACE+ticks;
|
player_active_timeout = PLAYER_GRACE+ticks;
|
||||||
|
ServerNetworkHandler.updateTickPlayerActiveTimeoutToConnectedPlayers();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BaseText tickrate_advance(ServerPlayerEntity player, int advance, String callback, ServerCommandSource source)
|
public static BaseText tickrate_advance(ServerPlayerEntity player, int advance, String callback, ServerCommandSource source)
|
||||||
@@ -155,7 +188,7 @@ public class TickSpeed
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void tick(MinecraftServer server)
|
public static void tick()
|
||||||
{
|
{
|
||||||
process_entities = true;
|
process_entities = true;
|
||||||
if (player_active_timeout > 0)
|
if (player_active_timeout > 0)
|
||||||
|
|||||||
@@ -18,6 +18,6 @@ public class ChunkTicketManager_tickMixin
|
|||||||
{
|
{
|
||||||
// pausing expiry of tickets
|
// pausing expiry of tickets
|
||||||
// that will prevent also chunks from unloading, so require a deep frozen state
|
// that will prevent also chunks from unloading, so require a deep frozen state
|
||||||
if (!TickSpeed.process_entities && TickSpeed.deepFreeze) age--;
|
if (!TickSpeed.process_entities && TickSpeed.deeplyFrozen()) age--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package carpet.mixins;
|
package carpet.mixins;
|
||||||
|
|
||||||
|
import carpet.helpers.TickSpeed;
|
||||||
import carpet.utils.CarpetProfiler;
|
import carpet.utils.CarpetProfiler;
|
||||||
import net.minecraft.server.function.CommandFunctionManager;
|
import net.minecraft.server.function.CommandFunctionManager;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
@@ -12,9 +13,11 @@ public class CommandFunctionManager_tickMixin
|
|||||||
{
|
{
|
||||||
CarpetProfiler.ProfilerToken currentSection;
|
CarpetProfiler.ProfilerToken currentSection;
|
||||||
|
|
||||||
@Inject(method = "tick", at = @At("HEAD"))
|
@Inject(method = "tick", at = @At("HEAD"), cancellable = true)
|
||||||
private void beforeDatapacks(CallbackInfo ci)
|
private void beforeDatapacks(CallbackInfo ci)
|
||||||
{
|
{
|
||||||
|
if (!TickSpeed.process_entities) ci.cancel();
|
||||||
|
else
|
||||||
currentSection = CarpetProfiler.start_section(null, "Datapacks", CarpetProfiler.TYPE.GENERAL);
|
currentSection = CarpetProfiler.start_section(null, "Datapacks", CarpetProfiler.TYPE.GENERAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
package carpet.mixins;
|
package carpet.mixins;
|
||||||
|
|
||||||
|
import carpet.CarpetServer;
|
||||||
|
import carpet.helpers.TickSpeed;
|
||||||
import carpet.network.CarpetClient;
|
import carpet.network.CarpetClient;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import net.minecraft.client.world.ClientWorld;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
@@ -11,9 +15,21 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||||||
@Mixin(MinecraftClient.class)
|
@Mixin(MinecraftClient.class)
|
||||||
public class MinecraftClientMixin
|
public class MinecraftClientMixin
|
||||||
{
|
{
|
||||||
|
@Shadow public ClientWorld world;
|
||||||
|
|
||||||
@Inject(method = "disconnect(Lnet/minecraft/client/gui/screen/Screen;)V", at = @At("HEAD"))
|
@Inject(method = "disconnect(Lnet/minecraft/client/gui/screen/Screen;)V", at = @At("HEAD"))
|
||||||
private void onCloseGame(Screen screen, CallbackInfo ci)
|
private void onCloseGame(Screen screen, CallbackInfo ci)
|
||||||
{
|
{
|
||||||
CarpetClient.disconnect();
|
CarpetClient.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Inject(at = @At("HEAD"), method = "tick")
|
||||||
|
private void onClientTick(CallbackInfo info) {
|
||||||
|
if (this.world != null) {
|
||||||
|
if (CarpetServer.minecraft_server == null)
|
||||||
|
TickSpeed.tick();
|
||||||
|
if (!TickSpeed.process_entities)
|
||||||
|
CarpetClient.shapes.renewShapes();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package carpet.mixins;
|
package carpet.mixins;
|
||||||
|
|
||||||
import carpet.fakes.MinecraftServerInterface;
|
import carpet.fakes.MinecraftServerInterface;
|
||||||
|
import carpet.helpers.TickSpeed;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.ServerTask;
|
import net.minecraft.server.ServerTask;
|
||||||
import net.minecraft.server.world.ServerWorld;
|
import net.minecraft.server.world.ServerWorld;
|
||||||
@@ -69,6 +70,8 @@ public abstract class MinecraftServer_scarpetMixin extends ReentrantThreadExecut
|
|||||||
))
|
))
|
||||||
public void tickTasks(BooleanSupplier booleanSupplier_1, CallbackInfo ci)
|
public void tickTasks(BooleanSupplier booleanSupplier_1, CallbackInfo ci)
|
||||||
{
|
{
|
||||||
|
if (!TickSpeed.process_entities)
|
||||||
|
return;
|
||||||
TICK.onTick();
|
TICK.onTick();
|
||||||
NETHER_TICK.onTick();
|
NETHER_TICK.onTick();
|
||||||
ENDER_TICK.onTick();
|
ENDER_TICK.onTick();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package carpet.mixins;
|
package carpet.mixins;
|
||||||
|
|
||||||
|
import carpet.fakes.ServerPlayerEntityInterface;
|
||||||
import net.minecraft.server.PlayerManager;
|
import net.minecraft.server.PlayerManager;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
@@ -17,4 +18,11 @@ public class PlayerManager_scarpetEventsMixin
|
|||||||
{
|
{
|
||||||
PLAYER_RESPAWNS.onPlayerEvent(player);
|
PLAYER_RESPAWNS.onPlayerEvent(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Inject(method = "respawnPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayerEntity;onSpawn()V"))
|
||||||
|
private void invalidatePreviousInstance(ServerPlayerEntity player, boolean alive, CallbackInfoReturnable<ServerPlayerEntity> cir)
|
||||||
|
{
|
||||||
|
((ServerPlayerEntityInterface)player).invalidateEntityObjectReference();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package carpet.mixins;
|
||||||
|
|
||||||
|
import net.minecraft.scoreboard.ScoreboardCriterion;
|
||||||
|
import net.minecraft.scoreboard.ScoreboardObjective;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
|
@Mixin(ScoreboardObjective.class)
|
||||||
|
public interface ScoreboardObjective_scarpetMixin {
|
||||||
|
@Accessor("criterion")
|
||||||
|
void setCriterion(ScoreboardCriterion criterion);
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package carpet.mixins;
|
||||||
|
|
||||||
|
import net.minecraft.scoreboard.Scoreboard;
|
||||||
|
import net.minecraft.scoreboard.ScoreboardCriterion;
|
||||||
|
import net.minecraft.scoreboard.ScoreboardObjective;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Mixin(Scoreboard.class)
|
||||||
|
public interface Scoreboard_scarpetMixin {
|
||||||
|
@Accessor("objectivesByCriterion")
|
||||||
|
Map<ScoreboardCriterion, List<ScoreboardObjective>> getObjectivesByCriterion();
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package carpet.mixins;
|
package carpet.mixins;
|
||||||
|
|
||||||
import carpet.fakes.EntityInterface;
|
import carpet.fakes.EntityInterface;
|
||||||
|
import carpet.fakes.ServerPlayerEntityInterface;
|
||||||
import carpet.script.EntityEventsGroup;
|
import carpet.script.EntityEventsGroup;
|
||||||
import com.mojang.authlib.GameProfile;
|
import com.mojang.authlib.GameProfile;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
@@ -28,8 +29,11 @@ import static carpet.script.CarpetEventServer.Event.PLAYER_FINISHED_USING_ITEM;
|
|||||||
import static carpet.script.CarpetEventServer.Event.STATISTICS;
|
import static carpet.script.CarpetEventServer.Event.STATISTICS;
|
||||||
|
|
||||||
@Mixin(ServerPlayerEntity.class)
|
@Mixin(ServerPlayerEntity.class)
|
||||||
public abstract class ServerPlayerEntity_scarpetEventMixin extends PlayerEntity
|
public abstract class ServerPlayerEntity_scarpetEventMixin extends PlayerEntity implements ServerPlayerEntityInterface
|
||||||
{
|
{
|
||||||
|
// to denote if the player reference is valid
|
||||||
|
|
||||||
|
private boolean isInvalidReference = false;
|
||||||
|
|
||||||
public ServerPlayerEntity_scarpetEventMixin(World world, BlockPos blockPos, float f, GameProfile gameProfile)
|
public ServerPlayerEntity_scarpetEventMixin(World world, BlockPos blockPos, float f, GameProfile gameProfile)
|
||||||
{
|
{
|
||||||
@@ -109,6 +113,17 @@ public abstract class ServerPlayerEntity_scarpetEventMixin extends PlayerEntity
|
|||||||
}
|
}
|
||||||
PLAYER_CHANGES_DIMENSION.onDimensionChange(player, previousLocation, to, previousDimension, destination.getRegistryKey());
|
PLAYER_CHANGES_DIMENSION.onDimensionChange(player, previousLocation, to, previousDimension, destination.getRegistryKey());
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidateEntityObjectReference()
|
||||||
|
{
|
||||||
|
isInvalidReference = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInvalidEntityObject()
|
||||||
|
{
|
||||||
|
return isInvalidReference;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,7 @@ import carpet.settings.SettingsManager;
|
|||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import net.minecraft.client.network.ClientPlayerEntity;
|
import net.minecraft.client.network.ClientPlayerEntity;
|
||||||
import net.minecraft.nbt.AbstractNumberTag;
|
import net.minecraft.nbt.AbstractNumberTag;
|
||||||
|
import net.minecraft.nbt.ByteTag;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.ListTag;
|
import net.minecraft.nbt.ListTag;
|
||||||
import net.minecraft.nbt.Tag;
|
import net.minecraft.nbt.Tag;
|
||||||
@@ -65,6 +66,14 @@ public class ClientNetworkHandler
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
dataHandlers.put("TickRate", (p, t) -> TickSpeed.tickrate(((AbstractNumberTag)t).getFloat(), false));
|
dataHandlers.put("TickRate", (p, t) -> TickSpeed.tickrate(((AbstractNumberTag)t).getFloat(), false));
|
||||||
|
dataHandlers.put("TickingState", (p, t) -> {
|
||||||
|
CompoundTag tickingState = (CompoundTag)t;
|
||||||
|
TickSpeed.setFrozenState(tickingState.getBoolean("is_paused"), tickingState.getBoolean("deepFreeze"));
|
||||||
|
});
|
||||||
|
dataHandlers.put("SuperHotState", (p, t) -> {
|
||||||
|
TickSpeed.is_superHot = ((ByteTag) t).equals(ByteTag.ONE);
|
||||||
|
});
|
||||||
|
dataHandlers.put("TickPlayerActiveTimeout", (p, t) -> TickSpeed.player_active_timeout = ((AbstractNumberTag)t).getInt());
|
||||||
dataHandlers.put("scShape", (p, t) -> { // deprecated
|
dataHandlers.put("scShape", (p, t) -> { // deprecated
|
||||||
if (CarpetClient.shapes != null)
|
if (CarpetClient.shapes != null)
|
||||||
CarpetClient.shapes.addShape((CompoundTag)t);
|
CarpetClient.shapes.addShape((CompoundTag)t);
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ public class ServerNetworkHandler
|
|||||||
CarpetSettings.LOG.info("Player "+playerEntity.getName().getString()+" joined with a matching carpet client");
|
CarpetSettings.LOG.info("Player "+playerEntity.getName().getString()+" joined with a matching carpet client");
|
||||||
else
|
else
|
||||||
CarpetSettings.LOG.warn("Player "+playerEntity.getName().getString()+" joined with another carpet version: "+clientVersion);
|
CarpetSettings.LOG.warn("Player "+playerEntity.getName().getString()+" joined with another carpet version: "+clientVersion);
|
||||||
DataBuilder data = DataBuilder.create().withTickRate();
|
DataBuilder data = DataBuilder.create().withTickRate().withFrozenState().withTickPlayerActiveTimeout(); // .withSuperHotState()
|
||||||
CarpetServer.settingsManager.getRules().forEach(data::withRule);
|
CarpetServer.settingsManager.getRules().forEach(data::withRule);
|
||||||
CarpetServer.extensions.forEach(e -> {
|
CarpetServer.extensions.forEach(e -> {
|
||||||
SettingsManager eManager = e.customSettingsManager();
|
SettingsManager eManager = e.customSettingsManager();
|
||||||
@@ -173,6 +173,42 @@ public class ServerNetworkHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void updateFrozenStateToConnectedPlayers()
|
||||||
|
{
|
||||||
|
if (CarpetSettings.superSecretSetting) return;
|
||||||
|
for (ServerPlayerEntity player : remoteCarpetPlayers.keySet())
|
||||||
|
{
|
||||||
|
player.networkHandler.sendPacket(new CustomPayloadS2CPacket(
|
||||||
|
CarpetClient.CARPET_CHANNEL,
|
||||||
|
DataBuilder.create().withFrozenState().build()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void updateSuperHotStateToConnectedPlayers()
|
||||||
|
{
|
||||||
|
if(CarpetSettings.superSecretSetting) return;
|
||||||
|
for (ServerPlayerEntity player : remoteCarpetPlayers.keySet())
|
||||||
|
{
|
||||||
|
player.networkHandler.sendPacket(new CustomPayloadS2CPacket(
|
||||||
|
CarpetClient.CARPET_CHANNEL,
|
||||||
|
DataBuilder.create().withSuperHotState().build()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void updateTickPlayerActiveTimeoutToConnectedPlayers()
|
||||||
|
{
|
||||||
|
if (CarpetSettings.superSecretSetting) return;
|
||||||
|
for (ServerPlayerEntity player : remoteCarpetPlayers.keySet())
|
||||||
|
{
|
||||||
|
player.networkHandler.sendPacket(new CustomPayloadS2CPacket(
|
||||||
|
CarpetClient.CARPET_CHANNEL,
|
||||||
|
DataBuilder.create().withTickPlayerActiveTimeout().build()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void broadcastCustomCommand(String command, Tag data)
|
public static void broadcastCustomCommand(String command, Tag data)
|
||||||
{
|
{
|
||||||
if (CarpetSettings.superSecretSetting) return;
|
if (CarpetSettings.superSecretSetting) return;
|
||||||
@@ -240,6 +276,24 @@ public class ServerNetworkHandler
|
|||||||
tag.putFloat("TickRate", TickSpeed.tickrate);
|
tag.putFloat("TickRate", TickSpeed.tickrate);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
private DataBuilder withFrozenState()
|
||||||
|
{
|
||||||
|
CompoundTag tickingState = new CompoundTag();
|
||||||
|
tickingState.putBoolean("is_paused", TickSpeed.isPaused());
|
||||||
|
tickingState.putBoolean("deepFreeze", TickSpeed.deeplyFrozen());
|
||||||
|
tag.put("TickingState", tickingState);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
private DataBuilder withSuperHotState()
|
||||||
|
{
|
||||||
|
tag.putBoolean("SuperHotState", TickSpeed.is_superHot);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
private DataBuilder withTickPlayerActiveTimeout()
|
||||||
|
{
|
||||||
|
tag.putInt("TickPlayerActiveTimeout", TickSpeed.player_active_timeout);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
private DataBuilder withRule(ParsedRule<?> rule)
|
private DataBuilder withRule(ParsedRule<?> rule)
|
||||||
{
|
{
|
||||||
CompoundTag rules = (CompoundTag) tag.get("Rules");
|
CompoundTag rules = (CompoundTag) tag.get("Rules");
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package carpet.script;
|
|||||||
|
|
||||||
import carpet.CarpetServer;
|
import carpet.CarpetServer;
|
||||||
import carpet.CarpetSettings;
|
import carpet.CarpetSettings;
|
||||||
|
import carpet.helpers.TickSpeed;
|
||||||
import carpet.script.exception.InternalExpressionException;
|
import carpet.script.exception.InternalExpressionException;
|
||||||
import carpet.script.value.BlockValue;
|
import carpet.script.value.BlockValue;
|
||||||
import carpet.script.value.EntityValue;
|
import carpet.script.value.EntityValue;
|
||||||
@@ -973,6 +974,8 @@ public class CarpetEventServer
|
|||||||
|
|
||||||
public void tick()
|
public void tick()
|
||||||
{
|
{
|
||||||
|
if (!TickSpeed.process_entities)
|
||||||
|
return;
|
||||||
Iterator<ScheduledCall> eventIterator = scheduledCalls.iterator();
|
Iterator<ScheduledCall> eventIterator = scheduledCalls.iterator();
|
||||||
List<ScheduledCall> currentCalls = new ArrayList<>();
|
List<ScheduledCall> currentCalls = new ArrayList<>();
|
||||||
while(eventIterator.hasNext())
|
while(eventIterator.hasNext())
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ import carpet.script.value.NumericValue;
|
|||||||
import carpet.script.value.StringValue;
|
import carpet.script.value.StringValue;
|
||||||
import carpet.script.value.Value;
|
import carpet.script.value.Value;
|
||||||
import carpet.utils.Messenger;
|
import carpet.utils.Messenger;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
@@ -705,7 +707,7 @@ public class CarpetScriptHost extends ScriptHost
|
|||||||
public boolean removeResourceFile(String resource, boolean isShared, String type)
|
public boolean removeResourceFile(String resource, boolean isShared, String type)
|
||||||
{
|
{
|
||||||
if (getName() == null && !isShared) return false; //
|
if (getName() == null && !isShared) return false; //
|
||||||
return Module.dropExistingFile(main, resource, type.equals("nbt")?"nbt":"txt", isShared);
|
return Module.dropExistingFile(main, resource, type, isShared);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean appendLogFile(String resource, boolean isShared, String type, List<String> data)
|
public boolean appendLogFile(String resource, boolean isShared, String type, List<String> data)
|
||||||
@@ -714,16 +716,22 @@ public class CarpetScriptHost extends ScriptHost
|
|||||||
return Module.appendToTextFile(main, resource, type, isShared, data);
|
return Module.appendToTextFile(main, resource, type, isShared, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> readTextResource(String resource, boolean isShared)
|
public List<String> readTextResource(String resource, String type, boolean isShared)
|
||||||
{
|
{
|
||||||
if (getName() == null && !isShared) return null; //
|
if (getName() == null && !isShared) return null;
|
||||||
return Module.listFile(main, resource, "txt", isShared);
|
return Module.listFile(main, resource, type, isShared);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonElement readJsonFile(String resource, String type, boolean isShared)
|
||||||
|
{
|
||||||
|
if (getName() == null && !isShared) return null;
|
||||||
|
return Module.readJsonFile(main, resource, type, isShared);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream<String> listFolder(String resource, String ext, boolean isShared)
|
public Stream<String> listFolder(String resource, String type, boolean isShared)
|
||||||
{
|
{
|
||||||
if (getName() == null && !isShared) return null; //
|
if (getName() == null && !isShared) return null; //
|
||||||
return Module.listFolder(main, resource, ext, isShared);
|
return Module.listFolder(main, resource, type, isShared);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ public abstract class ScriptHost
|
|||||||
|
|
||||||
protected ScriptHost parent;
|
protected ScriptHost parent;
|
||||||
protected boolean perUser;
|
protected boolean perUser;
|
||||||
protected String user;
|
public String user;
|
||||||
|
|
||||||
public String getName() {return main ==null?null: main.getName();}
|
public String getName() {return main ==null?null: main.getName();}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import carpet.fakes.MinecraftServerInterface;
|
|||||||
import carpet.fakes.StatTypeInterface;
|
import carpet.fakes.StatTypeInterface;
|
||||||
import carpet.fakes.ThreadedAnvilChunkStorageInterface;
|
import carpet.fakes.ThreadedAnvilChunkStorageInterface;
|
||||||
import carpet.helpers.FeatureGenerator;
|
import carpet.helpers.FeatureGenerator;
|
||||||
|
import carpet.script.bundled.Module;
|
||||||
import carpet.script.CarpetContext;
|
import carpet.script.CarpetContext;
|
||||||
import carpet.script.CarpetEventServer;
|
import carpet.script.CarpetEventServer;
|
||||||
import carpet.script.CarpetScriptHost;
|
import carpet.script.CarpetScriptHost;
|
||||||
@@ -19,6 +20,7 @@ import carpet.script.argument.Vector3Argument;
|
|||||||
import carpet.script.exception.ExitStatement;
|
import carpet.script.exception.ExitStatement;
|
||||||
import carpet.script.exception.InternalExpressionException;
|
import carpet.script.exception.InternalExpressionException;
|
||||||
import carpet.script.utils.FixedCommandSource;
|
import carpet.script.utils.FixedCommandSource;
|
||||||
|
import carpet.script.utils.ScarpetJsonDeserializer;
|
||||||
import carpet.script.utils.ShapeDispatcher;
|
import carpet.script.utils.ShapeDispatcher;
|
||||||
import carpet.script.utils.WorldTools;
|
import carpet.script.utils.WorldTools;
|
||||||
import carpet.script.value.EntityValue;
|
import carpet.script.value.EntityValue;
|
||||||
@@ -33,7 +35,6 @@ import carpet.script.value.StringValue;
|
|||||||
import carpet.script.value.Value;
|
import carpet.script.value.Value;
|
||||||
import carpet.script.value.ValueConversions;
|
import carpet.script.value.ValueConversions;
|
||||||
import carpet.utils.Messenger;
|
import carpet.utils.Messenger;
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EntityType;
|
import net.minecraft.entity.EntityType;
|
||||||
@@ -69,6 +70,11 @@ import net.minecraft.world.World;
|
|||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
import org.apache.commons.lang3.tuple.Triple;
|
import org.apache.commons.lang3.tuple.Triple;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -86,12 +92,7 @@ import static java.lang.Math.min;
|
|||||||
public class Auxiliary {
|
public class Auxiliary {
|
||||||
public static final String MARKER_STRING = "__scarpet_marker";
|
public static final String MARKER_STRING = "__scarpet_marker";
|
||||||
private static final Map<String, SoundCategory> mixerMap = Arrays.stream(SoundCategory.values()).collect(Collectors.toMap(SoundCategory::getName, k -> k));
|
private static final Map<String, SoundCategory> mixerMap = Arrays.stream(SoundCategory.values()).collect(Collectors.toMap(SoundCategory::getName, k -> k));
|
||||||
private static final Map<String, String> supportedTypes = ImmutableMap.of(
|
public static final Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().registerTypeAdapter(Value.class, new ScarpetJsonDeserializer()).create();
|
||||||
"raw", ".txt",
|
|
||||||
"text", ".txt",
|
|
||||||
"nbt", ".nbt",
|
|
||||||
"folder", "folder"
|
|
||||||
);
|
|
||||||
|
|
||||||
public static String recognizeResource(Value value, boolean isFloder)
|
public static String recognizeResource(Value value, boolean isFloder)
|
||||||
{
|
{
|
||||||
@@ -112,7 +113,7 @@ public class Auxiliary {
|
|||||||
String origtype = lv.get(1).evalValue(c).getString().toLowerCase(Locale.ROOT);
|
String origtype = lv.get(1).evalValue(c).getString().toLowerCase(Locale.ROOT);
|
||||||
boolean shared = origtype.startsWith("shared_");
|
boolean shared = origtype.startsWith("shared_");
|
||||||
String type = shared ? origtype.substring(7) : origtype; //len(shared_)
|
String type = shared ? origtype.substring(7) : origtype; //len(shared_)
|
||||||
if (!supportedTypes.containsKey(type))
|
if (!Module.supportedTypes.containsKey(type))
|
||||||
throw new InternalExpressionException("Unsupported file type: "+origtype);
|
throw new InternalExpressionException("Unsupported file type: "+origtype);
|
||||||
if (type.equals("folder") && !isFloder)
|
if (type.equals("folder") && !isFloder)
|
||||||
throw new InternalExpressionException("Folder types are no supported for this IO function");
|
throw new InternalExpressionException("Folder types are no supported for this IO function");
|
||||||
@@ -526,7 +527,7 @@ public class Auxiliary {
|
|||||||
Text title = null;
|
Text title = null;
|
||||||
if (lv.size() > 2)
|
if (lv.size() > 2)
|
||||||
{
|
{
|
||||||
pVal = lv.get(2).evalValue(c);
|
pVal = lv.get(2).evalValue(c);
|
||||||
if (pVal instanceof FormattedTextValue)
|
if (pVal instanceof FormattedTextValue)
|
||||||
title = ((FormattedTextValue) pVal).getText();
|
title = ((FormattedTextValue) pVal).getText();
|
||||||
else
|
else
|
||||||
@@ -803,7 +804,7 @@ public class Auxiliary {
|
|||||||
expression.addLazyFunction("list_files", 2, (c, t, lv) ->
|
expression.addLazyFunction("list_files", 2, (c, t, lv) ->
|
||||||
{
|
{
|
||||||
Triple<String, String, Boolean> fdesc = getFileDescriptor(lv, c, true);
|
Triple<String, String, Boolean> fdesc = getFileDescriptor(lv, c, true);
|
||||||
Stream<String> files = ((CarpetScriptHost) c.host).listFolder(fdesc.getLeft(), supportedTypes.get(fdesc.getMiddle()), fdesc.getRight());
|
Stream<String> files = ((CarpetScriptHost) c.host).listFolder(fdesc.getLeft(), fdesc.getMiddle(), fdesc.getRight());
|
||||||
if (files == null) return LazyValue.NULL;
|
if (files == null) return LazyValue.NULL;
|
||||||
Value ret = ListValue.wrap(files.map(StringValue::of).collect(Collectors.toList()));
|
Value ret = ListValue.wrap(files.map(StringValue::of).collect(Collectors.toList()));
|
||||||
return (cc, tt) -> ret;
|
return (cc, tt) -> ret;
|
||||||
@@ -820,9 +821,29 @@ public class Auxiliary {
|
|||||||
if (state == null) return LazyValue.NULL;
|
if (state == null) return LazyValue.NULL;
|
||||||
retVal = new NBTSerializableValue(state);
|
retVal = new NBTSerializableValue(state);
|
||||||
}
|
}
|
||||||
|
else if (fdesc.getMiddle().equals("json"))
|
||||||
|
{
|
||||||
|
JsonElement json;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
json = ((CarpetScriptHost) c.host).readJsonFile(fdesc.getLeft(), fdesc.getMiddle(), fdesc.getRight());
|
||||||
|
}
|
||||||
|
catch (JsonParseException e)
|
||||||
|
{
|
||||||
|
Throwable exception = e;
|
||||||
|
if(e.getCause() != null)
|
||||||
|
exception = e.getCause();
|
||||||
|
throw new InternalExpressionException("Failed to read JSON file: "+exception.getMessage());
|
||||||
|
}
|
||||||
|
Value parsedJson = gson.fromJson(json, Value.class);
|
||||||
|
if (parsedJson == null)
|
||||||
|
retVal = Value.NULL;
|
||||||
|
else
|
||||||
|
retVal = parsedJson;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
List<String> content = ((CarpetScriptHost) c.host).readTextResource(fdesc.getLeft(), fdesc.getRight());
|
List<String> content = ((CarpetScriptHost) c.host).readTextResource(fdesc.getLeft(), fdesc.getMiddle(), fdesc.getRight());
|
||||||
if (content == null) return LazyValue.NULL;
|
if (content == null) return LazyValue.NULL;
|
||||||
retVal = ListValue.wrap(content.stream().map(StringValue::new).collect(Collectors.toList()));
|
retVal = ListValue.wrap(content.stream().map(StringValue::new).collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
@@ -851,6 +872,12 @@ public class Auxiliary {
|
|||||||
Tag tag = tagValue.getTag();
|
Tag tag = tagValue.getTag();
|
||||||
success = ((CarpetScriptHost) c.host).writeTagFile(tag, fdesc.getLeft(), fdesc.getRight());
|
success = ((CarpetScriptHost) c.host).writeTagFile(tag, fdesc.getLeft(), fdesc.getRight());
|
||||||
}
|
}
|
||||||
|
else if (fdesc.getMiddle().equals("json"))
|
||||||
|
{
|
||||||
|
List<String> data = Collections.singletonList(gson.toJson(lv.get(2).evalValue(c).toJson()));
|
||||||
|
((CarpetScriptHost) c.host).removeResourceFile(fdesc.getLeft(), fdesc.getRight(), fdesc.getMiddle());
|
||||||
|
success = ((CarpetScriptHost) c.host).appendLogFile(fdesc.getLeft(), fdesc.getRight(), fdesc.getMiddle(), data);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
List<String> data = new ArrayList<>();
|
List<String> data = new ArrayList<>();
|
||||||
|
|||||||
@@ -45,10 +45,17 @@ public class Entities {
|
|||||||
{
|
{
|
||||||
expression.addLazyFunction("player", -1, (c, t, lv) ->
|
expression.addLazyFunction("player", -1, (c, t, lv) ->
|
||||||
{
|
{
|
||||||
if (lv.size() ==0)
|
if (lv.size() == 0)
|
||||||
{
|
{
|
||||||
|
CarpetContext cc = (CarpetContext)c;
|
||||||
Entity callingEntity = ((CarpetContext)c).s.getEntity();
|
if (cc.host.user != null)
|
||||||
|
{
|
||||||
|
ServerPlayerEntity player = cc.s.getMinecraftServer().getPlayerManager().getPlayer(cc.host.user);
|
||||||
|
if (player == null) return LazyValue.NULL;
|
||||||
|
Value ret = new EntityValue(player);
|
||||||
|
return (_c, _t) -> ret;
|
||||||
|
}
|
||||||
|
Entity callingEntity = cc.s.getEntity();
|
||||||
if (callingEntity instanceof PlayerEntity)
|
if (callingEntity instanceof PlayerEntity)
|
||||||
{
|
{
|
||||||
Value retval = new EntityValue(callingEntity);
|
Value retval = new EntityValue(callingEntity);
|
||||||
@@ -108,7 +115,7 @@ public class Entities {
|
|||||||
retval = new EntityValue(player);
|
retval = new EntityValue(player);
|
||||||
}
|
}
|
||||||
Value finalVar = retval;
|
Value finalVar = retval;
|
||||||
return (cc, tt) -> finalVar;
|
return (_c, _t) -> finalVar;
|
||||||
});
|
});
|
||||||
|
|
||||||
expression.addLazyFunction("spawn", -1, (c, t, lv) ->
|
expression.addLazyFunction("spawn", -1, (c, t, lv) ->
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package carpet.script.api;
|
package carpet.script.api;
|
||||||
|
|
||||||
|
import carpet.mixins.ScoreboardObjective_scarpetMixin;
|
||||||
|
import carpet.mixins.Scoreboard_scarpetMixin;
|
||||||
import carpet.script.CarpetContext;
|
import carpet.script.CarpetContext;
|
||||||
import carpet.script.Expression;
|
import carpet.script.Expression;
|
||||||
import carpet.script.LazyValue;
|
import carpet.script.LazyValue;
|
||||||
@@ -11,6 +13,7 @@ import carpet.script.value.NumericValue;
|
|||||||
import carpet.script.value.StringValue;
|
import carpet.script.value.StringValue;
|
||||||
import carpet.script.value.FormattedTextValue;
|
import carpet.script.value.FormattedTextValue;
|
||||||
import carpet.script.value.Value;
|
import carpet.script.value.Value;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.boss.BossBar;
|
import net.minecraft.entity.boss.BossBar;
|
||||||
import net.minecraft.entity.boss.BossBarManager;
|
import net.minecraft.entity.boss.BossBarManager;
|
||||||
@@ -133,8 +136,15 @@ public class Scoreboards {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ScoreboardObjective objective = scoreboard.getObjective(objectiveName);
|
ScoreboardObjective objective = scoreboard.getObjective(objectiveName);
|
||||||
if (objective != null)
|
if (objective != null) {
|
||||||
|
if(lv.size() == 1) return (_c, _t) -> StringValue.of(objective.getCriterion().getName());
|
||||||
|
if(objective.getCriterion().equals(criterion) || lv.size() == 1) return LazyValue.NULL;
|
||||||
|
((Scoreboard_scarpetMixin)scoreboard).getObjectivesByCriterion().get(objective.getCriterion()).remove(objective);
|
||||||
|
((ScoreboardObjective_scarpetMixin) objective).setCriterion(criterion);
|
||||||
|
(((Scoreboard_scarpetMixin)scoreboard).getObjectivesByCriterion().computeIfAbsent(criterion, (criterion1) -> Lists.newArrayList())).add(objective);
|
||||||
|
scoreboard.updateObjective(objective);
|
||||||
return LazyValue.FALSE;
|
return LazyValue.FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
scoreboard.addObjective(objectiveName, criterion, new LiteralText(objectiveName), criterion.getDefaultRenderType());
|
scoreboard.addObjective(objectiveName, criterion, new LiteralText(objectiveName), criterion.getDefaultRenderType());
|
||||||
return LazyValue.TRUE;
|
return LazyValue.TRUE;
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ import java.util.List;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import com.google.gson.stream.JsonReader;
|
||||||
|
|
||||||
public class FileModule extends Module
|
public class FileModule extends Module
|
||||||
{
|
{
|
||||||
private String name;
|
private String name;
|
||||||
@@ -137,11 +141,11 @@ public class FileModule extends Module
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean appendText(File filePath, boolean addNewLines, List<String> data)
|
public static boolean appendText(Path filePath, boolean addNewLines, List<String> data)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
OutputStream out = Files.newOutputStream(filePath.toPath(), StandardOpenOption.APPEND, StandardOpenOption.CREATE);
|
OutputStream out = Files.newOutputStream(filePath, StandardOpenOption.APPEND, StandardOpenOption.CREATE);
|
||||||
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8)))
|
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8)))
|
||||||
{
|
{
|
||||||
for (String line: data)
|
for (String line: data)
|
||||||
@@ -159,9 +163,9 @@ public class FileModule extends Module
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static List<String> listFileContent(File filePath)
|
public static List<String> listFileContent(Path filePath)
|
||||||
{
|
{
|
||||||
try (BufferedReader reader = Files.newBufferedReader(filePath.toPath(), StandardCharsets.UTF_8)) {
|
try (BufferedReader reader = Files.newBufferedReader(filePath, StandardCharsets.UTF_8)) {
|
||||||
List<String> result = new ArrayList<>();
|
List<String> result = new ArrayList<>();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
String line = reader.readLine();
|
String line = reader.readLine();
|
||||||
@@ -176,6 +180,18 @@ public class FileModule extends Module
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static JsonElement readJsonContent(Path filePath)
|
||||||
|
{
|
||||||
|
try (BufferedReader reader = Files.newBufferedReader(filePath, StandardCharsets.UTF_8))
|
||||||
|
{
|
||||||
|
return new JsonParser().parse(new JsonReader(reader));
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static Stream<Path> listFiles(Path dir, String ext)
|
public static Stream<Path> listFiles(Path dir, String ext)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,9 +5,13 @@ import net.minecraft.nbt.Tag;
|
|||||||
import net.minecraft.util.WorldSavePath;
|
import net.minecraft.util.WorldSavePath;
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public abstract class Module
|
public abstract class Module
|
||||||
@@ -16,6 +20,13 @@ public abstract class Module
|
|||||||
public abstract String getCode();
|
public abstract String getCode();
|
||||||
public abstract boolean isLibrary();
|
public abstract boolean isLibrary();
|
||||||
public final static Object writeIOSync = new Object();
|
public final static Object writeIOSync = new Object();
|
||||||
|
public final static Map<String, String> supportedTypes = ImmutableMap.of(
|
||||||
|
"raw", ".txt",
|
||||||
|
"text", ".txt",
|
||||||
|
"nbt", ".nbt",
|
||||||
|
"json", ".json",
|
||||||
|
"folder", "folder"
|
||||||
|
);
|
||||||
|
|
||||||
private static String getDescriptor(Module module, String file, boolean isShared)
|
private static String getDescriptor(Module module, String file, boolean isShared)
|
||||||
{
|
{
|
||||||
@@ -32,7 +43,7 @@ public abstract class Module
|
|||||||
|
|
||||||
public static Tag getData(Module module, String file, boolean isShared)
|
public static Tag getData(Module module, String file, boolean isShared)
|
||||||
{
|
{
|
||||||
Path dataFile = resolveResource(module, file, "nbt", isShared);
|
Path dataFile = resolveResource(module, file, ".nbt", isShared);
|
||||||
if (dataFile == null) return null;
|
if (dataFile == null) return null;
|
||||||
if (!Files.exists(dataFile) || !(dataFile.toFile().isFile())) return null;
|
if (!Files.exists(dataFile) || !(dataFile.toFile().isFile())) return null;
|
||||||
synchronized (writeIOSync) { return FileModule.read(dataFile.toFile()); }
|
synchronized (writeIOSync) { return FileModule.read(dataFile.toFile()); }
|
||||||
@@ -40,7 +51,7 @@ public abstract class Module
|
|||||||
|
|
||||||
public static boolean saveData(Module module, String file, Tag globalState, boolean isShared)
|
public static boolean saveData(Module module, String file, Tag globalState, boolean isShared)
|
||||||
{
|
{
|
||||||
Path dataFile = resolveResource(module, file, "nbt", isShared);
|
Path dataFile = resolveResource(module, file, ".nbt", isShared);
|
||||||
if (dataFile == null) return false;
|
if (dataFile == null) return false;
|
||||||
if (!Files.exists(dataFile.getParent()) && !dataFile.toFile().getParentFile().mkdirs()) return false;
|
if (!Files.exists(dataFile.getParent()) && !dataFile.toFile().getParentFile().mkdirs()) return false;
|
||||||
synchronized (writeIOSync) { return FileModule.write(globalState, dataFile.toFile()); }
|
synchronized (writeIOSync) { return FileModule.write(globalState, dataFile.toFile()); }
|
||||||
@@ -48,30 +59,38 @@ public abstract class Module
|
|||||||
|
|
||||||
public static boolean appendToTextFile(Module module, String resourceName, String type, boolean isShared, List<String> message)
|
public static boolean appendToTextFile(Module module, String resourceName, String type, boolean isShared, List<String> message)
|
||||||
{
|
{
|
||||||
Path dataFile = resolveResource(module, resourceName, "txt", isShared);
|
Path dataFile = resolveResource(module, resourceName, supportedTypes.get(type), isShared);
|
||||||
if (dataFile == null) return false;
|
if (dataFile == null) return false;
|
||||||
if (!Files.exists(dataFile.getParent()) && !dataFile.toFile().getParentFile().mkdirs()) return false;
|
if (!Files.exists(dataFile.getParent()) && !dataFile.toFile().getParentFile().mkdirs()) return false;
|
||||||
synchronized (writeIOSync) { return FileModule.appendText(dataFile.toFile(), type.equals("text"), message); }
|
synchronized (writeIOSync) { return FileModule.appendText(dataFile, type.equals("text"), message); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean dropExistingFile(Module module, String resourceName, String ext, boolean isShared)
|
public static boolean dropExistingFile(Module module, String resourceName, String type, boolean isShared)
|
||||||
{
|
{
|
||||||
Path dataFile = resolveResource(module, resourceName, ext, isShared);
|
Path dataFile = resolveResource(module, resourceName, supportedTypes.get(type), isShared);
|
||||||
if (dataFile == null) return false;
|
if (dataFile == null) return false;
|
||||||
synchronized (writeIOSync) { return dataFile.toFile().delete(); }
|
synchronized (writeIOSync) { return dataFile.toFile().delete(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<String> listFile(Module module, String resourceName, String ext, boolean isShared)
|
public static List<String> listFile(Module module, String resourceName, String type, boolean isShared)
|
||||||
{
|
{
|
||||||
Path dataFile = resolveResource(module, resourceName, ext, isShared);
|
Path dataFile = resolveResource(module, resourceName, supportedTypes.get(type), isShared);
|
||||||
if (dataFile == null) return null;
|
if (dataFile == null) return null;
|
||||||
if (!dataFile.toFile().exists()) return null;
|
if (!dataFile.toFile().exists()) return null;
|
||||||
synchronized (writeIOSync) { return FileModule.listFileContent(dataFile.toFile()); }
|
synchronized (writeIOSync) { return FileModule.listFileContent(dataFile); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JsonElement readJsonFile(Module module, String resourceName, String type, boolean isShared) {
|
||||||
|
Path dataFile = resolveResource(module, resourceName, supportedTypes.get(type), isShared);
|
||||||
|
if (dataFile == null) return null;
|
||||||
|
if (!dataFile.toFile().exists()) return null;
|
||||||
|
synchronized (writeIOSync) { return FileModule.readJsonContent(dataFile); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Stream<String> listFolder(Module module, String resourceName, String ext, boolean isShared)
|
public static Stream<String> listFolder(Module module, String resourceName, String type, boolean isShared)
|
||||||
{
|
{
|
||||||
Path dir = resolveResource(module, resourceName, null, isShared);
|
Path dir = resolveResource(module, resourceName, null, isShared);
|
||||||
|
String ext = supportedTypes.get(type);
|
||||||
if (dir == null) return null;
|
if (dir == null) return null;
|
||||||
if (!Files.exists(dir)) return null;
|
if (!Files.exists(dir)) return null;
|
||||||
Stream<Path> result;
|
Stream<Path> result;
|
||||||
@@ -87,7 +106,7 @@ public abstract class Module
|
|||||||
private static Path resolveResource(Module module, String resourceName, String ext, boolean isShared)
|
private static Path resolveResource(Module module, String resourceName, String ext, boolean isShared)
|
||||||
{
|
{
|
||||||
if (!isShared && (module == null || module.getName() == null)) return null;
|
if (!isShared && (module == null || module.getName() == null)) return null;
|
||||||
return CarpetServer.minecraft_server.getSavePath(WorldSavePath.ROOT).resolve("scripts/"+getDescriptor(module, resourceName, isShared)+(ext==null?"":"."+ext));
|
return CarpetServer.minecraft_server.getSavePath(WorldSavePath.ROOT).resolve("scripts/"+getDescriptor(module, resourceName, isShared)+(ext==null?"":ext));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -315,13 +315,13 @@ public abstract class CommandArgument
|
|||||||
public static CommandArgument buildFromConfig(String suffix, Map<String, Value> config, CarpetScriptHost host)
|
public static CommandArgument buildFromConfig(String suffix, Map<String, Value> config, CarpetScriptHost host)
|
||||||
{
|
{
|
||||||
if (!config.containsKey("type"))
|
if (!config.containsKey("type"))
|
||||||
throw new InternalExpressionException("Custom types should at least specify the type");
|
throw new InternalExpressionException("Custom type "+suffix+" should at least specify the type");
|
||||||
String baseType = config.get("type").getString();
|
String baseType = config.get("type").getString();
|
||||||
if (!builtIns.containsKey(baseType))
|
if (!builtIns.containsKey(baseType))
|
||||||
throw new InternalExpressionException("Unknown base type: "+baseType);
|
throw new InternalExpressionException("Unknown base type "+baseType+" for custom type "+suffix);
|
||||||
CommandArgument variant = builtIns.get(baseType).factory().get();
|
CommandArgument variant = builtIns.get(baseType).factory().get();
|
||||||
variant.configure(config, host);
|
|
||||||
variant.suffix = suffix;
|
variant.suffix = suffix;
|
||||||
|
variant.configure(config, host);
|
||||||
return variant;
|
return variant;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,9 +334,9 @@ public abstract class CommandArgument
|
|||||||
}
|
}
|
||||||
if (config.containsKey("suggest"))
|
if (config.containsKey("suggest"))
|
||||||
{
|
{
|
||||||
if (config.containsKey("suggester")) throw new InternalExpressionException("Attempted to provide 'suggest' list while 'suggester' is present");
|
if (config.containsKey("suggester")) throw new InternalExpressionException("Attempted to provide 'suggest' list while 'suggester' is present"+" for custom type "+suffix);
|
||||||
Value suggestionValue = config.get("suggest");
|
Value suggestionValue = config.get("suggest");
|
||||||
if (!(suggestionValue instanceof ListValue)) throw new InternalExpressionException("Argument suggestions needs to be a list");
|
if (!(suggestionValue instanceof ListValue)) throw new InternalExpressionException("Argument suggestions needs to be a list"+" for custom type "+suffix);
|
||||||
examples = ((ListValue) suggestionValue).getItems().stream()
|
examples = ((ListValue) suggestionValue).getItems().stream()
|
||||||
.map(Value::getString)
|
.map(Value::getString)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
@@ -378,7 +378,7 @@ public abstract class CommandArgument
|
|||||||
args.add(MapValue.wrap(params));
|
args.add(MapValue.wrap(params));
|
||||||
args.addAll(customSuggester.args);
|
args.addAll(customSuggester.args);
|
||||||
Value response = host.handleCommand(context.getSource(), customSuggester.function, args);
|
Value response = host.handleCommand(context.getSource(), customSuggester.function, args);
|
||||||
if (!(response instanceof ListValue)) throw error("Custom suggester should return a list of options");
|
if (!(response instanceof ListValue)) throw error("Custom suggester should return a list of options"+" for custom type "+suffix);
|
||||||
return ((ListValue) response).getItems().stream().map(Value::getString).collect(Collectors.toList());
|
return ((ListValue) response).getItems().stream().map(Value::getString).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
if (needsMatching) return examples;
|
if (needsMatching) return examples;
|
||||||
@@ -426,7 +426,7 @@ public abstract class CommandArgument
|
|||||||
if (!caseSensitive) choseValue = choseValue.toLowerCase(Locale.ROOT);
|
if (!caseSensitive) choseValue = choseValue.toLowerCase(Locale.ROOT);
|
||||||
if (!validOptions.isEmpty() && !validOptions.contains(choseValue))
|
if (!validOptions.isEmpty() && !validOptions.contains(choseValue))
|
||||||
{
|
{
|
||||||
throw new SimpleCommandExceptionType(new LiteralText("Incorrect value for "+param+": "+choseValue)).create();
|
throw new SimpleCommandExceptionType(new LiteralText("Incorrect value for "+param+": "+choseValue+" for custom type "+suffix)).create();
|
||||||
}
|
}
|
||||||
return StringValue.of(choseValue);
|
return StringValue.of(choseValue);
|
||||||
}
|
}
|
||||||
@@ -438,7 +438,7 @@ public abstract class CommandArgument
|
|||||||
if (config.containsKey("options"))
|
if (config.containsKey("options"))
|
||||||
{
|
{
|
||||||
Value optionsValue = config.get("options");
|
Value optionsValue = config.get("options");
|
||||||
if (!(optionsValue instanceof ListValue)) throw new InternalExpressionException("Custom string type requires options passed as a list");
|
if (!(optionsValue instanceof ListValue)) throw new InternalExpressionException("Custom string type requires options passed as a list"+" for custom type "+suffix);
|
||||||
validOptions = ((ListValue) optionsValue).getItems().stream()
|
validOptions = ((ListValue) optionsValue).getItems().stream()
|
||||||
.map(v -> caseSensitive?v.getString():(v.getString().toLowerCase(Locale.ROOT)))
|
.map(v -> caseSensitive?v.getString():(v.getString().toLowerCase(Locale.ROOT)))
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
@@ -577,7 +577,7 @@ public abstract class CommandArgument
|
|||||||
if (!single) return ListValue.wrap(founds.stream().map(EntityValue::new).collect(Collectors.toList()));
|
if (!single) return ListValue.wrap(founds.stream().map(EntityValue::new).collect(Collectors.toList()));
|
||||||
if (founds.size() == 0) return Value.NULL;
|
if (founds.size() == 0) return Value.NULL;
|
||||||
if (founds.size() == 1) return new EntityValue(founds.iterator().next());
|
if (founds.size() == 1) return new EntityValue(founds.iterator().next());
|
||||||
throw new SimpleCommandExceptionType(new LiteralText("Multiple entities returned while only one was requested")).create();
|
throw new SimpleCommandExceptionType(new LiteralText("Multiple entities returned while only one was requested"+" for custom type "+suffix)).create();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -618,7 +618,7 @@ public abstract class CommandArgument
|
|||||||
int size = profiles.size();
|
int size = profiles.size();
|
||||||
if (size == 0) return Value.NULL;
|
if (size == 0) return Value.NULL;
|
||||||
if (size == 1) return StringValue.of(profiles.iterator().next().getName());
|
if (size == 1) return StringValue.of(profiles.iterator().next().getName());
|
||||||
throw new SimpleCommandExceptionType(new LiteralText("Multiple game profiles returned while only one was requested")).create();
|
throw new SimpleCommandExceptionType(new LiteralText("Multiple game profiles returned while only one was requested"+" for custom type "+suffix)).create();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -659,7 +659,7 @@ public abstract class CommandArgument
|
|||||||
int size = holders.size();
|
int size = holders.size();
|
||||||
if (size == 0) return Value.NULL;
|
if (size == 0) return Value.NULL;
|
||||||
if (size == 1) return StringValue.of(holders.iterator().next());
|
if (size == 1) return StringValue.of(holders.iterator().next());
|
||||||
throw new SimpleCommandExceptionType(new LiteralText("Multiple score holders returned while only one was requested")).create();
|
throw new SimpleCommandExceptionType(new LiteralText("Multiple score holders returned while only one was requested"+" for custom type "+suffix)).create();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -734,7 +734,7 @@ public abstract class CommandArgument
|
|||||||
Identifier choseValue = IdentifierArgumentType.getIdentifier(context, param);
|
Identifier choseValue = IdentifierArgumentType.getIdentifier(context, param);
|
||||||
if (!validOptions.isEmpty() && !validOptions.contains(choseValue))
|
if (!validOptions.isEmpty() && !validOptions.contains(choseValue))
|
||||||
{
|
{
|
||||||
throw new SimpleCommandExceptionType(new LiteralText("Incorrect value for "+param+": "+choseValue)).create();
|
throw new SimpleCommandExceptionType(new LiteralText("Incorrect value for "+param+": "+choseValue+" for custom type "+suffix)).create();
|
||||||
}
|
}
|
||||||
return ValueConversions.of(choseValue);
|
return ValueConversions.of(choseValue);
|
||||||
}
|
}
|
||||||
@@ -752,7 +752,7 @@ public abstract class CommandArgument
|
|||||||
if (config.containsKey("options"))
|
if (config.containsKey("options"))
|
||||||
{
|
{
|
||||||
Value optionsValue = config.get("options");
|
Value optionsValue = config.get("options");
|
||||||
if (!(optionsValue instanceof ListValue)) throw new InternalExpressionException("Custom sting type requires options passed as a list");
|
if (!(optionsValue instanceof ListValue)) throw new InternalExpressionException("Custom sting type requires options passed as a list"+" for custom type "+suffix);
|
||||||
validOptions = ((ListValue) optionsValue).getItems().stream().map(v -> new Identifier(v.getString())).collect(Collectors.toSet());
|
validOptions = ((ListValue) optionsValue).getItems().stream().map(v -> new Identifier(v.getString())).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -799,7 +799,7 @@ public abstract class CommandArgument
|
|||||||
{
|
{
|
||||||
max = NumericValue.asNumber(config.get("max"), "max").getDouble();
|
max = NumericValue.asNumber(config.get("max"), "max").getDouble();
|
||||||
}
|
}
|
||||||
if (max != null && min == null) throw new InternalExpressionException("Double types cannot be only upper-bounded");
|
if (max != null && min == null) throw new InternalExpressionException("Double types cannot be only upper-bounded"+" for custom type "+suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -850,7 +850,7 @@ public abstract class CommandArgument
|
|||||||
{
|
{
|
||||||
max = NumericValue.asNumber(config.get("max"), "max").getLong();
|
max = NumericValue.asNumber(config.get("max"), "max").getLong();
|
||||||
}
|
}
|
||||||
if (max != null && min == null) throw new InternalExpressionException("Double types cannot be only upper-bounded");
|
if (max != null && min == null) throw new InternalExpressionException("Double types cannot be only upper-bounded"+" for custom type "+suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -923,7 +923,7 @@ public abstract class CommandArgument
|
|||||||
int slot = ItemSlotArgumentType.getItemSlot(context, param);
|
int slot = ItemSlotArgumentType.getItemSlot(context, param);
|
||||||
if (restrict != null && !RESTRICTED_CONTAINERS.get(restrict).getLeft().contains(slot))
|
if (restrict != null && !RESTRICTED_CONTAINERS.get(restrict).getLeft().contains(slot))
|
||||||
{
|
{
|
||||||
throw new SimpleCommandExceptionType(new LiteralText("Incorrect slot restricted to "+restrict)).create();
|
throw new SimpleCommandExceptionType(new LiteralText("Incorrect slot restricted to "+restrict+" for custom type "+suffix)).create();
|
||||||
}
|
}
|
||||||
return ValueConversions.ofVanillaSlotResult(slot);
|
return ValueConversions.ofVanillaSlotResult(slot);
|
||||||
}
|
}
|
||||||
@@ -937,7 +937,7 @@ public abstract class CommandArgument
|
|||||||
restrict = config.get("restrict").getString().toLowerCase(Locale.ROOT);
|
restrict = config.get("restrict").getString().toLowerCase(Locale.ROOT);
|
||||||
needsMatching = true;
|
needsMatching = true;
|
||||||
if (!RESTRICTED_CONTAINERS.containsKey(restrict))
|
if (!RESTRICTED_CONTAINERS.containsKey(restrict))
|
||||||
throw new InternalExpressionException("Incorrect slot restriction: "+restrict);
|
throw new InternalExpressionException("Incorrect slot restriction "+restrict+" for custom type "+suffix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ public class DataStructures {
|
|||||||
throw new InternalExpressionException("'slice' takes 2 or 3 arguments");
|
throw new InternalExpressionException("'slice' takes 2 or 3 arguments");
|
||||||
Value hwat = lv.get(0);
|
Value hwat = lv.get(0);
|
||||||
long from = NumericValue.asNumber(lv.get(1)).getLong();
|
long from = NumericValue.asNumber(lv.get(1)).getLong();
|
||||||
long to = -1;
|
Long to = null;
|
||||||
if (lv.size()== 3)
|
if (lv.size()== 3)
|
||||||
to = NumericValue.asNumber(lv.get(2)).getLong();
|
to = NumericValue.asNumber(lv.get(2)).getLong();
|
||||||
return hwat.slice(from, to);
|
return hwat.slice(from, to);
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package carpet.script.utils;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonDeserializationContext;
|
||||||
|
import com.google.gson.JsonDeserializer;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
|
import com.google.gson.JsonPrimitive;
|
||||||
|
|
||||||
|
import carpet.script.value.ListValue;
|
||||||
|
import carpet.script.value.MapValue;
|
||||||
|
import carpet.script.value.NumericValue;
|
||||||
|
import carpet.script.value.StringValue;
|
||||||
|
import carpet.script.value.Value;
|
||||||
|
|
||||||
|
public class ScarpetJsonDeserializer implements JsonDeserializer<Value>{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Value deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||||
|
throws JsonParseException {
|
||||||
|
return parseElement(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Value parseElement(JsonElement element) throws JsonParseException {
|
||||||
|
if (element.isJsonObject())
|
||||||
|
{
|
||||||
|
return parseMap(element.getAsJsonObject());
|
||||||
|
}
|
||||||
|
else if (element.isJsonArray())
|
||||||
|
{
|
||||||
|
return parseList(element.getAsJsonArray());
|
||||||
|
}
|
||||||
|
else if (element.isJsonPrimitive())
|
||||||
|
{
|
||||||
|
return parsePrimitive(element.getAsJsonPrimitive());
|
||||||
|
}
|
||||||
|
return Value.NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Value parseMap(JsonObject jsonMap) throws JsonParseException {
|
||||||
|
Map<Value, Value> map = new HashMap<Value, Value>();
|
||||||
|
jsonMap.entrySet().forEach(entry -> {
|
||||||
|
map.put(new StringValue(entry.getKey()), parseElement(entry.getValue()));
|
||||||
|
});
|
||||||
|
return MapValue.wrap(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Value parseList(JsonArray jsonList) throws JsonParseException {
|
||||||
|
List<Value> list = new ArrayList<Value>();
|
||||||
|
jsonList.forEach(elem -> {
|
||||||
|
list.add(parseElement(elem));
|
||||||
|
});
|
||||||
|
return new ListValue(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Value parsePrimitive(JsonPrimitive primitive) throws JsonParseException {
|
||||||
|
if (primitive.isString())
|
||||||
|
{
|
||||||
|
return new StringValue(primitive.getAsString());
|
||||||
|
}
|
||||||
|
else if (primitive.isBoolean())
|
||||||
|
{
|
||||||
|
return primitive.getAsBoolean() ? Value.TRUE : Value.FALSE;
|
||||||
|
}
|
||||||
|
else if (primitive.isNumber())
|
||||||
|
{
|
||||||
|
return NumericValue.of(primitive.getAsNumber());
|
||||||
|
}
|
||||||
|
return Value.NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -168,6 +168,15 @@ public class ShapesRenderer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void renewShapes()
|
||||||
|
{
|
||||||
|
synchronized (shapes)
|
||||||
|
{
|
||||||
|
shapes.values().forEach(el -> el.values().forEach(shape -> {
|
||||||
|
shape.expiryTick++;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public abstract static class RenderedShape<T extends ShapeDispatcher.ExpiringShape>
|
public abstract static class RenderedShape<T extends ShapeDispatcher.ExpiringShape>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import carpet.settings.ParsedRule;
|
|||||||
import carpet.settings.SettingsManager;
|
import carpet.settings.SettingsManager;
|
||||||
import com.sun.management.OperatingSystemMXBean;
|
import com.sun.management.OperatingSystemMXBean;
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
import net.minecraft.SharedConstants;
|
||||||
import net.minecraft.util.WorldSavePath;
|
import net.minecraft.util.WorldSavePath;
|
||||||
import net.minecraft.world.GameRules;
|
import net.minecraft.world.GameRules;
|
||||||
|
|
||||||
@@ -56,6 +57,7 @@ public class SystemInfo {
|
|||||||
put("game_view_distance", c -> new NumericValue(c.s.getMinecraftServer().getPlayerManager().getViewDistance()));
|
put("game_view_distance", c -> new NumericValue(c.s.getMinecraftServer().getPlayerManager().getViewDistance()));
|
||||||
put("game_mod_name", c -> StringValue.of(c.s.getMinecraftServer().getServerModName()));
|
put("game_mod_name", c -> StringValue.of(c.s.getMinecraftServer().getServerModName()));
|
||||||
put("game_version", c -> StringValue.of(c.s.getMinecraftServer().getVersion()));
|
put("game_version", c -> StringValue.of(c.s.getMinecraftServer().getVersion()));
|
||||||
|
put("game_data_version", c->NumericValue.of(SharedConstants.getGameVersion().getWorldVersion()));
|
||||||
|
|
||||||
put("server_ip", c -> StringValue.of(c.s.getMinecraftServer().getServerIp()));
|
put("server_ip", c -> StringValue.of(c.s.getMinecraftServer().getServerIp()));
|
||||||
put("server_whitelisted", c -> new NumericValue(c.s.getMinecraftServer().isEnforceWhitelist()));
|
put("server_whitelisted", c -> new NumericValue(c.s.getMinecraftServer().isEnforceWhitelist()));
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import carpet.script.exception.InternalExpressionException;
|
|||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
public abstract class AbstractListValue extends Value
|
public abstract class AbstractListValue extends Value implements Iterable<Value>
|
||||||
{
|
{
|
||||||
public abstract Iterator<Value> iterator();
|
public abstract Iterator<Value> iterator();
|
||||||
public void fatality() { }
|
public void fatality() { }
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import carpet.fakes.LivingEntityInterface;
|
|||||||
import carpet.fakes.MemoryInterface;
|
import carpet.fakes.MemoryInterface;
|
||||||
import carpet.fakes.MobEntityInterface;
|
import carpet.fakes.MobEntityInterface;
|
||||||
import carpet.fakes.HungerManagerInterface;
|
import carpet.fakes.HungerManagerInterface;
|
||||||
|
import carpet.fakes.ServerPlayerEntityInterface;
|
||||||
import carpet.fakes.ServerPlayerInteractionManagerInterface;
|
import carpet.fakes.ServerPlayerInteractionManagerInterface;
|
||||||
import carpet.helpers.Tracer;
|
import carpet.helpers.Tracer;
|
||||||
import carpet.network.ServerNetworkHandler;
|
import carpet.network.ServerNetworkHandler;
|
||||||
@@ -91,7 +92,7 @@ import static carpet.utils.MobAI.genericJump;
|
|||||||
// TODO: decide whether copy(entity) should duplicate entity in the world.
|
// TODO: decide whether copy(entity) should duplicate entity in the world.
|
||||||
public class EntityValue extends Value
|
public class EntityValue extends Value
|
||||||
{
|
{
|
||||||
private final Entity entity;
|
private Entity entity;
|
||||||
|
|
||||||
public EntityValue(Entity e)
|
public EntityValue(Entity e)
|
||||||
{
|
{
|
||||||
@@ -120,6 +121,11 @@ public class EntityValue extends Value
|
|||||||
|
|
||||||
public Entity getEntity()
|
public Entity getEntity()
|
||||||
{
|
{
|
||||||
|
if (entity instanceof ServerPlayerEntity && ((ServerPlayerEntityInterface)entity).isInvalidEntityObject())
|
||||||
|
{
|
||||||
|
ServerPlayerEntity newPlayer = entity.getServer().getPlayerManager().getPlayer(entity.getUuid());
|
||||||
|
if (newPlayer != null) entity = newPlayer;
|
||||||
|
}
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +177,7 @@ public class EntityValue extends Value
|
|||||||
@Override
|
@Override
|
||||||
public String getString()
|
public String getString()
|
||||||
{
|
{
|
||||||
return entity.getName().getString();
|
return getEntity().getName().getString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -185,7 +191,7 @@ public class EntityValue extends Value
|
|||||||
{
|
{
|
||||||
if (v instanceof EntityValue)
|
if (v instanceof EntityValue)
|
||||||
{
|
{
|
||||||
return entity.getEntityId()==((EntityValue) v).entity.getEntityId();
|
return getEntity().getEntityId()==((EntityValue) v).getEntity().getEntityId();
|
||||||
}
|
}
|
||||||
return super.equals((Value)v);
|
return super.equals((Value)v);
|
||||||
}
|
}
|
||||||
@@ -221,7 +227,7 @@ public class EntityValue extends Value
|
|||||||
@Override
|
@Override
|
||||||
public int hashCode()
|
public int hashCode()
|
||||||
{
|
{
|
||||||
return entity.hashCode();
|
return getEntity().hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EntityClassDescriptor getEntityDescriptor(String who, MinecraftServer server)
|
public static EntityClassDescriptor getEntityDescriptor(String who, MinecraftServer server)
|
||||||
@@ -389,7 +395,7 @@ public class EntityValue extends Value
|
|||||||
throw new InternalExpressionException("Unknown entity feature: "+what);
|
throw new InternalExpressionException("Unknown entity feature: "+what);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return featureAccessors.get(what).apply(entity, arg);
|
return featureAccessors.get(what).apply(getEntity(), arg);
|
||||||
}
|
}
|
||||||
catch (NullPointerException npe)
|
catch (NullPointerException npe)
|
||||||
{
|
{
|
||||||
@@ -850,7 +856,7 @@ public class EntityValue extends Value
|
|||||||
throw new InternalExpressionException("Unknown entity action: " + what);
|
throw new InternalExpressionException("Unknown entity action: " + what);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
featureModifiers.get(what).accept(entity, toWhat);
|
featureModifiers.get(what).accept(getEntity(), toWhat);
|
||||||
}
|
}
|
||||||
catch (NullPointerException npe)
|
catch (NullPointerException npe)
|
||||||
{
|
{
|
||||||
@@ -1483,7 +1489,7 @@ public class EntityValue extends Value
|
|||||||
EntityEventsGroup.Event event = EntityEventsGroup.Event.byName.get(eventName);
|
EntityEventsGroup.Event event = EntityEventsGroup.Event.byName.get(eventName);
|
||||||
if (event == null)
|
if (event == null)
|
||||||
throw new InternalExpressionException("Unknown entity event: " + eventName);
|
throw new InternalExpressionException("Unknown entity event: " + eventName);
|
||||||
((EntityInterface)entity).getEventContainer().addEvent(event, cc.host, fun, args);
|
((EntityInterface)getEntity()).getEventContainer().addEvent(event, cc.host, fun, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1492,7 +1498,7 @@ public class EntityValue extends Value
|
|||||||
if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this);
|
if (!force) throw new NBTSerializableValue.IncompatibleTypeException(this);
|
||||||
CompoundTag tag = new CompoundTag();
|
CompoundTag tag = new CompoundTag();
|
||||||
tag.put("Data", getEntity().toTag( new CompoundTag()));
|
tag.put("Data", getEntity().toTag( new CompoundTag()));
|
||||||
tag.put("Name", StringTag.of(Registry.ENTITY_TYPE.getId(entity.getType()).toString()));
|
tag.put("Name", StringTag.of(Registry.ENTITY_TYPE.getId(getEntity().getType()).toString()));
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,7 +133,7 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value slice(long from, long to)
|
public Value slice(long from, Long to)
|
||||||
{
|
{
|
||||||
throw new InternalExpressionException("Cannot slice a function");
|
throw new InternalExpressionException("Cannot slice a function");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,9 +129,9 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value slice(long from, long to)
|
public Value slice(long from, Long to)
|
||||||
{
|
{
|
||||||
if (to < 0) to = Integer.MAX_VALUE;
|
if (to == null || to < 0) to = (long) Integer.MAX_VALUE;
|
||||||
if (from < 0) from = 0;
|
if (from < 0) from = 0;
|
||||||
if (from > to)
|
if (from > to)
|
||||||
return ListValue.of();
|
return ListValue.of();
|
||||||
|
|||||||
@@ -289,27 +289,22 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
items.add(v);
|
items.add(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAtIndex(int index, List<Value> subList)
|
/**
|
||||||
|
* Finds a proper list index >=0 and < len that correspont to the rolling index value of idx
|
||||||
|
*
|
||||||
|
* @param idx
|
||||||
|
* @param len
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static int normalizeIndex(long idx, int len)
|
||||||
{
|
{
|
||||||
int numitems = items.size();
|
if (idx >=0 && idx < len) return (int)idx;
|
||||||
long range = abs(index)/numitems;
|
long range = abs(idx)/len;
|
||||||
index += (range+2)*numitems;
|
idx += (range+2)*len;
|
||||||
index = index % numitems;
|
idx = idx % len;
|
||||||
for (Value v: subList)
|
return (int)idx;
|
||||||
{
|
|
||||||
if (index < numitems)
|
|
||||||
{
|
|
||||||
items.set(index, v);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
items.add(v);
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class ListConstructorValue extends ListValue
|
public static class ListConstructorValue extends ListValue
|
||||||
{
|
{
|
||||||
public ListConstructorValue(Collection<? extends Value> list)
|
public ListConstructorValue(Collection<? extends Value> list)
|
||||||
@@ -339,15 +334,17 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value slice(long from, long to)
|
public Value slice(long fromDesc, Long toDesc)
|
||||||
{
|
{
|
||||||
List<Value> items = getItems();
|
List<Value> items = getItems();
|
||||||
int size = items.size();
|
int size = items.size();
|
||||||
if (to < 0 || to > size) to = size;
|
int from = normalizeIndex(fromDesc, size);
|
||||||
if (from < 0 || from > size) from = size;
|
if (toDesc == null)
|
||||||
|
return new ListValue((Collection<? extends Value>) getItems().subList(from, size));
|
||||||
|
int to = normalizeIndex(toDesc, size);
|
||||||
if (from > to)
|
if (from > to)
|
||||||
return ListValue.of();
|
return ListValue.of();
|
||||||
return new ListValue((Collection<? extends Value>) getItems().subList((int)from, (int) to));
|
return new ListValue((Collection<? extends Value>) getItems().subList(from, to));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -395,10 +392,8 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
return false;
|
return false;
|
||||||
int index = (int)((NumericValue) ind).getLong();
|
int index = (int)((NumericValue) ind).getLong();
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
{
|
{// only for values < 0
|
||||||
long range = abs(index) / numitems;
|
index = normalizeIndex(index, numitems);
|
||||||
index += (range + 2) * numitems;
|
|
||||||
index = index % numitems;
|
|
||||||
}
|
}
|
||||||
if (replace)
|
if (replace)
|
||||||
{
|
{
|
||||||
@@ -424,11 +419,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
public Value get(Value value)
|
public Value get(Value value)
|
||||||
{
|
{
|
||||||
long index = NumericValue.asNumber(value, "'address' to a list index").getLong();
|
long index = NumericValue.asNumber(value, "'address' to a list index").getLong();
|
||||||
int numitems = items.size();
|
return items.get(normalizeIndex(index, items.size()));
|
||||||
long range = abs(index)/numitems;
|
|
||||||
index += (range+2)*numitems;
|
|
||||||
index = index % numitems;
|
|
||||||
return items.get((int)index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -443,11 +434,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
|||||||
{
|
{
|
||||||
if (!(where instanceof NumericValue) || items.isEmpty()) return false;
|
if (!(where instanceof NumericValue) || items.isEmpty()) return false;
|
||||||
long index = ((NumericValue) where).getLong();
|
long index = ((NumericValue) where).getLong();
|
||||||
int numitems = items.size();
|
items.remove(normalizeIndex(index, items.size()));
|
||||||
long range = abs(index)/numitems;
|
|
||||||
index += (range+2)*numitems;
|
|
||||||
index = index % numitems;
|
|
||||||
items.remove((int)index);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value slice(long from, long to)
|
public Value slice(long from, Long to)
|
||||||
{
|
{
|
||||||
throw new InternalExpressionException("Cannot slice a map value");
|
throw new InternalExpressionException("Cannot slice a map value");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import net.minecraft.nbt.Tag;
|
|||||||
|
|
||||||
public class StringValue extends Value
|
public class StringValue extends Value
|
||||||
{
|
{
|
||||||
|
public static Value EMPTY = StringValue.of("");
|
||||||
|
|
||||||
private String str;
|
private String str;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -178,16 +178,15 @@ public abstract class Value implements Comparable<Value>, Cloneable
|
|||||||
return getString().length();
|
return getString().length();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Value slice(long from, long to)
|
public Value slice(long fromDesc, Long toDesc)
|
||||||
{
|
{
|
||||||
String value = this.getString();
|
String value = this.getString();
|
||||||
int size = value.length();
|
int size = value.length();
|
||||||
if (to > size) to = -1;
|
int from = ListValue.normalizeIndex(fromDesc, size);
|
||||||
if (from < 0) from = 0;
|
if (toDesc == null) return new StringValue(value.substring(from));
|
||||||
if (from > size) from = size;
|
int to = ListValue.normalizeIndex(toDesc, size);
|
||||||
if (to>=0)
|
if (from > to) return StringValue.EMPTY;
|
||||||
return new StringValue(value.substring((int)from, (int)to));
|
return new StringValue(value.substring(from, to));
|
||||||
return new StringValue(value.substring((int)from));
|
|
||||||
}
|
}
|
||||||
public double readDoubleNumber()
|
public double readDoubleNumber()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -166,6 +166,8 @@
|
|||||||
"BlockItem_scarpetEventMixin",
|
"BlockItem_scarpetEventMixin",
|
||||||
"PlayerManager_scarpetEventsMixin",
|
"PlayerManager_scarpetEventsMixin",
|
||||||
"PlayerInventory_scarpetEventMixin",
|
"PlayerInventory_scarpetEventMixin",
|
||||||
|
"ScoreboardObjective_scarpetMixin",
|
||||||
|
"Scoreboard_scarpetMixin",
|
||||||
"TradeOutputSlot_scarpetEventMixin",
|
"TradeOutputSlot_scarpetEventMixin",
|
||||||
|
|
||||||
"ChunkTicketManager_scarpetMixin",
|
"ChunkTicketManager_scarpetMixin",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"schemaVersion": 1,
|
"schemaVersion": 1,
|
||||||
"id": "carpet",
|
"id": "carpet",
|
||||||
"version": "1.4.21",
|
"version": "${version}",
|
||||||
|
|
||||||
"name": "Carpet Mod in Fabric",
|
"name": "Carpet Mod in Fabric",
|
||||||
"description": "Carpet made out of fabric",
|
"description": "Carpet made out of fabric",
|
||||||
|
|||||||
Reference in new issue
Block a user