Merge branch 'master' into 1.15
# Conflicts: # src/main/java/carpet/script/CarpetExpression.java
This commit is contained in:
commit
3e6f83905c
21 files changed
+1019
-296
No files matched your search
@@ -26,26 +26,20 @@ public abstract class ContainerMixin
|
||||
@Shadow public abstract void sendContentUpdates();
|
||||
|
||||
@Inject( method = "onSlotClick", at = @At(value = "HEAD"), cancellable = true)
|
||||
private void onThrowClick(
|
||||
int int_1,
|
||||
int int_2,
|
||||
SlotActionType slotActionType_1,
|
||||
PlayerEntity playerEntity_1,
|
||||
CallbackInfoReturnable<ItemStack> cir
|
||||
)
|
||||
private void onThrowClick( int slotId, int clickData, SlotActionType actionType, PlayerEntity playerEntity, CallbackInfoReturnable<ItemStack> cir)
|
||||
{
|
||||
if (slotActionType_1 == SlotActionType.THROW && CarpetSettings.ctrlQCraftingFix && playerEntity_1.inventory.getCursorStack().isEmpty() && int_1 >= 0)
|
||||
if (actionType == SlotActionType.THROW && CarpetSettings.ctrlQCraftingFix && playerEntity.inventory.getCursorStack().isEmpty() && slotId >= 0)
|
||||
{
|
||||
ItemStack itemStack_1 = ItemStack.EMPTY;
|
||||
Slot slot_4 = slotList.get(int_1);
|
||||
if (slot_4 != null && slot_4.hasStack() && slot_4.canTakeItems(playerEntity_1))
|
||||
Slot slot_4 = slotList.get(slotId);
|
||||
if (slot_4 != null && slot_4.hasStack() && slot_4.canTakeItems(playerEntity))
|
||||
{
|
||||
if(int_1 == 0 && int_2 == 1)
|
||||
if(slotId == 0 && clickData == 1)
|
||||
{
|
||||
Item craftedItem = slot_4.getStack().getItem();
|
||||
while(slot_4.hasStack() && slot_4.getStack().getItem() == craftedItem)
|
||||
{
|
||||
this.onSlotClick(int_1, 0, SlotActionType.THROW, playerEntity_1);
|
||||
this.onSlotClick(slotId, 0, SlotActionType.THROW, playerEntity);
|
||||
}
|
||||
this.sendContentUpdates();
|
||||
cir.setReturnValue(itemStack_1);
|
||||
|
||||
@@ -4,14 +4,18 @@ import com.mojang.authlib.GameProfile;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.stat.Stat;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.world.World;
|
||||
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.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import static carpet.script.CarpetEventServer.Event.PLAYER_FINISHED_USING_ITEM;
|
||||
import static carpet.script.CarpetEventServer.Event.STATISTICS;
|
||||
|
||||
@Mixin(ServerPlayerEntity.class)
|
||||
public abstract class ServerPlayerEntity_scarpetEventMixin extends PlayerEntity
|
||||
@@ -43,4 +47,10 @@ public abstract class ServerPlayerEntity_scarpetEventMixin extends PlayerEntity
|
||||
super.consumeItem();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "increaseStat", at = @At("HEAD"))
|
||||
private void grabStat(Stat<?> stat, int amount, CallbackInfo ci)
|
||||
{
|
||||
STATISTICS.onPlayerStatistic((ServerPlayerEntity) (Object)this, stat, amount);
|
||||
}
|
||||
}
|
||||
@@ -21,14 +21,4 @@ public class WorldChunk_fillUpdatesMixin
|
||||
if (!CarpetSettings.impendingFillSkipUpdates)
|
||||
blockState.onBlockAdded(world_1, blockPos_1, blockState_1, boolean_1);
|
||||
}
|
||||
|
||||
@Redirect(method = "setBlockState", at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/block/BlockState;onBlockRemoved(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Z)V"
|
||||
))
|
||||
private void onRemoved(BlockState blockState, World world_1, BlockPos blockPos_1, BlockState blockState_1, boolean boolean_1)
|
||||
{
|
||||
if (!CarpetSettings.impendingFillSkipUpdates)
|
||||
blockState.onBlockRemoved(world_1, blockPos_1, blockState_1, boolean_1);
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import carpet.script.value.BlockValue;
|
||||
import carpet.script.value.EntityValue;
|
||||
import carpet.script.value.FunctionValue;
|
||||
import carpet.script.value.ListValue;
|
||||
import carpet.script.value.NBTSerializableValue;
|
||||
import carpet.script.value.NumericValue;
|
||||
import carpet.script.value.StringValue;
|
||||
import carpet.script.value.Value;
|
||||
@@ -13,11 +14,15 @@ import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.stat.Stat;
|
||||
import net.minecraft.stat.Stats;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.dimension.DimensionType;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
@@ -25,10 +30,12 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -403,7 +410,32 @@ public class CarpetEventServer
|
||||
{
|
||||
handler.call( () -> Collections.singletonList(((c, t) -> new EntityValue(player))), player::getCommandSource);
|
||||
}
|
||||
};
|
||||
},
|
||||
STATISTICS("statistic", new CallbackList(4))
|
||||
{
|
||||
private <T> Identifier getStatId(Stat<T> stat)
|
||||
{
|
||||
return stat.getType().getRegistry().getId(stat.getValue());
|
||||
}
|
||||
private Set<Identifier> skippedStats = new HashSet<Identifier>(){{
|
||||
add(Stats.TIME_SINCE_DEATH);
|
||||
add(Stats.TIME_SINCE_REST);
|
||||
add(Stats.PLAY_ONE_MINUTE);
|
||||
}};
|
||||
@Override
|
||||
public void onPlayerStatistic(ServerPlayerEntity player, Stat<?> stat, int amount)
|
||||
{
|
||||
Identifier id = getStatId(stat);
|
||||
if (skippedStats.contains(id)) return;
|
||||
handler.call( () -> Arrays.asList(
|
||||
((c, t) -> new EntityValue(player)),
|
||||
((c, t) -> new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.STAT_TYPE.getId(stat.getType())))),
|
||||
((c, t) -> new StringValue(NBTSerializableValue.nameFromRegistryId(id))),
|
||||
((c, t) -> new NumericValue(amount))
|
||||
), player::getCommandSource);
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
// on projectile thrown (arrow from bows, crossbows, tridents, snoballs, e-pearls
|
||||
|
||||
@@ -427,6 +459,7 @@ public class CarpetEventServer
|
||||
//stubs for calls just to ease calls in vanilla code so they don't need to deal with scarpet value types
|
||||
public void onTick() { }
|
||||
public void onPlayerEvent(ServerPlayerEntity player) { }
|
||||
public void onPlayerStatistic(ServerPlayerEntity player, Stat<?> stat, int amount) { }
|
||||
public void onMountControls(ServerPlayerEntity player, float strafeSpeed, float forwardSpeed, boolean jumping, boolean sneaking) { }
|
||||
public void onItemAction(ServerPlayerEntity player, Hand enumhand, ItemStack itemstack) { }
|
||||
public void onBlockAction(ServerPlayerEntity player, BlockPos blockpos, Direction facing) { }
|
||||
|
||||
@@ -11,6 +11,7 @@ import carpet.script.exception.CarpetExpressionException;
|
||||
import carpet.script.exception.ExitStatement;
|
||||
import carpet.script.exception.ExpressionException;
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import carpet.CarpetSettings;
|
||||
import carpet.script.value.BlockValue;
|
||||
import carpet.script.value.EntityValue;
|
||||
import carpet.script.value.FunctionValue;
|
||||
@@ -20,8 +21,8 @@ import carpet.script.value.NBTSerializableValue;
|
||||
import carpet.script.value.NullValue;
|
||||
import carpet.script.value.NumericValue;
|
||||
import carpet.script.value.StringValue;
|
||||
import carpet.script.value.ThreadValue;
|
||||
import carpet.script.value.Value;
|
||||
import carpet.CarpetSettings;
|
||||
import carpet.utils.BlockInfo;
|
||||
import carpet.utils.Messenger;
|
||||
import com.google.common.collect.Sets;
|
||||
@@ -106,7 +107,6 @@ import java.util.function.BiFunction;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static carpet.script.value.NBTSerializableValue.nameFromRegistryId;
|
||||
import static java.lang.Math.abs;
|
||||
import static java.lang.Math.max;
|
||||
import static java.lang.Math.min;
|
||||
@@ -127,7 +127,7 @@ import static java.lang.Math.sqrt;
|
||||
* players using <code>player('*')</code>, which only returns players in current dimension, or use
|
||||
* <code>in_dimension(expr)</code> function.</p>
|
||||
*/
|
||||
public class CarpetExpression
|
||||
public class CarpetExpression
|
||||
{
|
||||
|
||||
private ServerCommandSource source;
|
||||
@@ -771,7 +771,7 @@ public class CarpetExpression
|
||||
booleanStateTest(c, "liquid", lv, (s, p) -> !s.getFluidState().isEmpty()));
|
||||
|
||||
this.expr.addLazyFunction("flammable", -1, (c, t, lv) ->
|
||||
booleanStateTest(c, "flammable", lv, (s, p) -> !s.getMaterial().isBurnable()));
|
||||
booleanStateTest(c, "flammable", lv, (s, p) -> s.getMaterial().isBurnable()));
|
||||
|
||||
this.expr.addLazyFunction("transparent", -1, (c, t, lv) ->
|
||||
booleanStateTest(c, "transparent", lv, (s, p) -> !s.getMaterial().isSolid()));
|
||||
@@ -970,27 +970,29 @@ public class CarpetExpression
|
||||
|
||||
if (sourceBlockState == targetBlockState && data == null)
|
||||
return (c_, t_) -> Value.FALSE;
|
||||
CarpetSettings.impendingFillSkipUpdates = !CarpetSettings.fillUpdates;
|
||||
BlockState finalSourceBlockState = sourceBlockState;
|
||||
BlockPos targetPos = targetLocator.block.getPos();
|
||||
Clearable.clear(world.getBlockEntity(targetPos));
|
||||
world.setBlockState(targetPos, sourceBlockState, 2);
|
||||
|
||||
if ( data != null)
|
||||
cc.s.getMinecraftServer().executeSync( () ->
|
||||
{
|
||||
BlockEntity be = world.getBlockEntity(targetPos);
|
||||
if (be != null)
|
||||
CarpetSettings.impendingFillSkipUpdates = !CarpetSettings.fillUpdates;
|
||||
Clearable.clear(world.getBlockEntity(targetPos));
|
||||
world.setBlockState(targetPos, finalSourceBlockState, 2);
|
||||
if (data != null)
|
||||
{
|
||||
CompoundTag destTag = data.copy();
|
||||
destTag.putInt("x", targetPos.getX());
|
||||
destTag.putInt("y", targetPos.getY());
|
||||
destTag.putInt("z", targetPos.getZ());
|
||||
be.fromTag(destTag);
|
||||
be.markDirty();
|
||||
BlockEntity be = world.getBlockEntity(targetPos);
|
||||
if (be != null)
|
||||
{
|
||||
CompoundTag destTag = data.copy();
|
||||
destTag.putInt("x", targetPos.getX());
|
||||
destTag.putInt("y", targetPos.getY());
|
||||
destTag.putInt("z", targetPos.getZ());
|
||||
be.fromTag(destTag);
|
||||
be.markDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CarpetSettings.impendingFillSkipUpdates = false;
|
||||
Value retval = new BlockValue(sourceBlockState, world, targetLocator.block.getPos());
|
||||
CarpetSettings.impendingFillSkipUpdates = false;
|
||||
});
|
||||
Value retval = new BlockValue(finalSourceBlockState, world, targetLocator.block.getPos());
|
||||
return (c_, t_) -> retval;
|
||||
});
|
||||
|
||||
@@ -2873,6 +2875,7 @@ public class CarpetExpression
|
||||
CarpetContext cc = (CarpetContext)c;
|
||||
BlockState targetBlock = null;
|
||||
BlockValue.VectorLocator pointLocator;
|
||||
boolean interactable = true;
|
||||
String name;
|
||||
try
|
||||
{
|
||||
@@ -2880,8 +2883,14 @@ public class CarpetExpression
|
||||
name = nameValue instanceof NullValue ? "" : nameValue.getString();
|
||||
pointLocator = BlockValue.locateVec(cc, lv, 1, true);
|
||||
if (lv.size()>pointLocator.offset)
|
||||
targetBlock = BlockValue.fromParams(cc, lv, pointLocator.offset, true).block.getBlockState();
|
||||
|
||||
{
|
||||
BlockValue.LocatorResult blockLocator = BlockValue.fromParams(cc, lv, pointLocator.offset, true, true);
|
||||
if (blockLocator.block != null) targetBlock = blockLocator.block.getBlockState();
|
||||
if (lv.size() > blockLocator.offset)
|
||||
{
|
||||
interactable = lv.get(blockLocator.offset).evalValue(c, Context.BOOLEAN).getBoolean();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IndexOutOfBoundsException e)
|
||||
{
|
||||
@@ -2909,6 +2918,7 @@ public class CarpetExpression
|
||||
armorstand.setNoGravity(true);
|
||||
armorstand.setInvisible(true);
|
||||
armorstand.setInvulnerable(true);
|
||||
armorstand.getDataTracker().set(ArmorStandEntity.ARMOR_STAND_FLAGS, (byte)(interactable?8 : 16|8));
|
||||
cc.s.getWorld().spawnEntity(armorstand);
|
||||
EntityValue result = new EntityValue(armorstand);
|
||||
return (_c, _t) -> result;
|
||||
@@ -2960,6 +2970,17 @@ public class CarpetExpression
|
||||
return (_c, _t) -> res; // pass through for variables
|
||||
});
|
||||
|
||||
//"overidden" native call to cancel if on main thread
|
||||
this.expr.addLazyFunction("join_task", 1, (c, t, lv) -> {
|
||||
if (((CarpetContext)c).s.getMinecraftServer().isOnThread())
|
||||
throw new InternalExpressionException("'join_task' cannot be called from main thread to avoid deadlocks");
|
||||
Value v = lv.get(0).evalValue(c);
|
||||
if (!(v instanceof ThreadValue))
|
||||
throw new InternalExpressionException("'join_task' could only be used with a task value");
|
||||
Value ret = ((ThreadValue) v).join();
|
||||
return (_c, _t) -> ret;
|
||||
});
|
||||
|
||||
this.expr.addLazyFunction("logger", 1, (c, t, lv) ->
|
||||
{
|
||||
Value res = lv.get(0).evalValue(c);
|
||||
@@ -2993,6 +3014,7 @@ public class CarpetExpression
|
||||
|
||||
this.expr.addLazyFunction("game_tick", -1, (c, t, lv) -> {
|
||||
ServerCommandSource s = ((CarpetContext)c).s;
|
||||
if (!s.getMinecraftServer().isOnThread()) throw new InternalExpressionException("Unable to run ticks from threads");
|
||||
((MinecraftServerInterface)s.getMinecraftServer()).forceTick( () -> System.nanoTime()- CarpetServer.scriptServer.tickStart<50000000L);
|
||||
if (lv.size()>0)
|
||||
{
|
||||
@@ -3019,7 +3041,7 @@ public class CarpetExpression
|
||||
|
||||
this.expr.addLazyFunction("current_dimension", 0, (c, t, lv) -> {
|
||||
ServerCommandSource s = ((CarpetContext)c).s;
|
||||
Value retval = new StringValue(nameFromRegistryId(Registry.DIMENSION.getId(s.getWorld().dimension.getType())));
|
||||
Value retval = new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.DIMENSION.getId(s.getWorld().dimension.getType())));
|
||||
return (cc, tt) -> retval;
|
||||
});
|
||||
|
||||
@@ -3075,12 +3097,19 @@ public class CarpetExpression
|
||||
if (lv.size() <= locator.offset)
|
||||
throw new InternalExpressionException("'plop' needs extra argument indicating what to plop");
|
||||
String what = lv.get(locator.offset).evalValue(c).getString();
|
||||
Boolean res = FeatureGenerator.spawn(what, ((CarpetContext)c).s.getWorld(), locator.block.getPos());
|
||||
if (res == null)
|
||||
return (c_, t_) -> Value.NULL;
|
||||
if (what.equalsIgnoreCase("boulder")) // there might be more of those
|
||||
this.forceChunkUpdate(locator.block.getPos(), ((CarpetContext)c).s.getWorld());
|
||||
return (c_, t_) -> new NumericValue(res);
|
||||
Value [] result = new Value[]{Value.NULL};
|
||||
((CarpetContext)c).s.getMinecraftServer().executeSync( () ->
|
||||
{
|
||||
|
||||
Boolean res = FeatureGenerator.spawn(what, ((CarpetContext) c).s.getWorld(), locator.block.getPos());
|
||||
if (res == null)
|
||||
return;
|
||||
if (what.equalsIgnoreCase("boulder")) // there might be more of those
|
||||
this.forceChunkUpdate(locator.block.getPos(), ((CarpetContext) c).s.getWorld());
|
||||
result[0] = new NumericValue(res);
|
||||
});
|
||||
Value ret = result[0]; // preventing from lazy evaluating of the result in case a future completes later
|
||||
return (_c, _t) -> ret;
|
||||
});
|
||||
|
||||
this.expr.addLazyFunction("schedule", -1, (c, t, lv) -> {
|
||||
@@ -3139,7 +3168,7 @@ public class CarpetExpression
|
||||
String file = null;
|
||||
if (lv.size()>1)
|
||||
{
|
||||
String origfile = lv.get(0).evalValue(c).getString();
|
||||
String origfile = lv.get(1).evalValue(c).getString();
|
||||
file = origfile.toLowerCase(Locale.ROOT).replaceAll("[^A-Za-z0-9]", "");
|
||||
if (file.isEmpty())
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@ import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
@@ -217,6 +218,35 @@ public class CarpetScriptHost extends ScriptHost
|
||||
super.onClose();
|
||||
if (this.saveTimeout > 0)
|
||||
dumpState();
|
||||
|
||||
FunctionValue closing = globalFunctions.get("__on_close");
|
||||
if (closing != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
callUDF(BlockPos.ORIGIN, CarpetServer.minecraft_server.getCommandSource(), closing, Collections.emptyList());
|
||||
}
|
||||
catch (InvalidCallbackException ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
userHosts.forEach((key, value) ->
|
||||
{
|
||||
FunctionValue userClosing = value.globalFunctions.get("__on_close");
|
||||
if (userClosing != null)
|
||||
{
|
||||
ServerPlayerEntity player = CarpetServer.minecraft_server.getPlayerManager().getPlayer(key);
|
||||
ServerCommandSource source = (player != null)?player.getCommandSource():CarpetServer.minecraft_server.getCommandSource();
|
||||
try
|
||||
{
|
||||
((CarpetScriptHost) value).callUDF(BlockPos.ORIGIN, source, userClosing, Collections.emptyList());
|
||||
}
|
||||
catch (InvalidCallbackException ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
String markerName = ExpressionInspector.MARKER_STRING+"_"+((getName()==null)?"":getName());
|
||||
for (ServerWorld world : CarpetServer.minecraft_server.getWorlds())
|
||||
{
|
||||
@@ -225,6 +255,7 @@ public class CarpetScriptHost extends ScriptHost
|
||||
e.remove();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void dumpState()
|
||||
@@ -239,9 +270,9 @@ public class CarpetScriptHost extends ScriptHost
|
||||
|
||||
public Tag getGlobalState(String file)
|
||||
{
|
||||
if (getName() == null || myCode.isInternal()) return null;
|
||||
if (getName() == null ) return null;
|
||||
if (file != null)
|
||||
myCode.getData(file);
|
||||
return myCode.getData(file);
|
||||
if (parent == null)
|
||||
return globalState;
|
||||
return ((CarpetScriptHost)parent).globalState;
|
||||
@@ -249,7 +280,7 @@ public class CarpetScriptHost extends ScriptHost
|
||||
|
||||
public void setGlobalState(Tag tag, String file)
|
||||
{
|
||||
if (getName() == null || myCode.isInternal()) return;
|
||||
if (getName() == null ) return;
|
||||
|
||||
if (file!= null)
|
||||
{
|
||||
|
||||
@@ -38,12 +38,12 @@ public class CarpetScriptServer
|
||||
//make static for now, but will change that later:
|
||||
public CarpetScriptHost globalHost;
|
||||
public Map<String, CarpetScriptHost> modules;
|
||||
long tickStart;
|
||||
public long tickStart;
|
||||
public boolean stopAll;
|
||||
Set<String> holyMoly;
|
||||
private Set<String> holyMoly;
|
||||
public CarpetEventServer events;
|
||||
|
||||
public static List<ModuleInterface> bundledModuleData = new ArrayList<ModuleInterface>(){{
|
||||
private static List<ModuleInterface> bundledModuleData = new ArrayList<ModuleInterface>(){{
|
||||
add(new BundledModule("camera"));
|
||||
add(new BundledModule("event_test"));
|
||||
}};
|
||||
@@ -72,7 +72,7 @@ public class CarpetScriptServer
|
||||
|
||||
}
|
||||
|
||||
ModuleInterface getModule(String name)
|
||||
private ModuleInterface getModule(String name)
|
||||
{
|
||||
File folder = CarpetServer.minecraft_server.getLevelStorage().resolveFile(
|
||||
CarpetServer.minecraft_server.getLevelName(), "scripts");
|
||||
@@ -218,25 +218,6 @@ public class CarpetScriptServer
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private void addEvents(ServerCommandSource source, String hostName)
|
||||
{
|
||||
if (1+2 == 3) throw new RuntimeException("This should run when code is evaluated");
|
||||
ScriptHost host = modules.get(hostName);
|
||||
if (host == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (String fun : host.globalFunctions.keySet())
|
||||
{
|
||||
if (!fun.startsWith("__on_"))
|
||||
continue;
|
||||
String event = fun.replaceFirst("__on_","");
|
||||
if (!CarpetEventServer.Event.byName.containsKey(event))
|
||||
continue;
|
||||
events.addEvent(event, hostName, fun);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void addCommand(ServerCommandSource source, String hostName)
|
||||
{
|
||||
@@ -261,7 +242,9 @@ public class CarpetScriptServer
|
||||
requires((player) -> modules.containsKey(hostName)).
|
||||
executes( (c) ->
|
||||
{
|
||||
Messenger.m(c.getSource(), "gi "+modules.get(hostName).retrieveForExecution(c.getSource()).call(c.getSource(),"__command", null, ""));
|
||||
String response = modules.get(hostName).retrieveForExecution(c.getSource()).
|
||||
call(c.getSource(),"__command", null, "");
|
||||
if (!response.isEmpty()) Messenger.m(c.getSource(), "gi "+response);
|
||||
return 1;
|
||||
});
|
||||
|
||||
@@ -271,28 +254,16 @@ public class CarpetScriptServer
|
||||
then(literal(function).
|
||||
requires((player) -> modules.containsKey(hostName) && modules.get(hostName).getPublicFunctions().contains(function)).
|
||||
executes( (c) -> {
|
||||
Messenger.m(
|
||||
c.getSource(),
|
||||
"gi "+modules.get(hostName).retrieveForExecution(c.getSource()).call(
|
||||
c.getSource(),
|
||||
function,
|
||||
null,
|
||||
""
|
||||
)
|
||||
);
|
||||
String response = modules.get(hostName).retrieveForExecution(c.getSource()).
|
||||
call(c.getSource(), function,null,"");
|
||||
if (!response.isEmpty()) Messenger.m(c.getSource(),"gi "+response);
|
||||
return 1;
|
||||
}).
|
||||
then(argument("args...", StringArgumentType.greedyString()).
|
||||
executes( (c) -> {
|
||||
Messenger.m(
|
||||
c.getSource(),
|
||||
"gi "+modules.get(hostName).retrieveForExecution(c.getSource()).call(
|
||||
c.getSource(),
|
||||
function,
|
||||
null,
|
||||
StringArgumentType.getString(c, "args...")
|
||||
)
|
||||
);
|
||||
String response = modules.get(hostName).retrieveForExecution(c.getSource()).
|
||||
call(c.getSource(), function,null, StringArgumentType.getString(c, "args..."));
|
||||
if (!response.isEmpty()) Messenger.m(c.getSource(), "gi "+response);
|
||||
return 1;
|
||||
})));
|
||||
}
|
||||
|
||||
@@ -6,16 +6,16 @@ import java.util.Set;
|
||||
|
||||
public class Context
|
||||
{
|
||||
static final int NONE = 0;
|
||||
static final int VOID = 1;
|
||||
static final int BOOLEAN = 2;
|
||||
static final int NUMBER = 3;
|
||||
static final int STRING = 4;
|
||||
static final int LIST = 5;
|
||||
static final int ITERATOR = 6;
|
||||
static final int SIGNATURE = 7;
|
||||
static final int LOCALIZATION = 8;
|
||||
static final int LVALUE = 9;
|
||||
public static final int NONE = 0;
|
||||
public static final int VOID = 1;
|
||||
public static final int BOOLEAN = 2;
|
||||
public static final int NUMBER = 3;
|
||||
public static final int STRING = 4;
|
||||
public static final int LIST = 5;
|
||||
public static final int ITERATOR = 6;
|
||||
public static final int SIGNATURE = 7;
|
||||
public static final int LOCALIZATION = 8;
|
||||
public static final int LVALUE = 9;
|
||||
|
||||
public Map<String, LazyValue> variables = new HashMap<>();
|
||||
|
||||
|
||||
@@ -11,7 +11,13 @@ import carpet.script.Fluff.QuadFunction;
|
||||
import carpet.script.Fluff.QuinnFunction;
|
||||
import carpet.script.Fluff.SexFunction;
|
||||
import carpet.script.Fluff.TriFunction;
|
||||
import carpet.script.exception.*;
|
||||
import carpet.script.exception.BreakStatement;
|
||||
import carpet.script.exception.ContinueStatement;
|
||||
import carpet.script.exception.ExitStatement;
|
||||
import carpet.script.exception.ExpressionException;
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import carpet.script.exception.ReturnStatement;
|
||||
import carpet.script.exception.ThrowStatement;
|
||||
import carpet.script.value.AbstractListValue;
|
||||
import carpet.script.value.ContainerValueInterface;
|
||||
import carpet.script.value.FunctionSignatureValue;
|
||||
@@ -23,6 +29,7 @@ import carpet.script.value.ListValue;
|
||||
import carpet.script.value.MapValue;
|
||||
import carpet.script.value.NumericValue;
|
||||
import carpet.script.value.StringValue;
|
||||
import carpet.script.value.ThreadValue;
|
||||
import carpet.script.value.Value;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import org.apache.commons.lang3.text.WordUtils;
|
||||
@@ -1191,16 +1198,14 @@ public class Expression implements Cloneable
|
||||
{
|
||||
Value v1 = lv1.evalValue(c, Context.BOOLEAN);
|
||||
if (!v1.getBoolean()) return (cc, tt) -> v1;
|
||||
Value v2 = lv2.evalValue(c, Context.BOOLEAN);
|
||||
return v2.getBoolean() ? ((cc, tt) -> v2) : LazyValue.FALSE;
|
||||
return lv2;
|
||||
});
|
||||
|
||||
addLazyBinaryOperator("||", precedence.get("or||"), false, (c, t, lv1, lv2) ->
|
||||
{
|
||||
Value v1 = lv1.evalValue(c, Context.BOOLEAN);
|
||||
if (v1.getBoolean()) return (cc, tt) -> v1;
|
||||
Value v2 = lv2.evalValue(c, Context.BOOLEAN);
|
||||
return v2.getBoolean() ? ((cc, tt) -> v2) : LazyValue.FALSE;
|
||||
return lv2;
|
||||
});
|
||||
|
||||
addBinaryOperator("~", precedence.get("attribute~:"), true, Value::in);
|
||||
@@ -1921,7 +1926,7 @@ public class Expression implements Cloneable
|
||||
LazyValue expr = lv.get(1);
|
||||
//scoping
|
||||
LazyValue _val = c.getVariable("_");
|
||||
LazyValue _iter = c.getVariable("_i");
|
||||
LazyValue _ite = c.getVariable("_i");
|
||||
int successCount = 0;
|
||||
for (int i=0; iterator.hasNext(); i++)
|
||||
{
|
||||
@@ -1952,7 +1957,7 @@ public class Expression implements Cloneable
|
||||
//revering scope
|
||||
((AbstractListValue) rval).fatality();
|
||||
c.setVariable("_", _val);
|
||||
c.setVariable("_i", _iter);
|
||||
c.setVariable("_i", _ite);
|
||||
long promiseWontChange = successCount;
|
||||
return (cc, tt) -> new NumericValue(promiseWontChange);
|
||||
});
|
||||
@@ -1981,15 +1986,18 @@ public class Expression implements Cloneable
|
||||
//scoping
|
||||
LazyValue _val = c.getVariable("_");
|
||||
LazyValue _acc = c.getVariable("_a");
|
||||
LazyValue _ite = c.getVariable("_i");
|
||||
|
||||
while (iterator.hasNext())
|
||||
for (int i=0; iterator.hasNext(); i++)
|
||||
{
|
||||
Value next = iterator.next();
|
||||
String var = next.boundVariable;
|
||||
next.bindTo("_");
|
||||
Value promiseWontChangeYou = acc;
|
||||
int seriously = i;
|
||||
c.setVariable("_a", (cc, tt) -> promiseWontChangeYou.bindTo("_a"));
|
||||
c.setVariable("_", (cc, tt) -> next);
|
||||
c.setVariable("_i", (cc, tt) -> new NumericValue(seriously).bindTo("_i"));
|
||||
try
|
||||
{
|
||||
acc = expr.evalValue(c, t);
|
||||
@@ -2009,6 +2017,7 @@ public class Expression implements Cloneable
|
||||
((AbstractListValue) rval).fatality();
|
||||
c.setVariable("_a", _acc);
|
||||
c.setVariable("_", _val);
|
||||
c.setVariable("_i", _ite);
|
||||
|
||||
Value hopeItsEnoughPromise = acc;
|
||||
return (cc, tt) -> hopeItsEnoughPromise;
|
||||
@@ -2992,6 +3001,57 @@ public class Expression implements Cloneable
|
||||
return (cc, tt) -> retval;
|
||||
});
|
||||
|
||||
addLazyFunctionWithDelegation("task", -1, (c, t, expr, tok, lv) -> {
|
||||
if (lv.size() == 0)
|
||||
throw new InternalExpressionException("'task' requires at least function to call as a parameter");
|
||||
Value funcDesc = lv.get(0).evalValue(c);
|
||||
if (!(funcDesc instanceof FunctionValue))
|
||||
{
|
||||
String name = funcDesc.getString();
|
||||
funcDesc = c.host.globalFunctions.get(name);
|
||||
if (funcDesc == null)
|
||||
throw new InternalExpressionException("Function "+name+" is not defined yet");
|
||||
}
|
||||
FunctionValue fun = (FunctionValue)funcDesc;
|
||||
int extraargs = lv.size() - fun.getArguments().size();
|
||||
if (extraargs != 1 && extraargs != 2)
|
||||
{
|
||||
throw new InternalExpressionException("Function takes "+fun.getArguments().size()+" arguments.");
|
||||
}
|
||||
List<LazyValue> lvargs = new ArrayList<>();
|
||||
for (int i=0; i< fun.getArguments().size(); i++)
|
||||
{
|
||||
lvargs.add(lv.get(i+1));
|
||||
}
|
||||
Value queue = Value.NULL;
|
||||
if (extraargs == 2) queue = lv.get(lv.size()-1).evalValue(c);
|
||||
ThreadValue thread = new ThreadValue(queue, fun, expr, tok, c, lvargs);
|
||||
Thread.yield();
|
||||
return (cc, tt) -> thread;
|
||||
});
|
||||
|
||||
addFunction("task_count", (lv) ->
|
||||
{
|
||||
if (lv.size() > 0)
|
||||
{
|
||||
return new NumericValue(ThreadValue.taskCount(lv.get(0)));
|
||||
}
|
||||
return new NumericValue(ThreadValue.taskCount());
|
||||
});
|
||||
|
||||
addUnaryFunction("join_task", (v) -> {
|
||||
if (!(v instanceof ThreadValue))
|
||||
throw new InternalExpressionException("'join_task' could only be used with a task value");
|
||||
return ((ThreadValue) v).join();
|
||||
});
|
||||
|
||||
addUnaryFunction("task_completed", (v) -> {
|
||||
if (!(v instanceof ThreadValue))
|
||||
throw new InternalExpressionException("'task_completed' could only be used with a task value");
|
||||
return new NumericValue(((ThreadValue) v).isFinished());
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
static Expression none = new Expression("null");
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
public class ScriptHost
|
||||
{
|
||||
private final Map<String, ScriptHost> userHosts = new Object2ObjectOpenHashMap<>();
|
||||
protected final Map<String, ScriptHost> userHosts = new Object2ObjectOpenHashMap<>();
|
||||
public Map<String, FunctionValue> globalFunctions = new Object2ObjectOpenHashMap<>();
|
||||
public Map<String, LazyValue> globalVariables = new Object2ObjectOpenHashMap<>();
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ public class FileModule implements ModuleInterface
|
||||
}
|
||||
|
||||
//copied private method from net.minecraft.nbt.NbtIo.read()
|
||||
private static Tag read(File file)
|
||||
public static Tag read(File file)
|
||||
{
|
||||
try (DataInputStream dataInput_1 = new DataInputStream(new FileInputStream(file)))
|
||||
{
|
||||
@@ -78,7 +78,7 @@ public class FileModule implements ModuleInterface
|
||||
}
|
||||
|
||||
//copied private method from net.minecraft.nbt.NbtIo.write() and client method safe_write
|
||||
private static void write(Tag tag_1, File file)
|
||||
public static void write(Tag tag_1, File file)
|
||||
{
|
||||
File file_2 = new File(file.getAbsolutePath() + "_tmp");
|
||||
if (file_2.exists()) file_2.delete();
|
||||
@@ -99,23 +99,4 @@ public class FileModule implements ModuleInterface
|
||||
if (file.exists()) file.delete();
|
||||
if (!file.exists()) file_2.renameTo(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag getData(String file)
|
||||
{
|
||||
File dataFile =CarpetServer.minecraft_server.getLevelStorage().resolveFile(
|
||||
CarpetServer.minecraft_server.getLevelName(), "scripts/"+name+".data"+(file==null?"":"."+file)+".nbt");
|
||||
if (!(dataFile.isFile()))
|
||||
return null;
|
||||
return read(dataFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveData(String file, Tag globalState)
|
||||
{
|
||||
File dataFile =CarpetServer.minecraft_server.getLevelStorage().resolveFile(
|
||||
CarpetServer.minecraft_server.getLevelName(), "scripts/"+name+".data"+(file==null?"":"."+file)+".nbt");
|
||||
write(globalState, dataFile);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,44 @@
|
||||
package carpet.script.bundled;
|
||||
|
||||
import carpet.CarpetServer;
|
||||
import net.minecraft.nbt.Tag;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
||||
import static carpet.script.bundled.FileModule.read;
|
||||
import static carpet.script.bundled.FileModule.write;
|
||||
|
||||
public interface ModuleInterface
|
||||
{
|
||||
String getName();
|
||||
String getCode();
|
||||
default boolean isInternal() {return true; }
|
||||
default Tag getData(String file) {return null; }
|
||||
default void saveData(String file, Tag globalState) {}
|
||||
|
||||
default Tag getData(String file)
|
||||
{
|
||||
File dataFile = CarpetServer.minecraft_server.getLevelStorage().resolveFile(
|
||||
CarpetServer.minecraft_server.getLevelName(), "scripts/"+getName()+".data"+(file==null?"":"."+file)+".nbt");
|
||||
if (!Files.exists(dataFile.toPath()) || !(dataFile.isFile())) return null;
|
||||
return read(dataFile);
|
||||
}
|
||||
|
||||
default void saveData(String file, Tag globalState)
|
||||
{
|
||||
File dataFile =CarpetServer.minecraft_server.getLevelStorage().resolveFile(
|
||||
CarpetServer.minecraft_server.getLevelName(), "scripts/"+getName()+".data"+(file==null?"":"."+file)+".nbt");
|
||||
if (!Files.exists(dataFile.toPath().getParent()))
|
||||
{
|
||||
try
|
||||
{
|
||||
Files.createDirectory(dataFile.toPath().getParent());
|
||||
}
|
||||
catch (IOException ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
write(globalState, dataFile);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.WorldChunk;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@@ -129,15 +130,24 @@ public class BlockValue extends Value
|
||||
|
||||
public static LocatorResult fromParams(CarpetContext c, List<LazyValue> params, int offset)
|
||||
{
|
||||
return fromParams(c, params,offset, false);
|
||||
return fromParams(c, params,offset, false, false);
|
||||
}
|
||||
|
||||
public static LocatorResult fromParams(CarpetContext c, List<LazyValue> params, int offset, boolean acceptString)
|
||||
{
|
||||
return fromParams(c, params,offset, acceptString, false);
|
||||
}
|
||||
|
||||
public static LocatorResult fromParams(CarpetContext c, List<LazyValue> params, int offset, boolean acceptString, boolean optional)
|
||||
{
|
||||
try
|
||||
{
|
||||
Value v1 = params.get(0 + offset).evalValue(c);
|
||||
//add conditional from string name
|
||||
if (optional && v1 instanceof NullValue)
|
||||
{
|
||||
return new LocatorResult(null, 1+offset);
|
||||
}
|
||||
if (acceptString && v1 instanceof StringValue)
|
||||
{
|
||||
return new LocatorResult(fromString(v1.getString()), 1+offset);
|
||||
@@ -192,6 +202,15 @@ public class BlockValue extends Value
|
||||
throw new InternalExpressionException("Attempted to fetch block state without world or stored block state");
|
||||
}
|
||||
|
||||
public static BlockEntity getBlockEntity(ServerWorld world, BlockPos pos)
|
||||
{
|
||||
if (world.getServer().isOnThread())
|
||||
return world.getBlockEntity(pos);
|
||||
else
|
||||
return world.getWorldChunk(pos).getBlockEntity(pos, WorldChunk.CreationType.IMMEDIATE);
|
||||
}
|
||||
|
||||
|
||||
public CompoundTag getData()
|
||||
{
|
||||
if (data != null)
|
||||
@@ -202,7 +221,7 @@ public class BlockValue extends Value
|
||||
}
|
||||
if (world != null && pos != null)
|
||||
{
|
||||
BlockEntity be = world.getBlockEntity(pos);
|
||||
BlockEntity be = getBlockEntity(world, pos);
|
||||
CompoundTag tag = new CompoundTag();
|
||||
if (be == null)
|
||||
{
|
||||
|
||||
@@ -223,7 +223,7 @@ public class EntityValue extends Value
|
||||
put("dimension", (e, a) -> new StringValue(nameFromRegistryId(Registry.DIMENSION.getId(e.dimension))));
|
||||
put("height", (e, a) -> new NumericValue(e.getDimensions(EntityPose.STANDING).height));
|
||||
put("width", (e, a) -> new NumericValue(e.getDimensions(EntityPose.STANDING).width));
|
||||
put("eye_height", (e, a) -> new NumericValue(e.getEyeHeight(EntityPose.STANDING)));
|
||||
put("eye_height", (e, a) -> new NumericValue(e.getStandingEyeHeight()));
|
||||
put("age", (e, a) -> new NumericValue(e.age));
|
||||
put("despawn_timer", (e, a) -> e instanceof LivingEntity?new NumericValue(((LivingEntity) e).getDespawnCounter()):Value.NULL);
|
||||
put("item", (e, a) -> (e instanceof ItemEntity)?ListValue.fromItemStack(((ItemEntity) e).getStack()):Value.NULL);
|
||||
@@ -273,6 +273,22 @@ public class EntityValue extends Value
|
||||
}
|
||||
return Value.NULL;
|
||||
});
|
||||
|
||||
put("permission_level", (e, a) -> {
|
||||
if (e instanceof ServerPlayerEntity)
|
||||
{
|
||||
ServerPlayerEntity spe = (ServerPlayerEntity) e;
|
||||
for (int i=4; i>=0; i--)
|
||||
{
|
||||
if (spe.allowsPermissionLevel(i))
|
||||
return new NumericValue(i);
|
||||
|
||||
}
|
||||
return new NumericValue(0);
|
||||
}
|
||||
return Value.NULL;
|
||||
});
|
||||
|
||||
//spectating_entity
|
||||
// isGlowing
|
||||
put("effect", (e, a) ->
|
||||
@@ -743,6 +759,39 @@ public class EntityValue extends Value
|
||||
else
|
||||
e.noClip = v.getBoolean();
|
||||
});
|
||||
put("effect", (e, v) ->
|
||||
{
|
||||
if (!(e instanceof LivingEntity)) return;
|
||||
LivingEntity le = (LivingEntity)e;
|
||||
if (v == null)
|
||||
le.clearPotionEffects();
|
||||
else if (v instanceof ListValue)
|
||||
{
|
||||
List<Value> lv = ((ListValue) v).getItems();
|
||||
if (lv.size() >= 2 && lv.size() <= 5)
|
||||
{
|
||||
String effectName = lv.get(0).getString();
|
||||
if (effectName.startsWith("minecraft:"))
|
||||
effectName = "minecraft:"+effectName;
|
||||
StatusEffect effect = Registry.STATUS_EFFECT.get(new Identifier(effectName));
|
||||
if (effect == null)
|
||||
throw new InternalExpressionException("Wrong effect name: "+effectName);
|
||||
int duration = (int)NumericValue.asNumber(lv.get(1)).getLong();
|
||||
int amplifier = 0;
|
||||
if (lv.size() > 2)
|
||||
amplifier = (int)NumericValue.asNumber(lv.get(2)).getLong();
|
||||
boolean showParticles = true;
|
||||
if (lv.size() > 3)
|
||||
showParticles = lv.get(3).getBoolean();
|
||||
boolean showIcon = true;
|
||||
if (lv.size() > 4)
|
||||
showIcon = lv.get(4).getBoolean();
|
||||
le.addPotionEffect(new StatusEffectInstance(effect, duration, amplifier, showParticles, showIcon));
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new InternalExpressionException("'effect' needs either no arguments (clear) or effect name, duration, and optional amplifier, show particles and show icon");
|
||||
});
|
||||
|
||||
// gamemode
|
||||
// spectate
|
||||
|
||||
@@ -246,7 +246,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
|
||||
return items;
|
||||
}
|
||||
|
||||
public Iterator<Value> iterator() { return new ArrayList<>(items).iterator(); }
|
||||
public Iterator<Value> iterator() { return new ArrayList<>(items).iterator(); } // should be thread safe
|
||||
|
||||
public void extend(List<Value> subList)
|
||||
{
|
||||
|
||||
@@ -5,6 +5,12 @@ import carpet.script.LazyValue;
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
import com.mojang.brigadier.StringReader;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ChestBlock;
|
||||
import net.minecraft.block.InventoryProvider;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.block.entity.ChestBlockEntity;
|
||||
import net.minecraft.block.entity.HopperBlockEntity;
|
||||
import net.minecraft.command.arguments.ItemStackArgument;
|
||||
import net.minecraft.command.arguments.ItemStringReader;
|
||||
@@ -21,8 +27,12 @@ import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.StringNbtReader;
|
||||
import net.minecraft.nbt.StringTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.predicate.entity.EntityPredicates;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Box;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
@@ -116,6 +126,41 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
return copy;
|
||||
}
|
||||
|
||||
// stolen from HopperBlockEntity, adjusted for threaded operation
|
||||
public static Inventory getInventoryAt(ServerWorld world, BlockPos blockPos)
|
||||
{
|
||||
Inventory inventory = null;
|
||||
BlockState blockState = world.getBlockState(blockPos);
|
||||
Block block = blockState.getBlock();
|
||||
if (block instanceof InventoryProvider) {
|
||||
inventory = ((InventoryProvider)block).getInventory(blockState, world, blockPos);
|
||||
} else if (block.hasBlockEntity()) {
|
||||
BlockEntity blockEntity = BlockValue.getBlockEntity(world, blockPos);
|
||||
if (blockEntity instanceof Inventory) {
|
||||
inventory = (Inventory)blockEntity;
|
||||
if (inventory instanceof ChestBlockEntity && block instanceof ChestBlock) {
|
||||
inventory = ChestBlock.getInventory(blockState, world, blockPos, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inventory == null) {
|
||||
List<Entity> list = world.getEntities(
|
||||
(Entity)null,
|
||||
new Box(
|
||||
blockPos.getX() - 0.5D, blockPos.getY() - 0.5D, blockPos.getZ() - 0.5D,
|
||||
blockPos.getX() + 0.5D, blockPos.getY() + 0.5D, blockPos.getZ() + 0.5D),
|
||||
EntityPredicates.VALID_INVENTORIES
|
||||
);
|
||||
if (!list.isEmpty()) {
|
||||
inventory = (Inventory)list.get(world.random.nextInt(list.size()));
|
||||
}
|
||||
}
|
||||
|
||||
return inventory;
|
||||
}
|
||||
|
||||
|
||||
public static InventoryLocator locateInventory(CarpetContext c, List<LazyValue> params, int offset)
|
||||
{
|
||||
try
|
||||
@@ -139,7 +184,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
BlockPos pos = ((BlockValue) v1).getPos();
|
||||
if (pos == null)
|
||||
throw new InternalExpressionException("Block to access inventory needs to be positioned in the world");
|
||||
inv = HopperBlockEntity.getInventoryAt(c.s.getWorld(), pos);
|
||||
inv = getInventoryAt(c.s.getWorld(), pos);
|
||||
if (inv == null)
|
||||
return null;
|
||||
return new InventoryLocator(pos, pos, inv, offset + 1);
|
||||
@@ -151,7 +196,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
NumericValue.asNumber(args.get(0)).getDouble(),
|
||||
NumericValue.asNumber(args.get(1)).getDouble(),
|
||||
NumericValue.asNumber(args.get(2)).getDouble());
|
||||
inv = HopperBlockEntity.getInventoryAt(c.s.getWorld(), pos);
|
||||
inv = getInventoryAt(c.s.getWorld(), pos);
|
||||
if (inv == null)
|
||||
return null;
|
||||
return new InventoryLocator(pos, pos, inv, offset + 1);
|
||||
@@ -160,7 +205,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
||||
NumericValue.asNumber(v1).getDouble(),
|
||||
NumericValue.asNumber(params.get(1 + offset).evalValue(c)).getDouble(),
|
||||
NumericValue.asNumber(params.get(2 + offset).evalValue(c)).getDouble());
|
||||
inv = HopperBlockEntity.getInventoryAt(c.s.getWorld(), pos);
|
||||
inv = getInventoryAt(c.s.getWorld(), pos);
|
||||
if (inv == null)
|
||||
return null;
|
||||
return new InventoryLocator(pos, pos, inv, offset + 3);
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package carpet.script.value;
|
||||
|
||||
import carpet.script.Context;
|
||||
import carpet.script.Expression;
|
||||
import carpet.script.LazyValue;
|
||||
import carpet.script.Tokenizer;
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
public class ThreadValue extends Value
|
||||
{
|
||||
private CompletableFuture<Value> taskFuture;
|
||||
private long id;
|
||||
private static long sequence = 0L;
|
||||
private static final Map<Value,ThreadPoolExecutor> executorServices = new HashMap<>();
|
||||
|
||||
public ThreadValue(Value pool, FunctionValue function, Expression expr, Tokenizer.Token token, Context ctx, List<LazyValue> args)
|
||||
{
|
||||
id = sequence++;
|
||||
taskFuture = CompletableFuture.supplyAsync(
|
||||
() -> function.lazyEval(ctx, Context.NONE, expr, token, args).evalValue(ctx),
|
||||
executorServices.computeIfAbsent(pool, (v) -> (ThreadPoolExecutor)Executors.newCachedThreadPool())
|
||||
);
|
||||
Thread.yield();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString()
|
||||
{
|
||||
return taskFuture.getNow(Value.NULL).getString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean()
|
||||
{
|
||||
return taskFuture.getNow(Value.NULL).getBoolean();
|
||||
}
|
||||
|
||||
public Value join()
|
||||
{
|
||||
try
|
||||
{
|
||||
return taskFuture.get();
|
||||
}
|
||||
catch (InterruptedException | ExecutionException e)
|
||||
{
|
||||
return Value.NULL;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFinished()
|
||||
{
|
||||
return taskFuture.isDone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (!(o instanceof ThreadValue))
|
||||
return false;
|
||||
return ((ThreadValue) o).id == this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Value o)
|
||||
{
|
||||
if (!(o instanceof ThreadValue))
|
||||
throw new InternalExpressionException("Cannot compare tasks to other types");
|
||||
return (int) (this.id - ((ThreadValue) o).id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Long.hashCode(id);
|
||||
}
|
||||
|
||||
public static int taskCount()
|
||||
{
|
||||
return executorServices.values().stream().map(ThreadPoolExecutor::getActiveCount).reduce(0, Integer::sum);
|
||||
}
|
||||
|
||||
public static int taskCount(Value pool)
|
||||
{
|
||||
if (executorServices.containsKey(pool))
|
||||
{
|
||||
return executorServices.get(pool).getActiveCount();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -110,7 +110,7 @@ public abstract class Value implements Comparable<Value>, Cloneable
|
||||
@Override
|
||||
public int compareTo(final Value o)
|
||||
{
|
||||
if (o instanceof NumericValue || o instanceof ListValue)
|
||||
if (o instanceof NumericValue || o instanceof ListValue || o instanceof ThreadValue)
|
||||
{
|
||||
return -o.compareTo(this);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user