Adding absorption and xp API, and weather control (#540)
* fixes #537 * fixes #547
This commit is contained in:
1 parent
8acb322747
commit
42e67f27b7
9 files changed
+184
-20
No files matched your search
@@ -193,9 +193,10 @@ Other value types will only be converted to tags (including NBT tags) if `force`
|
|||||||
extra treatment when loading them back from NBT, but using `force` true will always produce output / never
|
extra treatment when loading them back from NBT, but using `force` true will always produce output / never
|
||||||
produce an exception.
|
produce an exception.
|
||||||
|
|
||||||
### `print(expr)`
|
### `print(expr)`, `print(player/player_list, expr)`
|
||||||
|
|
||||||
Displays the result of the expression to the chat. Overrides default `scarpet` behaviour of sending everyting to stderr.
|
Displays the result of the expression to the chat. Overrides default `scarpet` behaviour of sending everyting to stderr.
|
||||||
|
Can optionally define player or list of players to send the message to.
|
||||||
|
|
||||||
### `format(components, ...)`, `format(l(components, ...))`
|
### `format(components, ...)`, `format(l(components, ...))`
|
||||||
|
|
||||||
|
|||||||
@@ -212,6 +212,16 @@ Causes a block to be harvested by a specified player entity. Honors player item
|
|||||||
tool if applicable. If the entity is not a valid player, no block gets destroyed. If a player is not allowed to break
|
tool if applicable. If the entity is not a valid player, no block gets destroyed. If a player is not allowed to break
|
||||||
that block, a block doesn't get destroyed either.
|
that block, a block doesn't get destroyed either.
|
||||||
|
|
||||||
|
### `weather()`,`weather(type)`,`weather(type, ticks)`
|
||||||
|
|
||||||
|
If called with no args, returns `'clear'`, `'rain` or `'thunder'` based on the current weather. If thundering, will
|
||||||
|
always return `'thunder'`, if not will return `'rain'` or `'clear'` based on the current weather.
|
||||||
|
|
||||||
|
With one arg, (either `'clear'`, `'rain` or `'thunder'`), returns the number of remaining ticks for that weather type.
|
||||||
|
NB: It can thunder without there being a thunderstorm, there has to be both rain and thunder to form a storm.
|
||||||
|
|
||||||
|
With two args, sets the weather to `type` for `ticks` ticks.
|
||||||
|
|
||||||
## Block and World querying
|
## Block and World querying
|
||||||
|
|
||||||
### `pos(block), pos(entity)`
|
### `pos(block), pos(entity)`
|
||||||
|
|||||||
@@ -396,6 +396,18 @@ Number indicating remaining entity health, or `null` if not applicable.
|
|||||||
|
|
||||||
Retrieves player hunger related information. For non-players, returns `null`.
|
Retrieves player hunger related information. For non-players, returns `null`.
|
||||||
|
|
||||||
|
### `query(e, 'absorption')`
|
||||||
|
|
||||||
|
Gets the absorption of the player (yellow hearts, e.g when having a golden apple.)
|
||||||
|
|
||||||
|
### `query(e,'xp')`
|
||||||
|
### `query(e,'xp_level')`
|
||||||
|
### `query(e,'xp_progress')`
|
||||||
|
### `query(e,'score')`
|
||||||
|
|
||||||
|
Numbers related to player's xp. `xp` is the overall xp in the bar, `xp_level` is the levels seen in the hotbar,
|
||||||
|
`xp_points` is a float between 0 and 1 indicating the percentage of the xp bar filled, and `score` is the score displayed upon death
|
||||||
|
|
||||||
### `query(e, 'air')`
|
### `query(e, 'air')`
|
||||||
|
|
||||||
Number indicating remaining entity health, or `null` if not applicable.
|
Number indicating remaining entity health, or `null` if not applicable.
|
||||||
@@ -706,6 +718,17 @@ Will set entity on fire for `ticks` ticks. Set to 0 to extinguish.
|
|||||||
|
|
||||||
Modifies directly player raw hunger components. Has no effect on non-players
|
Modifies directly player raw hunger components. Has no effect on non-players
|
||||||
|
|
||||||
|
### `modify(e, 'absorption', value)`
|
||||||
|
|
||||||
|
Sets the absorption value for the player. Each point is half a yellow heart.
|
||||||
|
|
||||||
|
### `modify(e, 'add_xp', value)`
|
||||||
|
### `modify(e, 'xp_level', value)`
|
||||||
|
### `modify(e, 'xp_score', value)`
|
||||||
|
|
||||||
|
Manipulates player xp values - that's the method you probably want to use
|
||||||
|
to manipulate how much 'xp' an action should give.
|
||||||
|
|
||||||
### `modify(e, 'air', ticks)`
|
### `modify(e, 'air', ticks)`
|
||||||
|
|
||||||
Modifies entity air
|
Modifies entity air
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package carpet.fakes;
|
||||||
|
|
||||||
|
import net.minecraft.world.level.ServerWorldProperties;
|
||||||
|
|
||||||
|
public interface ServerWorldInterface {
|
||||||
|
ServerWorldProperties getWorldPropertiesCM();
|
||||||
|
}
|
||||||
+9
-1
@@ -1,6 +1,7 @@
|
|||||||
package carpet.mixins;
|
package carpet.mixins;
|
||||||
|
|
||||||
import carpet.CarpetSettings;
|
import carpet.CarpetSettings;
|
||||||
|
import carpet.fakes.ServerWorldInterface;
|
||||||
import carpet.script.CarpetEventServer;
|
import carpet.script.CarpetEventServer;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.LightningEntity;
|
import net.minecraft.entity.LightningEntity;
|
||||||
@@ -9,7 +10,9 @@ import net.minecraft.util.math.BlockPos;
|
|||||||
import net.minecraft.util.math.ChunkPos;
|
import net.minecraft.util.math.ChunkPos;
|
||||||
import net.minecraft.util.profiler.Profiler;
|
import net.minecraft.util.profiler.Profiler;
|
||||||
import net.minecraft.world.chunk.WorldChunk;
|
import net.minecraft.world.chunk.WorldChunk;
|
||||||
|
import net.minecraft.world.level.ServerWorldProperties;
|
||||||
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;
|
||||||
@@ -19,7 +22,7 @@ import static carpet.script.CarpetEventServer.Event.ENTITY_LOAD;
|
|||||||
import static carpet.script.CarpetEventServer.Event.LIGHTNING;
|
import static carpet.script.CarpetEventServer.Event.LIGHTNING;
|
||||||
|
|
||||||
@Mixin(ServerWorld.class)
|
@Mixin(ServerWorld.class)
|
||||||
public class ServerWorld_scarpetEventMixin
|
public class ServerWorld_scarpetMixin implements ServerWorldInterface
|
||||||
{
|
{
|
||||||
@Inject(method = "tickChunk", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(
|
@Inject(method = "tickChunk", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(
|
||||||
value = "INVOKE",
|
value = "INVOKE",
|
||||||
@@ -54,4 +57,9 @@ public class ServerWorld_scarpetEventMixin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
private ServerWorldProperties worldProperties;
|
||||||
|
public ServerWorldProperties getWorldPropertiesCM(){
|
||||||
|
return worldProperties;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -469,28 +469,42 @@ public class Auxiliary {
|
|||||||
if (lv.size() == 0 || lv.size() > 2) throw new InternalExpressionException("'print' takes one or two arguments");
|
if (lv.size() == 0 || lv.size() > 2) throw new InternalExpressionException("'print' takes one or two arguments");
|
||||||
ServerCommandSource s = ((CarpetContext)c).s;
|
ServerCommandSource s = ((CarpetContext)c).s;
|
||||||
Value res = lv.get(0).evalValue(c);
|
Value res = lv.get(0).evalValue(c);
|
||||||
if (lv.size() == 2)
|
Value playersVal = Value.NULL;
|
||||||
{
|
if (lv.size() == 2){
|
||||||
ServerPlayerEntity player = EntityValue.getPlayerByValue(s.getMinecraftServer(), res);
|
playersVal = res;
|
||||||
if (player == null) return LazyValue.NULL;
|
|
||||||
s = player.getCommandSource();
|
|
||||||
res = lv.get(1).evalValue(c);
|
res = lv.get(1).evalValue(c);
|
||||||
}
|
}
|
||||||
if (res instanceof FormattedTextValue)
|
|
||||||
{
|
if(playersVal instanceof ListValue){
|
||||||
s.sendFeedback(((FormattedTextValue) res).getText(), false);
|
|
||||||
}
|
List<Value> players = ((ListValue) playersVal).getItems();
|
||||||
else
|
for(Value playerVal:players){
|
||||||
{
|
ServerPlayerEntity player = EntityValue.getPlayerByValue(s.getMinecraftServer(), playerVal);
|
||||||
if (s.getEntity() instanceof PlayerEntity)
|
if (player == null) return LazyValue.NULL;
|
||||||
{
|
if(res instanceof FormattedTextValue)
|
||||||
Messenger.m((PlayerEntity) s.getEntity(), "w " + res.getString());
|
player.getCommandSource().sendFeedback(((FormattedTextValue) res).getText(), false);
|
||||||
|
else
|
||||||
|
Messenger.m(player, "w "+res.getString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if(playersVal instanceof EntityValue){
|
||||||
|
|
||||||
|
ServerPlayerEntity player = EntityValue.getPlayerByValue(s.getMinecraftServer(), playersVal);
|
||||||
|
if (player == null) return LazyValue.NULL;
|
||||||
|
if(res instanceof FormattedTextValue)
|
||||||
|
player.getCommandSource().sendFeedback(((FormattedTextValue) res).getText(), false);
|
||||||
|
else
|
||||||
|
Messenger.m(player, "w "+res.getString());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (res instanceof FormattedTextValue)
|
||||||
|
s.sendFeedback(((FormattedTextValue) res).getText(), false);
|
||||||
else
|
else
|
||||||
{
|
|
||||||
Messenger.m(s, "w " + res.getString());
|
Messenger.m(s, "w " + res.getString());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Value finalRes = res;
|
Value finalRes = res;
|
||||||
return (_c, _t) -> finalRes; // pass through for variables
|
return (_c, _t) -> finalRes; // pass through for variables
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import carpet.fakes.BiomeArrayInterface;
|
|||||||
import carpet.fakes.ChunkGeneratorInterface;
|
import carpet.fakes.ChunkGeneratorInterface;
|
||||||
import carpet.fakes.ChunkTicketManagerInterface;
|
import carpet.fakes.ChunkTicketManagerInterface;
|
||||||
import carpet.fakes.ServerChunkManagerInterface;
|
import carpet.fakes.ServerChunkManagerInterface;
|
||||||
|
import carpet.fakes.ServerWorldInterface;
|
||||||
import carpet.fakes.SpawnHelperInnerInterface;
|
import carpet.fakes.SpawnHelperInnerInterface;
|
||||||
import carpet.fakes.ThreadedAnvilChunkStorageInterface;
|
import carpet.fakes.ThreadedAnvilChunkStorageInterface;
|
||||||
import carpet.helpers.FeatureGenerator;
|
import carpet.helpers.FeatureGenerator;
|
||||||
@@ -58,6 +59,7 @@ import net.minecraft.item.SwordItem;
|
|||||||
import net.minecraft.item.TridentItem;
|
import net.minecraft.item.TridentItem;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.Tag;
|
import net.minecraft.nbt.Tag;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.server.world.ChunkTicket;
|
import net.minecraft.server.world.ChunkTicket;
|
||||||
import net.minecraft.server.world.ChunkTicketType;
|
import net.minecraft.server.world.ChunkTicketType;
|
||||||
@@ -89,6 +91,7 @@ import net.minecraft.world.gen.ChunkRandom;
|
|||||||
import net.minecraft.world.gen.chunk.ChunkGenerator;
|
import net.minecraft.world.gen.chunk.ChunkGenerator;
|
||||||
import net.minecraft.world.gen.feature.ConfiguredStructureFeature;
|
import net.minecraft.world.gen.feature.ConfiguredStructureFeature;
|
||||||
import net.minecraft.world.gen.feature.StructureFeature;
|
import net.minecraft.world.gen.feature.StructureFeature;
|
||||||
|
import net.minecraft.world.level.ServerWorldProperties;
|
||||||
import net.minecraft.world.poi.PointOfInterest;
|
import net.minecraft.world.poi.PointOfInterest;
|
||||||
import net.minecraft.world.poi.PointOfInterestStorage;
|
import net.minecraft.world.poi.PointOfInterestStorage;
|
||||||
import net.minecraft.world.poi.PointOfInterestType;
|
import net.minecraft.world.poi.PointOfInterestType;
|
||||||
@@ -413,6 +416,63 @@ public class WorldAccess {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
expression.addLazyFunction("weather",-1,(c, t, lv) -> {
|
||||||
|
ServerWorld world = ((CarpetContext) c).s.getWorld();
|
||||||
|
|
||||||
|
if(lv.size()==0)//cos it can thunder when raining or when clear.
|
||||||
|
return (_c,_t)->new StringValue( world.isThundering()? "thunder" : (world.isRaining()? "rain":"clear"));
|
||||||
|
|
||||||
|
|
||||||
|
Value weather = lv.get(0).evalValue(c);
|
||||||
|
ServerWorldProperties worldProperties = ((ServerWorldInterface) world).getWorldPropertiesCM();
|
||||||
|
|
||||||
|
if(lv.size()==1) {
|
||||||
|
int ticks;
|
||||||
|
|
||||||
|
switch (weather.getString()) {
|
||||||
|
case "clear":
|
||||||
|
ticks = worldProperties.getClearWeatherTime();
|
||||||
|
break;
|
||||||
|
case "rain":
|
||||||
|
ticks = world.isRaining()? worldProperties.getRainTime():0;//cos if not it gives 1 for some reason
|
||||||
|
break;
|
||||||
|
case "thunder":
|
||||||
|
ticks = world.isThundering()? worldProperties.getThunderTime():0;//same dealio here
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new InternalExpressionException("Weather can only be 'clear', 'rain' or 'thunder'");
|
||||||
|
}
|
||||||
|
return (_c,_t) -> new NumericValue(ticks);
|
||||||
|
} else if(lv.size()==2){
|
||||||
|
int ticks = ((NumericValue)lv.get(1).evalValue(c)).getInt();
|
||||||
|
|
||||||
|
switch (weather.getString()){
|
||||||
|
case "clear":
|
||||||
|
world.setWeather(ticks,0,false,false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "rain":
|
||||||
|
world.setWeather(0,ticks,true,false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "thunder":
|
||||||
|
world.setWeather(
|
||||||
|
0,
|
||||||
|
ticks,//this is used to set thunder time, idk why...
|
||||||
|
true,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new InternalExpressionException("Weather can only be 'clear', 'rain' or 'thunder'");
|
||||||
|
}
|
||||||
|
|
||||||
|
return LazyValue.TRUE;
|
||||||
|
} else
|
||||||
|
throw new InternalExpressionException("'weather' between 0 and 2 arguments");
|
||||||
|
});
|
||||||
|
|
||||||
expression.addLazyFunction("pos", 1, (c, t, lv) ->
|
expression.addLazyFunction("pos", 1, (c, t, lv) ->
|
||||||
{
|
{
|
||||||
Value arg = lv.get(0).evalValue(c);
|
Value arg = lv.get(0).evalValue(c);
|
||||||
|
|||||||
@@ -499,6 +499,31 @@ public class EntityValue extends Value
|
|||||||
return Value.NULL;
|
return Value.NULL;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
put("absorption",(e, a)->{
|
||||||
|
if(e instanceof PlayerEntity) return new NumericValue(((PlayerEntity) e).getAbsorptionAmount());
|
||||||
|
return Value.NULL;
|
||||||
|
});
|
||||||
|
|
||||||
|
put("xp",(e, a)->{
|
||||||
|
if(e instanceof PlayerEntity) return new NumericValue(((PlayerEntity) e).totalExperience);
|
||||||
|
return Value.NULL;
|
||||||
|
});
|
||||||
|
|
||||||
|
put("xp_level", (e, a)->{
|
||||||
|
if(e instanceof PlayerEntity) return new NumericValue(((PlayerEntity) e).experienceLevel);
|
||||||
|
return Value.NULL;
|
||||||
|
});
|
||||||
|
|
||||||
|
put("xp_progress", (e, a)->{
|
||||||
|
if(e instanceof PlayerEntity) return new NumericValue(((PlayerEntity) e).experienceProgress);
|
||||||
|
return Value.NULL;
|
||||||
|
});
|
||||||
|
|
||||||
|
put("score", (e, a)->{
|
||||||
|
if(e instanceof PlayerEntity) return new NumericValue(((PlayerEntity) e).getScore());
|
||||||
|
return Value.NULL;
|
||||||
|
});
|
||||||
|
|
||||||
put("jumping", (e, a) -> {
|
put("jumping", (e, a) -> {
|
||||||
if (e instanceof LivingEntity)
|
if (e instanceof LivingEntity)
|
||||||
{
|
{
|
||||||
@@ -1328,8 +1353,24 @@ public class EntityValue extends Value
|
|||||||
if(e instanceof PlayerEntity) ((PlayerEntity) e).getHungerManager().addExhaustion((int) NumericValue.asNumber(v).getLong());
|
if(e instanceof PlayerEntity) ((PlayerEntity) e).getHungerManager().addExhaustion((int) NumericValue.asNumber(v).getLong());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
put("absorption", (e, v) -> {
|
||||||
|
if (e instanceof PlayerEntity) ((PlayerEntity) e).setAbsorptionAmount((float) NumericValue.asNumber(v).getLong());
|
||||||
|
});
|
||||||
|
|
||||||
|
put("add_xp", (e, v) -> {
|
||||||
|
if (e instanceof PlayerEntity) ((PlayerEntity) e).addExperience(NumericValue.asNumber(v).getInt());
|
||||||
|
});
|
||||||
|
|
||||||
|
put("xp_level", (e, v) -> {
|
||||||
|
if (e instanceof PlayerEntity) ((PlayerEntity) e).addExperienceLevels(NumericValue.asNumber(v).getInt()-((PlayerEntity) e).experienceLevel);
|
||||||
|
});
|
||||||
|
|
||||||
|
put("xp_score", (e, v) -> {
|
||||||
|
if (e instanceof PlayerEntity) ((PlayerEntity) e).setScore(NumericValue.asNumber(v).getInt());
|
||||||
|
});
|
||||||
|
|
||||||
put("saturation", (e, v)-> {
|
put("saturation", (e, v)-> {
|
||||||
if(e instanceof PlayerEntity) ((PlayerEntity) e).getHungerManager().setSaturationLevelClient((float)NumericValue.asNumber(v).getLong());
|
if(e instanceof PlayerEntity) ((PlayerEntity) e).getHungerManager().setSaturationLevelClient(NumericValue.asNumber(v).getFloat());
|
||||||
});
|
});
|
||||||
|
|
||||||
put("air", (e, v) -> e.setAir(NumericValue.asNumber(v).getInt()));
|
put("air", (e, v) -> e.setAir(NumericValue.asNumber(v).getInt()));
|
||||||
|
|||||||
@@ -168,7 +168,7 @@
|
|||||||
"ChunkTicketManager_scarpetMixin",
|
"ChunkTicketManager_scarpetMixin",
|
||||||
"StatType_scarpetMixin",
|
"StatType_scarpetMixin",
|
||||||
"PointOfInterest_scarpetMixin",
|
"PointOfInterest_scarpetMixin",
|
||||||
"ServerWorld_scarpetEventMixin",
|
"ServerWorld_scarpetMixin",
|
||||||
"HungerManagerMixin_scarpetEventsMixin",
|
"HungerManagerMixin_scarpetEventsMixin",
|
||||||
|
|
||||||
"RecipeManager_scarpetMixin",
|
"RecipeManager_scarpetMixin",
|
||||||
|
|||||||
Reference in new issue
Block a user