Merge branch 'master' into future

# Conflicts:
#	gradle.properties
#	src/main/java/carpet/script/annotation/AnnotationParser.java
#	src/main/java/carpet/script/utils/BiomeInfo.java
#	src/main/resources/fabric.mod.json
This commit is contained in:
gnembon committed 2022-01-11 23:44:52 +01:00
commit 529a5b358d
38 files changed
+247 -381

No files matched your search

+5 -2
View File
@@ -2483,6 +2483,9 @@ is only effective if you set it at y=0, and affects the entire column of. In the
specific Y coordinate of the biome you want to change, and it affects roughly 4x4x4 area (give or take some random
noise).
This changed again in 1.18. The overworld behaves like the nether now, the biome must be set
for individual y coordinates.
Throws `unknown_biome` if the `biome_name` doesn't exist.
### `update(pos)`
@@ -2675,8 +2678,8 @@ With block, or name, returns the name of the biome in that position, or throws `
Note: Have to pass all 6 of the mentioned noise types and only these noise types for it to evaluate a biome.
With an optional feature, it returns value for the specified attribute for that biome. Available and queryable features include:
* `'top_material'`: unlocalized block representing the top surface material
* `'under_material'`: unlocalized block representing what sits below topsoil
* `'top_material'`: unlocalized block representing the top surface material (1.17.1 and below only)
* `'under_material'`: unlocalized block representing what sits below topsoil (1.17.1 and below only)
* `'category'`: the parent biome this biome is derived from. Possible values include:
`'none'`, `'taiga'`, `'extreme_hills'`, `'jungle'`, `'mesa'`, `'plains'`, `'savanna'`,
`'icy'`, `'the_end'`, `'beach'`, `'forest'`, `'ocean'`, `'desert'`, `'river'`,
+26 -9
View File
@@ -252,6 +252,8 @@ Decorators (listed as extra argument after the component they would affect):
* `'^<format> <text>'` - hover over tooltip text, appearing when hovering with your mouse over the text below.
* `'?<suggestion>` - command suggestion - a message that will be pasted to chat when text below it is clicked.
* `'!<message>'` - a chat message that will be executed when the text below it is clicked.
* `'@<url>'` - a URL that will be opened when the text below it is clicked.
* `'&<text>'` - a text that will be copied to clipboard when the text below it is clicked.
Both suggestions and messages can contain a command, which will be executed as a player that clicks it.
@@ -681,13 +683,13 @@ Fetches the value of a system property or returns all inforation as a map when c
fetch various information, mostly not changing, or only available via low level
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_list` - list of all loaded apps excluding default commandline app
* `app_scope` - scope of the global variables and function. Available options is `player` and `global`
* `app_player` - returns a player list that have app run under them. For `global` apps, the list is always empty
* `app_players` - returns a player list that have app run under them. For `global` apps, the list is always empty
Relevant world related properties
##### Relevant world related properties
* `world_name` - name of the world
* `world_seed` - a numeric seed of the world
* `world_dimensions` - a list of dimensions in the world
@@ -700,9 +702,10 @@ Available options in the scarpet app space:
* `world_top` - Returns current dimensions' topmost Y value where one can place blocks.
* `world_bottom` - Returns current dimensions' bottommost Y value where one can place blocks.
* `world_center` - Returns coordinates of the center of the world with respect of the world border
* `world_size` - Returns size of the world where at this distance from `world_center` world border appears.
* `world_size` - Returns radius of world border for current dimension.
* `world_max_size` - Returns maximum possible radius of world border for current dimension.
*
Relevant gameplay related properties
##### Relevant gameplay related properties
* `game_difficulty` - current difficulty of the game: `'peaceful'`, `'easy'`, `'normal'`, or `'hard'`
* `game_hardcore` - boolean whether the game is in hardcore mode
* `game_storage_format` - format of the world save files, either `'McRegion'` or `'Anvil'`
@@ -713,13 +716,13 @@ Available options in the scarpet app space:
* `game_version` - base version of the game
* `game_target` - target release version
* `game_major_target` - major release target. For 1.12.2, that would be 12
* `game_minor_reease` - minor release target. For 1.12.2, that woudl be 2
* `game_minor_release` - minor release target. For 1.12.2, that would be 2
* `game_protocol` - protocol version number
* `game_pack_version` - datapack version number
* `game_data_version` - data version of the game. Returns an integer, so it can be compared.
* `game_stable` - indicating if its a production release or a snapshot
Server related properties
##### Server related properties
* `server_motd` - the motd of the server visible when joining
* `server_ip` - IP adress of the game hosted
* `server_whitelisted` - boolean indicating whether the access to the server is only for whitelisted players
@@ -734,7 +737,21 @@ list may refer to the previous tick performance. In this case the last entry (ti
tick. For all intent and purpose, `system_info('last_tick_times'):0` should be used as last tick execution time, but
individual tick times may vary greatly, and these need to be taken with the little grain of averaging.
System related properties
##### Source related properties
The source is what is the cause of the code running, with Carpet using it same way as Minecraft commands use to run. Those are used in
some API functions that interact with the game or with commands, and can be manipulated if the execution is caused by an `execute` command, modified
by some functions or ran in non-standard ways. This section provides useful information from these cases (like running from a command
block, right clicking a sign, etc)
* `source_entity` - The entity associated with the execution. This is usually a player (in which case `player()` would get the entity from this),
but it may also be a different entity or `null` if the execution comes from the server console or a command block.
* `source_position` - The position associated with the execution. This is usually the position of the entity, but it may have been manipulated or
it could come from a command block (no entity then). If this call comes from the server console, it will be the world spawn.
* `source_dimension` - The dimension associated with the execution. Execution from the server console provides `overworld` as the dimension.
This can be manipulated by running code inside `in_dimension()`.
* `source_rotation` - The rotation associated with the execution. Usually `[0, 0]` in non-standard situations, the rotation of the entity otherwise.
##### System related properties
* `java_max_memory` - maximum allowed memory accessible by JVM
* `java_allocated_memory` - currently allocated memory by JVM
* `java_used_memory` - currently used memory by JVM
@@ -744,7 +761,7 @@ individual tick times may vary greatly, and these need to be taken with the litt
* `java_system_cpu_load` - current percentage of CPU used by the system
* `java_process_cpu_load` - current percentage of CPU used by JVM
Scarpet related properties
##### Scarpet related properties
* `scarpet_version` - returns the version of the carpet your scarpet comes with.
## NBT Storage
+6 -7
View File
@@ -157,12 +157,11 @@ Throws `unknown_poi` if the provided point of interest doesn't exist
### `set_biome(pos, biome_name, update=true)`
Changes the biome at that block position. if update is specified and false, then chunk will not be refreshed
on the clients. Biome changes can only be send to clients with the entire data from the chunk.
on the clients. Biome changes can only be sent to clients with the entire data from the chunk.
Setting a biome is now (as of 1.16) dimension specific. In the overworld and the end changing the biome
is only effective if you set it at y=0, and affects the entire column of. In the nether - you have to use the
specific Y coordinate of the biome you want to change, and it affects roughly 4x4x4 area (give or take some random
noise).
Be aware that depending on the MC version and dimension settings biome can be set either in a 1x1x256
column or 4x4x4 hyperblock, so for some versions Y will be ignored and for some precision of biome
setting is less than 1x1x1 block.
Throws `unknown_biome` if the `biome_name` doesn't exist.
@@ -356,8 +355,8 @@ With block, or name, returns the name of the biome in that position, or throws `
Note: Have to pass all 6 of the mentioned noise types and only these noise types for it to evaluate a biome.
With an optional feature, it returns value for the specified attribute for that biome. Available and queryable features include:
* `'top_material'`: unlocalized block representing the top surface material
* `'under_material'`: unlocalized block representing what sits below topsoil
* `'top_material'`: unlocalized block representing the top surface material (1.17.1 and below only)
* `'under_material'`: unlocalized block representing what sits below topsoil (1.17.1 and below only)
* `'category'`: the parent biome this biome is derived from. Possible values include:
`'none'`, `'taiga'`, `'extreme_hills'`, `'jungle'`, `'mesa'`, `'plains'`, `'savanna'`,
`'icy'`, `'the_end'`, `'beach'`, `'forest'`, `'ocean'`, `'desert'`, `'river'`,
+10 -4
View File
@@ -202,13 +202,19 @@ List of entities riding the entity.
Entity that `e` rides.
### `query(e, 'scoreboard_tags')` and
### `query(e, 'tags')`(deprecated)
### `(deprecated) query(e, 'tags')`
Deprecated by `query(e, 'scoreboard_tags')`
### `query(e, 'scoreboard_tags')`
List of entity's scoreboard tags.
### `query(e, 'has_scoreboard_tag',tag)` and
### `query(e, 'has_tag',tag)`(deprecated)
### `(deprecated) query(e, 'has_tag',tag)`
Deprecated by `query(e, 'has_scoreboard_tag',tag)`
### `query(e, 'has_scoreboard_tag',tag)`
Boolean, true if the entity is marked with a `tag` scoreboad tag.
+1 -1
View File
@@ -128,7 +128,7 @@ in a list and contain of map-like resources descriptors, looking like
or a relative location in the same folder as the app in question (the relative location directly).
`'target'` points to the path in app data, or shared app data folder. If not specified it will place the app into the main data folder with the name it has.
if `'shared'` is specified and `true`. When re-downloading the app, all resources will be re-downloaded as well.
Currently, app resources are only downloaded when using `/carpet download` command.
Currently, app resources are only downloaded when using `/script download` command.
* `libraries` - list of libraries or apps to be downloaded when installing the app from the app store. It needs to be a list of map-like resource
descriptors, like the above `resources` field.
```
+1 -1
View File
@@ -110,7 +110,7 @@ Or an example to find if a player has specific enchantment on a held axe (either
<pre>
global_get_enchantment(p, ench) -> (
$ for(['main','offhand'],
$ for(['mainhand','offhand'],
$ holds = query(p, 'holds', _);
$ if( holds,
$ [what, count, nbt] = holds;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 105 KiB

+1 -1
View File
@@ -6,7 +6,7 @@ org.gradle.jvmargs=-Xmx1G
# or better: https://modmuss50.me/fabric.html
minecraft_version=1.18
yarn_mappings=1.18+build.1
loader_version=0.12.6
loader_version=0.12.12
fabric_version=0.43.1+1.18
# Mod Properties
@@ -299,6 +299,9 @@ public class PlayerCommand
{
// Force override flying to true for spectator players, or they will fell out of the world.
flying = true;
} else if(mode.isSurvivalLike()){
// Force override flying to false for survival-like players, or they will fly too
flying = false;
}
String playerName = StringArgumentType.getString(context, "player");
if (playerName.length()>maxPlayerLength(source.getServer()))
@@ -51,10 +51,10 @@ public class TickCommand
then(literal("deep").executes( (c)-> setFreeze(c.getSource(), true, true)))).
then(literal("off").executes( (c) -> setFreeze(c.getSource(), false, false)))).
then(literal("step").
executes((c) -> step(1)).
executes((c) -> step(c.getSource(), 1)).
then(argument("ticks", integer(1,72000)).
suggests( (c, b) -> suggestMatching(new String[]{"20"},b)).
executes((c) -> step(getInteger(c,"ticks"))))).
executes((c) -> step(c.getSource(), getInteger(c,"ticks"))))).
then(literal("superHot").executes( (c)-> toggleSuperHot(c.getSource()))).
then(literal("health").
executes( (c) -> healthReport(c.getSource(), 100)).
@@ -130,9 +130,10 @@ public class TickCommand
return setFreeze(source, isDeep, !TickSpeed.isPaused());
}
private static int step(int advance)
private static int step(ServerCommandSource source, int advance)
{
TickSpeed.add_ticks_to_run_in_pause(advance);
Messenger.m(source, "gi Stepping " + advance + " tick" + (advance != 1 ? "s" : ""));
return 1;
}
@@ -1,12 +0,0 @@
package carpet.fakes;
import java.util.Optional;
public interface BiomeEffectsInterface
{
int getCMFogColor();
Optional<Integer> getCMFoliageColor();
int getCMSkyColor();
int getCMWaterColor();
int getCMWaterFogColor();
}
@@ -1,12 +0,0 @@
package carpet.fakes;
import net.minecraft.entity.ai.brain.Memory;
import net.minecraft.entity.ai.brain.MemoryModuleType;
import java.util.Map;
import java.util.Optional;
public interface BrainInterface
{
Map<MemoryModuleType<?>, Optional<? extends Memory<?>>> getMobMemories();
}
@@ -2,6 +2,5 @@ package carpet.fakes;
public interface ItemEntityInterface
{
int getAgeCM();
int getPickupDelayCM();
}
@@ -1,6 +0,0 @@
package carpet.fakes;
public interface MemoryInterface
{
long getScarpetExpiry();
}
@@ -1,53 +0,0 @@
package carpet.mixins;
import carpet.fakes.BiomeEffectsInterface;
import net.minecraft.world.biome.BiomeEffects;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.Optional;
@Mixin(BiomeEffects.class)
public class BiomeEffects_scarpetMixin implements BiomeEffectsInterface
{
@Shadow @Final private int fogColor;
@Shadow @Final private Optional<Integer> foliageColor;
@Shadow @Final private int skyColor;
@Shadow @Final private int waterColor;
@Shadow @Final private int waterFogColor;
@Override
public int getCMFogColor()
{
return fogColor;
}
@Override
public Optional<Integer> getCMFoliageColor()
{
return foliageColor;
}
@Override
public int getCMSkyColor()
{
return skyColor;
}
@Override
public int getCMWaterColor()
{
return waterColor;
}
@Override
public int getCMWaterFogColor()
{
return waterFogColor;
}
}
@@ -1,25 +0,0 @@
package carpet.mixins;
import carpet.fakes.BrainInterface;
import net.minecraft.entity.ai.brain.Brain;
import net.minecraft.entity.ai.brain.Memory;
import net.minecraft.entity.ai.brain.MemoryModuleType;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.Map;
import java.util.Optional;
@Mixin(Brain.class)
public class Brain_Mixin implements BrainInterface
{
@Shadow @Final private Map<MemoryModuleType<?>, Optional<? extends Memory<?>>> memories;
@Override
public Map<MemoryModuleType<?>, Optional<? extends Memory<?>>> getMobMemories()
{
return memories;
}
}
@@ -42,11 +42,6 @@ public abstract class ItemEntityMixin extends Entity implements ItemEntityInterf
}
}
@Override
public int getAgeCM() {
return this.itemAge;
}
@Override
public int getPickupDelayCM() {
return this.pickupDelay;
@@ -105,7 +100,7 @@ public abstract class ItemEntityMixin extends Entity implements ItemEntityInterf
self.setStack(selfStack);
this.pickupDelay = Math.max(((ItemEntityInterface)other).getPickupDelayCM(), this.pickupDelay);
this.itemAge = Math.min(((ItemEntityInterface)other).getAgeCM(), this.itemAge);
this.itemAge = Math.min(other.getItemAge(), this.itemAge);
otherStack.decrement(amount);
if (otherStack.isEmpty())
@@ -1,18 +0,0 @@
package carpet.mixins;
import carpet.fakes.MemoryInterface;
import net.minecraft.entity.ai.brain.Memory;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(Memory.class)
public class Memory_scarpetMixin implements MemoryInterface
{
@Shadow private long expiry;
@Override
public long getScarpetExpiry()
{
return expiry;
}
}
@@ -1,7 +1,5 @@
package carpet.mixins;
import carpet.fakes.BrainInterface;
import carpet.fakes.MemoryInterface;
import carpet.helpers.ParticleDisplay;
import carpet.utils.Messenger;
import carpet.utils.MobAI;
@@ -65,14 +63,14 @@ public abstract class VillagerEntity_aiMixin extends MerchantEntity
if (MobAI.isTracking(this, MobAI.TrackingType.IRON_GOLEM_SPAWNING))
{
long time;
Optional<? extends Memory<?>> last_seen = ((BrainInterface)this.brain).getMobMemories().get(MemoryModuleType.GOLEM_DETECTED_RECENTLY);
Optional<? extends Memory<?>> last_seen = this.brain.getMemories().get(MemoryModuleType.GOLEM_DETECTED_RECENTLY);
if (!last_seen.isPresent())
{
time = 0;
}
else
{
time = ((MemoryInterface)last_seen.get()).getScarpetExpiry();
time = last_seen.get().getExpiry();
}
boolean recentlySeen = time > 0;
Optional<Long> optional_11 = this.brain.getOptionalMemory(MemoryModuleType.LAST_SLEPT);
@@ -91,7 +91,7 @@ public class CarpetExpression
public Value scriptRunCommand(ScriptHost host, BlockPos pos)
{
if (CarpetServer.scriptServer.stopAll)
throw new CarpetExpressionException("SCRIPTING PAUSED", null);
throw new CarpetExpressionException("SCRIPTING PAUSED (unpause with /script resume)", null);
try
{
Context context = new CarpetContext(host, source, origin).
@@ -13,6 +13,7 @@ import carpet.script.exception.ExpressionException;
import carpet.script.exception.IntegrityException;
import carpet.script.exception.InternalExpressionException;
import carpet.script.exception.InvalidCallbackException;
import carpet.script.exception.LoadException;
import carpet.script.utils.AppStoreManager;
import carpet.script.value.EntityValue;
import carpet.script.value.FunctionValue;
@@ -37,6 +38,7 @@ import net.fabricmc.loader.api.ModContainer;
import net.fabricmc.loader.api.SemanticVersion;
import net.fabricmc.loader.api.Version;
import net.fabricmc.loader.api.VersionParsingException;
import net.fabricmc.loader.api.metadata.version.VersionPredicate;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.nbt.NbtElement;
@@ -60,7 +62,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -119,8 +120,7 @@ public class CarpetScriptHost extends ScriptHost
String code = module.getCode();
if (code == null)
{
Messenger.m(source, "r Unable to load "+module.getName()+" app - code not found");
return null;
throw new LoadException("Code not found");
}
host.setChatErrorSnooper(source);
CarpetExpression ex = new CarpetExpression(host.main, code, source, new BlockPos(0, 0, 0));
@@ -131,13 +131,12 @@ public class CarpetScriptHost extends ScriptHost
catch (CarpetExpressionException e)
{
host.handleErrorWithStack("Error while evaluating expression", e);
host.resetErrorSnooper();
return null;
throw new LoadException();
}
catch (ArithmeticException ae)
catch (ArithmeticException ae) // is this branch ever reached? Seems like arithmetic exceptions are converted to CEEs earlier
{
host.handleErrorWithStack("Math doesn't compute", ae);
return null;
throw new LoadException();
}
catch (StackOverflowError soe)
{
@@ -314,7 +313,7 @@ public class CarpetScriptHost extends ScriptHost
{
Value reqResult = callNow((FunctionValue) loadRequirements, Collections.emptyList());
if (reqResult.getBoolean()) // != false or null
throw new InternalExpressionException(reqResult.getString());
throw new LoadException(reqResult.getString());
}
else
{
@@ -422,20 +421,6 @@ public class CarpetScriptHost extends ScriptHost
return addLegacyCommand(notifier);
}
// Prefixes based on FLoader's SemanticVersionPredicateParser's class prefixes under Apache 2.0, since that's not public API
private static final Map<String, BiPredicate<SemanticVersion, SemanticVersion>> VERSION_PREFIXES = new HashMap<String, BiPredicate<SemanticVersion, SemanticVersion>>() {{
put(">=", (target, source) -> source.compareTo(target) >= 0);
put("<=", (target, source) -> source.compareTo(target) <= 0);
put(">", (target, source) -> source.compareTo(target) > 0);
put("<", (target, source) -> source.compareTo(target) < 0);
put("=", (target, source) -> source.compareTo(target) == 0);
put("~", (target, source) -> source.compareTo(target) >= 0
&& source.getVersionComponent(0) == target.getVersionComponent(0)
&& source.getVersionComponent(1) == target.getVersionComponent(1));
put("^", (target, source) -> source.compareTo(target) >= 0
&& source.getVersionComponent(0) == target.getVersionComponent(0));
}};
public void checkModVersionRequirements(Value reqs) {
if (reqs == null)
return;
@@ -446,58 +431,25 @@ public class CarpetScriptHost extends ScriptHost
Map<Value, Value> requirements = ((MapValue)reqs).getMap();
for (Entry<Value, Value> requirement : requirements.entrySet())
{
boolean successful = false;
String requiredModId = requirement.getKey().getString();
String requirementString = requirement.getValue().getString();
String stringPredicate = requirement.getValue().getString();
VersionPredicate predicate;
try {
predicate = VersionPredicate.parse(stringPredicate);
} catch (VersionParsingException e) {
throw new InternalExpressionException("Failed to parse version conditions for '" + requiredModId + "' in 'requires': " + e.getMessage());
}
ModContainer mod = FabricLoader.getInstance().getModContainer(requiredModId).orElse(null);
if (mod != null)
{
if (requirementString.equals("*"))
continue;
Version presentVersion = mod.getMetadata().getVersion();
BiPredicate<SemanticVersion, SemanticVersion> tester = null;
String remainingRequirementString = requirementString;
for (Entry<String, BiPredicate<SemanticVersion, SemanticVersion>> s : VERSION_PREFIXES.entrySet())
{
if (requirementString.startsWith(s.getKey()))
{
tester = s.getValue();
remainingRequirementString = requirementString.substring(s.getKey().length());
}
}
if (tester == null)
tester = VERSION_PREFIXES.get("=");
if (presentVersion instanceof SemanticVersion)
{
SemanticVersion requiredVersion = null;
try {
requiredVersion = SemanticVersion.parse(remainingRequirementString);
}
catch (VersionParsingException e)
{
throw new InternalExpressionException("Failed to parse semantic version for '" + requiredModId + "' in 'requires': " + e.getMessage());
}
if (tester.test(requiredVersion, (SemanticVersion) presentVersion))
successful = true;
}
else
{
if (FabricLoader.getInstance().isDevelopmentEnvironment())
successful = true; // Autoversioning breaks semver in dev (loads as ${version})
else
{
if (!(tester == VERSION_PREFIXES.get("=")))
throw new InternalExpressionException("Mod '"+requiredModId+"' doesn't use semversion, thus can only check version equality");
if (presentVersion.getFriendlyString().equals(remainingRequirementString))
successful = true;
}
if (predicate.test(presentVersion) || (FabricLoader.getInstance().isDevelopmentEnvironment() && !(presentVersion instanceof SemanticVersion)))
{ // in a dev env, mod version is usually replaced with ${version}, and that isn't semantic
continue;
}
}
if (!successful)
{
throw new InternalExpressionException(getName()+" requires " + requiredModId + " version " + requirementString + " in order to load");
}
throw new LoadException(String.format("%s requires a version of mod '%s' matching '%s', which is missing!", getName(), requiredModId, stringPredicate));
}
}
@@ -732,10 +684,10 @@ public class CarpetScriptHost extends ScriptHost
public Value callLegacy(ServerCommandSource source, String call, List<Integer> coords, String arg)
{
if (CarpetServer.scriptServer.stopAll)
throw new CarpetExpressionException("SCARPET PAUSED", null);
throw new CarpetExpressionException("SCARPET PAUSED (unpause with /script resume)", null);
FunctionValue function = getFunction(call);
if (function == null)
throw new CarpetExpressionException("UNDEFINED", null);
throw new CarpetExpressionException("Couldn't find function '" + call + "' in app '" + this.getName() + "'", null);
List<LazyValue> argv = new ArrayList<>();
if (coords != null)
for (Integer i: coords)
@@ -832,7 +784,7 @@ public class CarpetScriptHost extends ScriptHost
public Value call(ServerCommandSource source, FunctionValue function, List<Value> argv)
{
if (CarpetServer.scriptServer.stopAll)
throw new CarpetExpressionException("SCARPET PAUSED", null);
throw new CarpetExpressionException("SCARPET PAUSED (unpause with /script resume)", null);
List<String> args = function.getArguments();
if (argv.size() != args.size())
@@ -13,6 +13,7 @@ import carpet.CarpetServer;
import carpet.script.bundled.FileModule;
import carpet.script.bundled.Module;
import carpet.script.exception.ExpressionException;
import carpet.script.exception.LoadException;
import carpet.script.language.Arithmetic;
import carpet.script.language.ControlFlow;
import carpet.script.language.DataStructures;
@@ -256,10 +257,14 @@ public class CarpetScriptServer
Messenger.m(source, "r Failed to add "+name+" app");
return false;
}
CarpetScriptHost newHost = CarpetScriptHost.create(this, module, perPlayer, source, commandValidator, isRuleApp, installer);
if (newHost == null)
CarpetScriptHost newHost;
try
{
Messenger.m(source, "r Failed to add "+name+" app");
newHost = CarpetScriptHost.create(this, module, perPlayer, source, commandValidator, isRuleApp, installer);
}
catch (LoadException e)
{
Messenger.m(source, "r Failed to add " + name + " app" + (e.getMessage() == null ? "" : ": " + e.getMessage()));
return false;
}
// config needs to be read as we load the app since some events use that info
+7 -4
View File
@@ -481,9 +481,9 @@ public class Expression
}
public void addLazyFunction(String name, int num_params, TriFunction<Context, Context.Type, List<LazyValue>, LazyValue> fun)
public void addLazyFunction(String name, int numParams, TriFunction<Context, Context.Type, List<LazyValue>, LazyValue> fun)
{
functions.put(name, new AbstractLazyFunction(num_params, name)
functions.put(name, new AbstractLazyFunction(numParams, name)
{
@Override
public boolean pure() {
@@ -499,8 +499,11 @@ public class Expression
public LazyValue lazyEval(Context c, Context.Type i, Expression e, Tokenizer.Token t, List<LazyValue> lazyParams)
{
ILazyFunction.checkInterrupts();
if (num_params >= 0 && lazyParams.size() != num_params)
throw new InternalExpressionException("'"+name+"' requires "+num_params+" parameters, "+lazyParams.size()+" provided.");
if (numParams >= 0 && lazyParams.size() != numParams)
{
String error = "Function '"+name+"' requires "+numParams+" arguments, got "+lazyParams.size()+". ";
throw new InternalExpressionException(error + (fun instanceof Fluff.UsageProvider up ? up.getUsage() : ""));
}
try
{
+2
View File
@@ -30,6 +30,8 @@ public abstract class Fluff
@FunctionalInterface
public interface SexFunction<A, B, C, D, E, F, R> { R apply(A a, B b, C c, D d, E e, F f);}
public interface UsageProvider { String getUsage();}
public interface EvalNode
{
/**
@@ -21,6 +21,7 @@ import carpet.script.Context;
import carpet.script.Expression;
import carpet.script.Fluff.AbstractLazyFunction;
import carpet.script.Fluff.TriFunction;
import carpet.script.Fluff.UsageProvider;
import carpet.script.exception.InternalExpressionException;
import carpet.script.LazyValue;
import carpet.script.value.Value;
@@ -73,6 +74,7 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList;
*/
public final class AnnotationParser
{
static final int UNDEFINED_PARAMS = -2;
private static final List<ParsedFunction> functionList = new ArrayList<>();
/**
@@ -90,8 +92,8 @@ public final class AnnotationParser
* {@link InternalExpressionException}).
* Basically, it's fine as long as you don't add a {@code throws} declaration to your methods.</li>
* <li>Varargs (or effectively varargs) annotated methods must explicitly declare a maximum number of parameters to ingest in the {@link ScarpetFunction}
* annotation. They can still declare an unlimited amount by setting that maximum to {@code -1}. "Effectively varargs" means a function that has
* a parameter using/requiring a {@link ValueConverter} that has declared {@link ValueConverter#consumesVariableArgs()}.</li>
* annotation. They can still declare an unlimited amount by setting that maximum to {@link ScarpetFunction#UNLIMITED_PARAMS}. "Effectively varargs"
* means a function that has at least a parameter requiring a {@link ValueConverter} that has declared {@link ValueConverter#consumesVariableArgs()}.</li>
* <li>Annotated methods must not have a parameter with generics as the varargs parameter. This is just because it was painful for me (altrisi) and
* didn't want to support it. Those will crash with a {@code ClassCastException}</li>
* </ul>
@@ -141,7 +143,7 @@ public final class AnnotationParser
expr.addLazyFunction(function.name, function.scarpetParamCount, function);
}
private static class ParsedFunction implements TriFunction<Context, Context.Type, List<LazyValue>, LazyValue>
private static class ParsedFunction implements TriFunction<Context, Context.Type, List<LazyValue>, LazyValue>, UsageProvider
{
private final String name;
private final boolean isMethodVarArgs;
@@ -186,10 +188,10 @@ public final class AnnotationParser
if (this.isEffectivelyVarArgs)
{
maxParams = method.getAnnotation(ScarpetFunction.class).maxParams();
if (maxParams == -2)
throw new IllegalArgumentException("No maximum number of params specified for " + name + ", use -1 for unlimited. "
if (maxParams == UNDEFINED_PARAMS)
throw new IllegalArgumentException("No maximum number of params specified for " + name + ", use ScarpetFunction.UNLIMITED_PARAMS for unlimited. "
+ "Provided in " + instance.getClass());
if (maxParams == -1)
if (maxParams == ScarpetFunction.UNLIMITED_PARAMS)
maxParams = Integer.MAX_VALUE;
if (maxParams < this.minParams)
throw new IllegalArgumentException("Provided maximum number of params for " + name + " is smaller than method's param count."
@@ -293,7 +295,8 @@ public final class AnnotationParser
return params;
}
private String getUsage()
@Override
public String getUsage()
{
// Possibility: More descriptive messages using param.getName()? Would need changing gradle setup to keep those
StringBuilder builder = new StringBuilder("Usage: '");
@@ -51,6 +51,11 @@ import carpet.script.value.Value;
@Retention(RUNTIME)
public @interface ScarpetFunction
{
/**
* <p>Used to define that this {@link ScarpetFunction} can accept an unlimited number of parameters</p>
*/
public static final int UNLIMITED_PARAMS = -1;
/**
* <p>If the function can accept a variable number of parameters, either by declaring its last parameter as a varargs parameter or by having one
* of their parameters use a converter that consumes a variable number of arguments, this must define the maximum number of parameters this
@@ -65,11 +70,11 @@ public @interface ScarpetFunction
* consider that those can take either a single triple of values or 3 independent values, that would be counted in the maximum number of
* parameters.</p>
*
* <p>Use -1 to specify an unlimited number of parameters.</p>
* <p>Use {@link ScarpetFunction#UNLIMITED_PARAMS} to allow an unlimited number of parameters.</p>
*
* @return The maximum number of parameters this function can accept
*/
int maxParams() default -2;
int maxParams() default AnnotationParser.UNDEFINED_PARAMS;
/**
* <p>Defines the Context Type that will be used when evaluating arguments to annotated methods.</p>
@@ -162,13 +162,13 @@ public interface ValueConverter<R>
* constraints as {@link #convert(Value)}</p>
* @param valueIterator An {@link Iterator} holding the {@link Value} to convert in next position
* @param context The {@link Context} this function has been called with. This was used when this passed lazy values instead in order to
* evaluate, now it's used to get the context. It is now ignored by the default implementation
* @param theLazyT The {@code t} that the original function was called with. It is ignored by the default implementation.
* evaluate, now it's used to get the context
* @param contextType The {@link Context.Type} that the original function was called with
* @return The next {@link Value} (s) converted to the type {@code <R>} of this {@link ValueConverter}
* @implNote This method's default implementation runs the {@link #convert(Value)} function in the next {@link Value} ignoring {@link Context} and
* {@code theLazyT}.
*/
default public R checkAndConvert(Iterator<Value> valueIterator, Context context, Context.Type theLazyT)
default public R checkAndConvert(Iterator<Value> valueIterator, Context context, Context.Type contextType)
{
if (!valueIterator.hasNext())
return null;
@@ -676,7 +676,7 @@ public class Auxiliary {
expression.addContextFunction("last_tick_times", -1, (c, t, lv) ->
{
c.host.issueDeprecation("last_tick_times()");
return SystemInfo.get("last_tick_times", (CarpetContext)c);
return SystemInfo.get("server_last_tick_times", (CarpetContext)c);
});
@@ -736,6 +736,7 @@ public class Auxiliary {
return Value.TRUE;
});
// Should this be deprecated for system_info('source_dimension')?
expression.addContextFunction("current_dimension", 0, (c, t, lv) ->
ValueConversions.of( ((CarpetContext)c).s.getWorld()));
+32 -44
View File
@@ -3,6 +3,7 @@ package carpet.script.api;
import carpet.script.CarpetContext;
import carpet.script.CarpetEventServer;
import carpet.script.CarpetScriptHost;
import carpet.script.Context;
import carpet.script.Expression;
import carpet.script.argument.FunctionArgument;
import carpet.script.argument.Vector3Argument;
@@ -36,9 +37,20 @@ import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.UUID;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class Entities {
private static ListValue getPlayersFromWorldMatching(Context c, Predicate<ServerPlayerEntity> condition) {
List<Value> ret = new ArrayList<>();
for (ServerPlayerEntity player: ((CarpetContext) c).s.getWorld().getPlayers()) {
if (condition.test(player)) {
ret.add(new EntityValue(player));
}
}
return ListValue.wrap(ret);
}
public static void apply(Expression expression)
{
expression.addContextFunction("player", -1, (c, t, lv) ->
@@ -58,50 +70,26 @@ public class Entities {
return EntityValue.of(closestPlayer);
}
String playerName = lv.get(0).getString();
Value retval = Value.NULL;
if ("all".equalsIgnoreCase(playerName))
{
retval = ListValue.wrap(
((CarpetContext)c).s.getServer().getPlayerManager().getPlayerList().
stream().map(EntityValue::new).collect(Collectors.toList()));
}
else if ("*".equalsIgnoreCase(playerName))
{
retval = ListValue.wrap(
((CarpetContext)c).s.getWorld().getPlayers().
stream().map(EntityValue::new).collect(Collectors.toList()));
}
else if ("survival".equalsIgnoreCase(playerName))
{
retval = ListValue.wrap(
((CarpetContext)c).s.getWorld().getPlayers((p) -> p.interactionManager.isSurvivalLike()).
stream().map(EntityValue::new).collect(Collectors.toList()));
}
else if ("creative".equalsIgnoreCase(playerName))
{
retval = ListValue.wrap(
((CarpetContext)c).s.getWorld().getPlayers(PlayerEntity::isCreative).
stream().map(EntityValue::new).collect(Collectors.toList()));
}
else if ("spectating".equalsIgnoreCase(playerName))
{
retval = ListValue.wrap(
((CarpetContext)c).s.getWorld().getPlayers(PlayerEntity::isSpectator).
stream().map(EntityValue::new).collect(Collectors.toList()));
}
else if ("!spectating".equalsIgnoreCase(playerName))
{
retval = ListValue.wrap(
((CarpetContext)c).s.getWorld().getPlayers((p) -> !p.isSpectator()).
stream().map(EntityValue::new).collect(Collectors.toList()));
}
else
{
ServerPlayerEntity player = ((CarpetContext) c).s.getServer().getPlayerManager().getPlayer(playerName);
if (player != null)
retval = new EntityValue(player);
}
return retval;
return switch (playerName) {
case "all" -> {
List<Value> ret = new ArrayList<>();
for (ServerPlayerEntity player: ((CarpetContext)c).s.getServer().getPlayerManager().getPlayerList())
ret.add(new EntityValue(player));
yield ListValue.wrap(ret);
}
case "*" -> getPlayersFromWorldMatching(c, p -> true);
case "survival" -> getPlayersFromWorldMatching(c, p -> p.interactionManager.isSurvivalLike());
case "creative" -> getPlayersFromWorldMatching(c, PlayerEntity::isCreative);
case "spectating" -> getPlayersFromWorldMatching(c, PlayerEntity::isSpectator);
case "!spectating" -> getPlayersFromWorldMatching(c, p -> !p.isSpectator());
default -> {
ServerPlayerEntity player = ((CarpetContext) c).s.getServer().getPlayerManager().getPlayer(playerName);
if (player != null) {
yield new EntityValue(player);
}
yield Value.NULL;
}
};
});
expression.addContextFunction("spawn", -1, (c, t, lv) ->
@@ -0,0 +1,19 @@
package carpet.script.exception;
/**
* A Scarpet exception that indicates that load of the app has failed.
*
* Goes up the stack to the point of app load and gets caught there, preventing the app from loading with
* the given message.
*
*/
public class LoadException extends RuntimeException implements ResolvedException {
public LoadException() {
super();
}
public LoadException(String message) {
super(message);
}
}
@@ -8,9 +8,7 @@ import carpet.script.value.NumericValue;
import carpet.script.value.StringValue;
import carpet.script.value.Value;
import carpet.script.value.ValueConversions;
import net.minecraft.client.color.world.FoliageColors;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.feature.ConfiguredFeature;
@@ -27,11 +25,11 @@ public class BiomeInfo
//put("under_material", (w, b) -> new BlockValue( b.getGenerationSettings().getSurfaceConfig().getUnderMaterial(), null, null));
put("category", (w, b) -> StringValue.of(b.getCategory().getName()));
put("temperature", (w, b) -> NumericValue.of(b.getTemperature()));
put("fog_color", (w, b) -> ValueConversions.ofRGB(((BiomeEffectsInterface)b.getEffects()).getCMFogColor()));
put("foliage_color", (w, b) -> ValueConversions.ofRGB(((BiomeEffectsInterface)b.getEffects()).getCMFoliageColor().orElse(4764952))); // client Biome.getDefaultFoliageColor
put("sky_color", (w, b) -> ValueConversions.ofRGB(((BiomeEffectsInterface)b.getEffects()).getCMSkyColor()));
put("water_color", (w, b) -> ValueConversions.ofRGB(((BiomeEffectsInterface)b.getEffects()).getCMWaterColor()));
put("water_fog_color", (w, b) -> ValueConversions.ofRGB(((BiomeEffectsInterface)b.getEffects()).getCMWaterFogColor()));
put("fog_color", (w, b) -> ValueConversions.ofRGB(b.getEffects().getFogColor()));
put("foliage_color", (w, b) -> ValueConversions.ofRGB(b.getEffects().getFoliageColor().orElse(4764952))); // client Biome.getDefaultFoliageColor
put("sky_color", (w, b) -> ValueConversions.ofRGB(b.getEffects().getSkyColor()));
put("water_color", (w, b) -> ValueConversions.ofRGB(b.getEffects().getWaterColor()));
put("water_fog_color", (w, b) -> ValueConversions.ofRGB(b.getEffects().getWaterFogColor()));
put("humidity", (w, b) -> NumericValue.of(b.getDownfall()));
put("precipitation", (w, b) -> StringValue.of(b.getPrecipitation().getName()));
//put("depth", (w, b) -> NumericValue.of(b.getDepth()));
@@ -5,6 +5,7 @@ import carpet.CarpetSettings;
import carpet.script.CarpetContext;
import carpet.script.CarpetScriptHost;
import carpet.script.value.BooleanValue;
import carpet.script.value.EntityValue;
import carpet.script.value.ListValue;
import carpet.script.value.MapValue;
import carpet.script.value.NumericValue;
@@ -17,11 +18,9 @@ import com.sun.management.OperatingSystemMXBean;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.minecraft.SharedConstants;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.WorldSavePath;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.util.math.Vec2f;
import net.minecraft.world.GameRules;
import net.minecraft.world.World;
import net.minecraft.world.WorldProperties;
import net.minecraft.world.border.WorldBorder;
@@ -74,7 +73,9 @@ public class SystemInfo {
return ListValue.fromTriple(worldBorder.getCenterX(), 0, worldBorder.getCenterZ());
});
put("world_size", c-> new NumericValue( c.s.getWorld().getWorldBorder().getMaxRadius()));
put("world_size", c -> new NumericValue(c.s.getWorld().getWorldBorder().getSize() / 2));
put("world_max_size", c-> new NumericValue( c.s.getWorld().getWorldBorder().getMaxRadius()));
put("world_time", c -> new NumericValue(c.s.getWorld().getTime()));
@@ -199,6 +200,15 @@ public class SystemInfo {
});
return MapValue.wrap(rules);
});
put("source_entity", c -> EntityValue.of(c.s.getEntity()));
put("source_position", c -> ValueConversions.of(c.s.getPosition()));
put("source_dimension", c -> ValueConversions.of(c.s.getWorld()));
put("source_rotation", c -> {
Vec2f rotation = c.s.getRotation();
return ListValue.of(new NumericValue(rotation.x), new NumericValue(rotation.y));
});
put("scarpet_version", c -> StringValue.of(CarpetSettings.carpetVersion));
}};
@@ -1,10 +1,8 @@
package carpet.script.value;
import carpet.fakes.BrainInterface;
import carpet.fakes.EntityInterface;
import carpet.fakes.ItemEntityInterface;
import carpet.fakes.LivingEntityInterface;
import carpet.fakes.MemoryInterface;
import carpet.fakes.MobEntityInterface;
import carpet.fakes.ServerPlayerEntityInterface;
import carpet.fakes.ServerPlayerInteractionManagerInterface;
@@ -633,11 +631,11 @@ public class EntityValue extends Value
if (e instanceof LivingEntity livingEntity)
{
Brain<?> brain = livingEntity.getBrain();
Map<MemoryModuleType<?>, Optional<? extends Memory<?>>> memories = ((BrainInterface)brain).getMobMemories();
Map<MemoryModuleType<?>, Optional<? extends Memory<?>>> memories = brain.getMemories();
Optional<? extends Memory<?>> optmemory = memories.get(moduleType);
if (optmemory==null || !optmemory.isPresent()) return Value.NULL;
Memory<?> memory = optmemory.get();
return ValueConversions.fromTimedMemory(e, ((MemoryInterface)memory).getScarpetExpiry(), memory.getValue());
return ValueConversions.fromTimedMemory(e, memory.getExpiry(), memory.getValue());
}
return Value.NULL;
});
@@ -1584,7 +1582,7 @@ public class EntityValue extends Value
});
put("absorption", (e, v) -> {
if (e instanceof PlayerEntity) ((PlayerEntity) e).setAbsorptionAmount((float) NumericValue.asNumber(v, "absorbtion").getLong());
if (e instanceof PlayerEntity) ((PlayerEntity) e).setAbsorptionAmount(NumericValue.asNumber(v, "absorbtion").getFloat());
});
put("add_xp", (e, v) -> {
@@ -19,18 +19,29 @@ public class ThreadValue extends Value
private final long id;
private static long sequence = 0L;
public ThreadValue(CompletableFuture<Value> taskFuture)
{
this.taskFuture = taskFuture;
this.id = sequence++;
}
public ThreadValue(Value pool, FunctionValue function, Expression expr, Tokenizer.Token token, Context ctx, List<Value> args)
{
id = sequence++;
this(getCompletableFutureFromFunction(pool, function, expr, token, ctx, args));
Thread.yield();
}
public static CompletableFuture<Value> getCompletableFutureFromFunction(Value pool, FunctionValue function, Expression expr, Tokenizer.Token token, Context ctx, List<Value> args)
{
ExecutorService executor = ctx.host.getExecutor(pool);
if (executor == null)
{
// app is shutting down - no more threads can be spawned.
taskFuture = CompletableFuture.completedFuture(Value.NULL);
return CompletableFuture.completedFuture(Value.NULL);
}
else
{
taskFuture = CompletableFuture.supplyAsync(
return CompletableFuture.supplyAsync(
() ->
{
try
@@ -52,7 +63,6 @@ public class ThreadValue extends Value
ctx.host.getExecutor(pool)
);
}
Thread.yield();
}
@Override
+37 -57
View File
@@ -103,23 +103,18 @@ public class Messenger
}
public static String creatureTypeColor(SpawnGroup type)
{
switch (type)
return switch (type)
{
case MONSTER:
return "n";
case CREATURE:
return "e";
case AMBIENT:
return "f";
case WATER_CREATURE:
return "v";
case WATER_AMBIENT:
return "q";
}
return "w";
case MONSTER -> "n";
case CREATURE -> "e";
case AMBIENT -> "f";
case WATER_CREATURE -> "v";
case WATER_AMBIENT -> "q";
default -> "w"; // missing MISC and UNDERGROUND_WATER_CREATURE
};
}
private static BaseText _getChatComponentFromDesc(String message, BaseText previous_message)
private static BaseText getChatComponentFromDesc(String message, BaseText previousMessage)
{
if (message.equalsIgnoreCase(""))
{
@@ -127,7 +122,7 @@ public class Messenger
}
if (Character.isWhitespace(message.charAt(0)))
{
message = "w"+message;
message = "w" + message;
}
int limit = message.indexOf(' ');
String desc = message;
@@ -137,52 +132,37 @@ public class Messenger
desc = message.substring(0, limit);
str = message.substring(limit+1);
}
if (desc.charAt(0) == '/') // deprecated
{
if (previous_message != null)
previous_message.setStyle(
previous_message.getStyle().withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, message))
);
return previous_message;
if (previousMessage == null) {
BaseText text = new LiteralText(str);
text.setStyle(parseStyle(desc));
return text;
}
if (desc.charAt(0) == '?')
{
if (previous_message != null)
previous_message.setStyle(
previous_message.getStyle().withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, message.substring(1)))
);
return previous_message;
}
if (desc.charAt(0) == '!')
{
if (previous_message != null)
previous_message.setStyle(
previous_message.getStyle().withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, message.substring(1)))
);
return previous_message;
}
if (desc.charAt(0) == '^')
{
if (previous_message != null)
previous_message.setStyle(
previous_message.getStyle().withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, c(message.substring(1))))
);
return previous_message;
}
BaseText txt = new LiteralText(str);
txt.setStyle(parseStyle(desc));
return txt;
Style previousStyle = previousMessage.getStyle();
BaseText ret = previousMessage;
previousMessage.setStyle(switch (desc.charAt(0)) {
case '?' -> previousStyle.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, message.substring(1)));
case '!' -> previousStyle.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, message.substring(1)));
case '^' -> previousStyle.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, c(message.substring(1))));
case '@' -> previousStyle.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, message.substring(1)));
case '&' -> previousStyle.withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, message.substring(1)));
default -> { // Create a new component
ret = new LiteralText(str);
ret.setStyle(parseStyle(desc));
yield previousStyle; // no op for the previous style
}
});
return ret;
}
public static BaseText tp(String desc, Vec3d pos) { return tp(desc, pos.x, pos.y, pos.z); }
public static BaseText tp(String desc, BlockPos pos) { return tp(desc, pos.getX(), pos.getY(), pos.getZ()); }
public static BaseText tp(String desc, double x, double y, double z) { return tp(desc, (float)x, (float)y, (float)z);}
public static BaseText tp(String desc, float x, float y, float z)
{
return _getCoordsTextComponent(desc, x, y, z, false);
return getCoordsTextComponent(desc, x, y, z, false);
}
public static BaseText tp(String desc, int x, int y, int z)
{
return _getCoordsTextComponent(desc, (float)x, (float)y, (float)z, true);
return getCoordsTextComponent(desc, (float)x, (float)y, (float)z, true);
}
/// to be continued
@@ -232,7 +212,7 @@ public class Messenger
return c(components.toArray(new Object[0]));
}
private static BaseText _getCoordsTextComponent(String style, float x, float y, float z, boolean isInt)
private static BaseText getCoordsTextComponent(String style, float x, float y, float z, boolean isInt)
{
String text;
String command;
@@ -266,19 +246,19 @@ public class Messenger
public static BaseText c(Object ... fields)
{
BaseText message = new LiteralText("");
BaseText previous_component = null;
BaseText previousComponent = null;
for (Object o: fields)
{
if (o instanceof BaseText)
{
message.append((BaseText)o);
previous_component = (BaseText)o;
previousComponent = (BaseText)o;
continue;
}
String txt = o.toString();
BaseText comp = _getChatComponentFromDesc(txt,previous_component);
if (comp != previous_component) message.append(comp);
previous_component = comp;
BaseText comp = getChatComponentFromDesc(txt, previousComponent);
if (comp != previousComponent) message.append(comp);
previousComponent = comp;
}
return message;
}
-3
View File
@@ -67,8 +67,6 @@
"EntityTrackerEntry_leashFixMixin",
"VillagerEntity_aiMixin",
"Brain_Mixin",
"Memory_scarpetMixin",
"PlayerEntity_fakePlayersMixin",
"ThrownEnderpearlEntity_fakePlayersMixin",
@@ -190,7 +188,6 @@
"Team_scarpetMixin",
"TradeOutputSlot_scarpetEventMixin",
"BiomeEffects_scarpetMixin",
"ChunkTicketManager_scarpetMixin",
"PointOfInterest_scarpetMixin",
"ServerWorld_scarpetMixin",
+1 -1
View File
@@ -33,7 +33,7 @@
"depends": {
"minecraft": "1.18.x",
"fabricloader": ">=0.11.6",
"fabricloader": ">=0.12.8",
"java": ">=17"
}
}