diff --git a/src/main/java/de/blazemcworld/fireflow/code/CodeEvaluator.java b/src/main/java/de/blazemcworld/fireflow/code/CodeEvaluator.java index 530e441..da50c6b 100644 --- a/src/main/java/de/blazemcworld/fireflow/code/CodeEvaluator.java +++ b/src/main/java/de/blazemcworld/fireflow/code/CodeEvaluator.java @@ -18,6 +18,7 @@ import de.blazemcworld.fireflow.code.widget.WidgetVec; import de.blazemcworld.fireflow.space.PlayWorld; import de.blazemcworld.fireflow.space.Space; +import de.blazemcworld.fireflow.space.SpaceManager; import de.blazemcworld.fireflow.util.DummyPlayer; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.damage.DamageSource; @@ -206,6 +207,7 @@ public boolean onUseItem(ServerPlayerEntity player, ItemStack stack, Hand hand) } public void exitPlay(ServerPlayerEntity player) { + SpaceManager.getSpaceForPlayer(player).bossBarManager.clearBossBars(player); for (Node node : nodes) { if (node instanceof OnPlayerLeaveNode n) { n.onLeave(this, player); diff --git a/src/main/java/de/blazemcworld/fireflow/code/node/NodeList.java b/src/main/java/de/blazemcworld/fireflow/code/node/NodeList.java index 22e648d..1b9dbdd 100644 --- a/src/main/java/de/blazemcworld/fireflow/code/node/NodeList.java +++ b/src/main/java/de/blazemcworld/fireflow/code/node/NodeList.java @@ -3,6 +3,10 @@ import de.blazemcworld.fireflow.FireFlow; import de.blazemcworld.fireflow.code.CodeEditor; import de.blazemcworld.fireflow.code.node.impl.condition.*; +import de.blazemcworld.fireflow.code.node.impl.number.constants.EulersNode; +import de.blazemcworld.fireflow.code.node.impl.number.constants.GoldenRatioNode; +import de.blazemcworld.fireflow.code.node.impl.number.constants.PiNode; +import de.blazemcworld.fireflow.code.node.impl.number.constants.TauNode; import de.blazemcworld.fireflow.code.node.impl.control.*; import de.blazemcworld.fireflow.code.node.impl.dictionary.*; import de.blazemcworld.fireflow.code.node.impl.entity.*; @@ -25,6 +29,9 @@ import de.blazemcworld.fireflow.code.node.impl.player.movement.*; import de.blazemcworld.fireflow.code.node.impl.player.statistic.*; import de.blazemcworld.fireflow.code.node.impl.player.visual.*; +import de.blazemcworld.fireflow.code.node.impl.player.visual.bossbar.ClearBossbarsNode; +import de.blazemcworld.fireflow.code.node.impl.player.visual.bossbar.RemoveBossbarNode; +import de.blazemcworld.fireflow.code.node.impl.player.visual.bossbar.SetBossbarNode; import de.blazemcworld.fireflow.code.node.impl.position.*; import de.blazemcworld.fireflow.code.node.impl.string.*; import de.blazemcworld.fireflow.code.node.impl.text.CombineTextsNode; @@ -170,15 +177,27 @@ public static void init() { .add(new TrimListNode<>(null)) ) .add(new Category("Number", Items.CLOCK) + .add(new Category("Math Constants", Items.TARGET) + .add(new EulersNode()) + .add(new GoldenRatioNode()) + .add(new PiNode()) + .add(new TauNode()) + ) .add(new AbsoluteNumberNode()) .add(new AddNumbersNode()) + .add(new AverageNumberNode()) .add(new BasicNoiseNode()) .add(new ClampNumberNode()) + .add(new CosineNode()) .add(new DivideNumbersNode()) + .add(new GaussianDistributionNode()) .add(new GreaterEqualNode()) .add(new GreaterThanNode()) + .add(new LerpNumbersNode()) .add(new LessEqualNode()) .add(new LessThanNode()) + .add(new MaxNumberNode()) + .add(new MinNumberNode()) .add(new ModuloNode()) .add(new MultiplyNumbersNode()) .add(new ParseNumberNode()) @@ -186,8 +205,10 @@ public static void init() { .add(new RemainderNode()) .add(new RoundNumberNode()) .add(new SetToExponentialNode()) + .add(new SineNode()) .add(new SquareRootNode()) .add(new SubtractNumbersNode()) + .add(new TangentNode()) ) .add(new Category("Player", Items.PLAYER_HEAD) .add(new Category("Gameplay", Items.GRASS_BLOCK) @@ -213,6 +234,7 @@ public static void init() { .add(new PlayerHasItemNode()) .add(new PlayerItemHasCooldownNode()) .add(new SetHeldSlotNode()) + .add(new SetPlayerArmorNode()) .add(new SetPlayerInventoryNode()) .add(new SetPlayerInventorySlotNode()) .add(new SetPlayerItemCooldownNode()) @@ -221,6 +243,7 @@ public static void init() { ) .add(new Category("Meta", Items.COMMAND_BLOCK) .add(new GetPlayerNameNode()) + .add(new GetPlayerPingNode()) .add(new GetPlayerUUIDNode()) .add(new IsPlayingNode()) .add(new KickPlayerNode()) @@ -254,6 +277,11 @@ public static void init() { .add(new SetPlayerSaturationNode()) ) .add(new Category("Visual", Items.ENDER_PEARL) + .add(new Category("Bossbar", Items.ENDER_DRAGON_SPAWN_EGG) + .add(new SetBossbarNode()) + .add(new RemoveBossbarNode()) + .add(new ClearBossbarsNode()) + ) .add(new BroadcastNode()) .add(new SendActionbarNode()) .add(new SendBlockChangeNode()) @@ -297,7 +325,9 @@ public static void init() { ) .add(new Category("Vector", Items.ARROW) .add(new AddVectorsNode()) + .add(new DotProductNode()) .add(new GetVectorComponentNode()) + .add(new GetVectorLengthNode()) .add(new PackVectorNode()) .add(new ReflectVectorNode()) .add(new RoundVectorAxesNode()) @@ -318,6 +348,7 @@ public static void init() { .add(new SetBlockNode()) .add(new SetBlockTagNode<>(null)) .add(new SetRegionNode()) + .add(new TimestampNode()) ) .add(new Category("Function", Items.COMMAND_BLOCK).markFunctions()) .finish(); diff --git a/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/AverageNumberNode.java b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/AverageNumberNode.java new file mode 100644 index 0000000..bf60eed --- /dev/null +++ b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/AverageNumberNode.java @@ -0,0 +1,29 @@ +package de.blazemcworld.fireflow.code.node.impl.number; + +import de.blazemcworld.fireflow.code.node.Node; +import de.blazemcworld.fireflow.code.type.NumberType; +import net.minecraft.item.Items; + +public class AverageNumberNode extends Node { + + public AverageNumberNode() { + super("average_number", "Average Number", "Returns the average number of a set.", Items.RAW_COPPER); + + Varargs numbers = new Varargs<>("numbers", "Numbers", NumberType.INSTANCE); + Output result = new Output<>("result", "Result", NumberType.INSTANCE); + + result.valueFrom((ctx) -> { + return numbers.getVarargs(ctx) + .stream() + .mapToDouble(Double::doubleValue) + .average() + .orElse(0.0); + }); + } + + @Override + public Node copy() { + return new AverageNumberNode(); + } + +} diff --git a/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/CosineNode.java b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/CosineNode.java new file mode 100644 index 0000000..7eba492 --- /dev/null +++ b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/CosineNode.java @@ -0,0 +1,47 @@ +package de.blazemcworld.fireflow.code.node.impl.number; + +import de.blazemcworld.fireflow.code.node.Node; +import de.blazemcworld.fireflow.code.type.NumberType; +import de.blazemcworld.fireflow.code.type.StringType; +import net.minecraft.item.Items; + +public class CosineNode extends Node { + public CosineNode() { + super("cosine", "Cosine", "Generates the trigonometric cosine function of a number.", Items.BUBBLE_CORAL_FAN); + Input value = new Input<>("value", "Value", NumberType.INSTANCE); + Input mode = new Input<>("mode", "Mode", StringType.INSTANCE).options("cos","cosh","acos"); + Input inputUnit = new Input<>("input_unit", "Input Unit", StringType.INSTANCE).options("Degrees","Radians"); + Output result = new Output<>("result", "Result", NumberType.INSTANCE); + + result.valueFrom((ctx) -> { + double valueInput = value.getValue(ctx); + switch (mode.getValue(ctx)) { + case "cos" -> { + if (inputUnit.getValue(ctx).equals("Degrees")) { + return Math.cos(Math.toRadians(valueInput)); + } else { + return Math.cos(valueInput); + } + } + case "acos" -> { + if (inputUnit.getValue(ctx).equals("Degrees")) { + return Math.toDegrees(Math.acos(valueInput)); + } else { + return Math.acos(valueInput); + } + } + case "cosh" -> { + return Math.cosh(valueInput); + } + default -> { + return 0.0; + } + } + }); + } + + @Override + public Node copy() { + return new CosineNode(); + } +} \ No newline at end of file diff --git a/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/GaussianDistributionNode.java b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/GaussianDistributionNode.java new file mode 100644 index 0000000..ef2e2d8 --- /dev/null +++ b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/GaussianDistributionNode.java @@ -0,0 +1,38 @@ +package de.blazemcworld.fireflow.code.node.impl.number; + +import de.blazemcworld.fireflow.code.node.Node; +import de.blazemcworld.fireflow.code.type.NumberType; +import de.blazemcworld.fireflow.code.type.StringType; +import net.minecraft.item.Items; + +import java.util.Random; + +public class GaussianDistributionNode extends Node { + + public GaussianDistributionNode() { + super("gaussian_distribution", "Gaussian Distribution", "Generate a normally distributed random number", Items.POLAR_BEAR_SPAWN_EGG); + Input mode = new Input<>("mode", "Mode", StringType.INSTANCE) + .options("Normal", "Folded"); + Input mean = new Input<>("mean", "μ (Mean midpoint)", NumberType.INSTANCE); + Input deviation = new Input<>("max", "σ (Standard deviation)", NumberType.INSTANCE); + Output output = new Output<>("output", "Output", NumberType.INSTANCE); + + output.valueFrom((ctx -> { + Random random = new Random(); + double outputMean = mean.getValue(ctx); + double outputDeviation = deviation.getValue(ctx); + + return switch (mode.getValue(ctx)) { + case "Normal" -> outputMean + outputDeviation * random.nextGaussian(); + case "Folded" -> outputMean + outputDeviation * Math.abs(random.nextGaussian()); + + default -> 0.0; + }; + })); + } + + @Override + public Node copy() { + return new GaussianDistributionNode(); + } +} \ No newline at end of file diff --git a/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/LerpNumbersNode.java b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/LerpNumbersNode.java new file mode 100644 index 0000000..46a3538 --- /dev/null +++ b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/LerpNumbersNode.java @@ -0,0 +1,29 @@ +package de.blazemcworld.fireflow.code.node.impl.number; + +import de.blazemcworld.fireflow.code.node.Node; +import de.blazemcworld.fireflow.code.type.NumberType; +import net.minecraft.item.Items; + +public class LerpNumbersNode extends Node { + + public LerpNumbersNode() { + super("lerp_numbers", "Lerp", "Calculates a value between two inputs by linearly interpolating based on a factor t, where t = 0 returns the start value, t = 1 returns the end value, and values in between produce a proportional blend.", Items.REPEATER); + + Input left = new Input<>("left", "Left", NumberType.INSTANCE); + Input right = new Input<>("right", "Right", NumberType.INSTANCE); + Input time = new Input<>("time", "Time (0-1)", NumberType.INSTANCE); + Output result = new Output<>("result", "Result", NumberType.INSTANCE); + + result.valueFrom((ctx) -> { + double leftValue = left.getValue(ctx); + double rightValue = right.getValue(ctx); + double timeValue = Math.clamp(time.getValue(ctx),0,1); + return leftValue + (rightValue - leftValue) * timeValue; + }); + } + + @Override + public Node copy() { + return new LerpNumbersNode(); + } +} diff --git a/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/MaxNumberNode.java b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/MaxNumberNode.java new file mode 100644 index 0000000..f0be5f4 --- /dev/null +++ b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/MaxNumberNode.java @@ -0,0 +1,28 @@ +package de.blazemcworld.fireflow.code.node.impl.number; + +import de.blazemcworld.fireflow.code.node.Node; +import de.blazemcworld.fireflow.code.type.NumberType; +import net.minecraft.item.Items; + +public class MaxNumberNode extends Node { + + public MaxNumberNode() { + super("max_number", "Maximum Number", "Returns the highest number in a set.", Items.NETHERITE_SCRAP); + + Varargs numbers = new Varargs<>("numbers", "Numbers", NumberType.INSTANCE); + Output result = new Output<>("result", "Result", NumberType.INSTANCE); + + result.valueFrom((ctx) -> { + return numbers.getVarargs(ctx) + .stream() + .max(Double::compareTo) + .orElse(0.0); + }); + } + + @Override + public Node copy() { + return new MaxNumberNode(); + } + +} diff --git a/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/MinNumberNode.java b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/MinNumberNode.java new file mode 100644 index 0000000..1e9bea4 --- /dev/null +++ b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/MinNumberNode.java @@ -0,0 +1,28 @@ +package de.blazemcworld.fireflow.code.node.impl.number; + +import de.blazemcworld.fireflow.code.node.Node; +import de.blazemcworld.fireflow.code.type.NumberType; +import net.minecraft.item.Items; + +public class MinNumberNode extends Node { + + public MinNumberNode() { + super("min_number", "Minimum Number", "Returns the lowest number in a set.", Items.DISC_FRAGMENT_5); + + Varargs numbers = new Varargs<>("numbers", "Numbers", NumberType.INSTANCE); + Output result = new Output<>("result", "Result", NumberType.INSTANCE); + + result.valueFrom((ctx) -> { + return numbers.getVarargs(ctx) + .stream() + .min(Double::compareTo) + .orElse(0.0); + }); + } + + @Override + public Node copy() { + return new MinNumberNode(); + } + +} diff --git a/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/SineNode.java b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/SineNode.java new file mode 100644 index 0000000..588e30e --- /dev/null +++ b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/SineNode.java @@ -0,0 +1,49 @@ +package de.blazemcworld.fireflow.code.node.impl.number; + +import de.blazemcworld.fireflow.code.node.Node; +import de.blazemcworld.fireflow.code.type.NumberType; +import de.blazemcworld.fireflow.code.type.StringType; +import net.minecraft.item.Items; + +import java.util.Objects; + +public class SineNode extends Node { + public SineNode() { + super("sine", "Sine", "Generates the trigonometric sine function of a number.", Items.TUBE_CORAL_FAN); + Input value = new Input<>("value", "Value", NumberType.INSTANCE); + Input mode = new Input<>("mode", "Mode", StringType.INSTANCE).options("sin","sinh","asin"); + Input inputUnit = new Input<>("input_unit", "Input Unit", StringType.INSTANCE).options("Degrees","Radians"); + Output result = new Output<>("result", "Result", NumberType.INSTANCE); + + result.valueFrom((ctx) -> { + double valueInput = value.getValue(ctx); + switch (mode.getValue(ctx)) { + case "sin" -> { + if (inputUnit.getValue(ctx).equals("Degrees")) { + return Math.sin(Math.toRadians(valueInput)); + } else { + return Math.sin(valueInput); + } + } + case "asin" -> { + if (inputUnit.getValue(ctx).equals("Degrees")) { + return Math.toDegrees(Math.asin(valueInput)); + } else { + return Math.asin(valueInput); + } + } + case "sinh" -> { + return Math.sinh(valueInput); + } + default -> { + return 0.0; + } + } + }); + } + + @Override + public Node copy() { + return new SineNode(); + } +} \ No newline at end of file diff --git a/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/TangentNode.java b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/TangentNode.java new file mode 100644 index 0000000..a459683 --- /dev/null +++ b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/TangentNode.java @@ -0,0 +1,47 @@ +package de.blazemcworld.fireflow.code.node.impl.number; + +import de.blazemcworld.fireflow.code.node.Node; +import de.blazemcworld.fireflow.code.type.NumberType; +import de.blazemcworld.fireflow.code.type.StringType; +import net.minecraft.item.Items; + +public class TangentNode extends Node { + public TangentNode() { + super("tangent", "Tangent", "Generates the trigonometric tangent function of a number.", Items.HORN_CORAL_FAN); + Input value = new Input<>("value", "Value", NumberType.INSTANCE); + Input mode = new Input<>("mode", "Mode", StringType.INSTANCE).options("tan","tanh","atan"); + Input inputUnit = new Input<>("input_unit", "Input Unit", StringType.INSTANCE).options("Degrees","Radians"); + Output result = new Output<>("result", "Result", NumberType.INSTANCE); + + result.valueFrom((ctx) -> { + double valueInput = value.getValue(ctx); + switch (mode.getValue(ctx)) { + case "tan" -> { + if (inputUnit.getValue(ctx).equals("Degrees")) { + return Math.tan(Math.toRadians(valueInput)); + } else { + return Math.tan(valueInput); + } + } + case "atan" -> { + if (inputUnit.getValue(ctx).equals("Degrees")) { + return Math.toDegrees(Math.atan(valueInput)); + } else { + return Math.atan(valueInput); + } + } + case "tanh" -> { + return Math.tanh(valueInput); + } + default -> { + return 0.0; + } + } + }); + } + + @Override + public Node copy() { + return new TangentNode(); + } +} \ No newline at end of file diff --git a/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/constants/EulersNode.java b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/constants/EulersNode.java new file mode 100644 index 0000000..14eca5b --- /dev/null +++ b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/constants/EulersNode.java @@ -0,0 +1,21 @@ +package de.blazemcworld.fireflow.code.node.impl.number.constants; + +import de.blazemcworld.fireflow.code.node.Node; +import de.blazemcworld.fireflow.code.type.NumberType; +import net.minecraft.item.Items; + +public class EulersNode extends Node { + + public EulersNode() { + super("eulers", "Euler's (e)", "Returns Euler's number.", Items.SPECTRAL_ARROW); + + Output value = new Output<>("value", "Value", NumberType.INSTANCE); + value.valueFrom(ctx -> Math.E); + } + + @Override + public Node copy() { + return new EulersNode(); + } + +} diff --git a/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/constants/GoldenRatioNode.java b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/constants/GoldenRatioNode.java new file mode 100644 index 0000000..e093e7f --- /dev/null +++ b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/constants/GoldenRatioNode.java @@ -0,0 +1,21 @@ +package de.blazemcworld.fireflow.code.node.impl.number.constants; + +import de.blazemcworld.fireflow.code.node.Node; +import de.blazemcworld.fireflow.code.type.NumberType; +import net.minecraft.item.Items; + +public class GoldenRatioNode extends Node { + + public GoldenRatioNode() { + super("golden_ratio", "Golden Ratio (Φ)", "Returns the Golden Ratio.", Items.GOLD_NUGGET); + + Output value = new Output<>("value", "Value", NumberType.INSTANCE); + value.valueFrom(ctx -> (1 + Math.sqrt(5)) / 2); + } + + @Override + public Node copy() { + return new GoldenRatioNode(); + } + +} diff --git a/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/constants/PiNode.java b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/constants/PiNode.java new file mode 100644 index 0000000..78ef21e --- /dev/null +++ b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/constants/PiNode.java @@ -0,0 +1,21 @@ +package de.blazemcworld.fireflow.code.node.impl.number.constants; + +import de.blazemcworld.fireflow.code.node.Node; +import de.blazemcworld.fireflow.code.type.NumberType; +import net.minecraft.item.Items; + +public class PiNode extends Node { + + public PiNode() { + super("pi", "Pi (π)", "Returns PI.", Items.SNOWBALL); + + Output value = new Output<>("value", "Value", NumberType.INSTANCE); + value.valueFrom(ctx -> Math.PI); + } + + @Override + public Node copy() { + return new PiNode(); + } + +} diff --git a/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/constants/TauNode.java b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/constants/TauNode.java new file mode 100644 index 0000000..678773b --- /dev/null +++ b/src/main/java/de/blazemcworld/fireflow/code/node/impl/number/constants/TauNode.java @@ -0,0 +1,21 @@ +package de.blazemcworld.fireflow.code.node.impl.number.constants; + +import de.blazemcworld.fireflow.code.node.Node; +import de.blazemcworld.fireflow.code.type.NumberType; +import net.minecraft.item.Items; + +public class TauNode extends Node { + + public TauNode() { + super("tau", "Tau (τ)", "Returns TAU.", Items.SNOW_BLOCK); + + Output value = new Output<>("value", "Value", NumberType.INSTANCE); + value.valueFrom(ctx -> Math.TAU); + } + + @Override + public Node copy() { + return new TauNode(); + } + +} diff --git a/src/main/java/de/blazemcworld/fireflow/code/node/impl/player/inventory/SetPlayerArmorNode.java b/src/main/java/de/blazemcworld/fireflow/code/node/impl/player/inventory/SetPlayerArmorNode.java new file mode 100644 index 0000000..c4556a1 --- /dev/null +++ b/src/main/java/de/blazemcworld/fireflow/code/node/impl/player/inventory/SetPlayerArmorNode.java @@ -0,0 +1,52 @@ +package de.blazemcworld.fireflow.code.node.impl.player.inventory; + +import de.blazemcworld.fireflow.code.node.Node; +import de.blazemcworld.fireflow.code.type.*; +import de.blazemcworld.fireflow.code.value.ListValue; +import de.blazemcworld.fireflow.code.value.PlayerValue; +import net.minecraft.entity.attribute.AttributeContainer; +import net.minecraft.entity.attribute.EntityAttributeModifier; +import net.minecraft.entity.attribute.EntityAttributes; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; + +public class SetPlayerArmorNode extends Node { + + public SetPlayerArmorNode() { + super("set_player_armor", "Set Player Armor", "Changes the armor of a player", Items.DIAMOND_LEGGINGS); + + Input signal = new Input<>("signal", "Signal", SignalType.INSTANCE); + Input player = new Input<>("player", "Player", PlayerType.INSTANCE); + Input head = new Input<>("head", "Head", ItemType.INSTANCE); + Input chest = new Input<>("chest", "Chest", ItemType.INSTANCE); + Input legs = new Input<>("legs", "Legs", ItemType.INSTANCE); + Input feet = new Input<>("feet", "Feet", ItemType.INSTANCE); + Input behaviour = new Input<>("behaviour", "Behaviour", StringType.INSTANCE) + .options("Clear", "Merge"); + Output next = new Output<>("next", "Next", SignalType.INSTANCE); + + signal.onSignal((ctx) -> { + player.getValue(ctx).tryUse(ctx, p -> { + boolean clearInv = behaviour.getValue(ctx).equals("Clear"); + ItemStack headItem = head.getValue(ctx); + ItemStack chestItem = chest.getValue(ctx); + ItemStack legsItem = legs.getValue(ctx); + ItemStack feetItem = feet.getValue(ctx); + if (!headItem.isEmpty() || clearInv) p.getInventory().setStack(39, headItem); + if (!chestItem.isEmpty() || clearInv) p.getInventory().setStack(38, chestItem); + if (!legsItem.isEmpty() || clearInv) p.getInventory().setStack(37, legsItem); + if (!feetItem.isEmpty() || clearInv) p.getInventory().setStack(36, feetItem); + }); + ctx.sendSignal(next); + }); + + } + + @Override + public Node copy() { + return new SetPlayerArmorNode(); + } + +} + + diff --git a/src/main/java/de/blazemcworld/fireflow/code/node/impl/player/meta/GetPlayerPingNode.java b/src/main/java/de/blazemcworld/fireflow/code/node/impl/player/meta/GetPlayerPingNode.java new file mode 100644 index 0000000..c027d08 --- /dev/null +++ b/src/main/java/de/blazemcworld/fireflow/code/node/impl/player/meta/GetPlayerPingNode.java @@ -0,0 +1,24 @@ +package de.blazemcworld.fireflow.code.node.impl.player.meta; + +import de.blazemcworld.fireflow.code.node.Node; +import de.blazemcworld.fireflow.code.type.NumberType; +import de.blazemcworld.fireflow.code.type.PlayerType; +import de.blazemcworld.fireflow.code.type.StringType; +import de.blazemcworld.fireflow.code.value.PlayerValue; +import net.minecraft.item.Items; + +public class GetPlayerPingNode extends Node { + public GetPlayerPingNode() { + super("get_player_ping", "Get Player Ping", "Gets the ping of a player.", Items.SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE); + + Input player = new Input<>("player", "Player", PlayerType.INSTANCE); + Output ping = new Output<>("ping", "Ping", NumberType.INSTANCE); + + ping.valueFrom(ctx -> (double) player.getValue(ctx).tryGet(ctx, p -> p.networkHandler.getLatency(), 0)); + } + + @Override + public Node copy() { + return new GetPlayerPingNode(); + } +} \ No newline at end of file diff --git a/src/main/java/de/blazemcworld/fireflow/code/node/impl/player/visual/bossbar/ClearBossbarsNode.java b/src/main/java/de/blazemcworld/fireflow/code/node/impl/player/visual/bossbar/ClearBossbarsNode.java new file mode 100644 index 0000000..02e8944 --- /dev/null +++ b/src/main/java/de/blazemcworld/fireflow/code/node/impl/player/visual/bossbar/ClearBossbarsNode.java @@ -0,0 +1,37 @@ +package de.blazemcworld.fireflow.code.node.impl.player.visual.bossbar; + +import de.blazemcworld.fireflow.code.node.Node; +import de.blazemcworld.fireflow.code.type.NumberType; +import de.blazemcworld.fireflow.code.type.PlayerType; +import de.blazemcworld.fireflow.code.type.SignalType; +import de.blazemcworld.fireflow.code.value.PlayerValue; +import de.blazemcworld.fireflow.space.BossBarManager; +import de.blazemcworld.fireflow.space.Space; +import de.blazemcworld.fireflow.space.SpaceManager; +import net.minecraft.item.Items; + +public class ClearBossbarsNode extends Node { + + public ClearBossbarsNode() { + super("clear_bossbars", "Clear Bossbars", "Removes all bossbars from a player", Items.STRUCTURE_VOID); + + Input signal = new Input<>("signal", "Signal", SignalType.INSTANCE); + Input player = new Input<>("player", "Player", PlayerType.INSTANCE); + + Output next = new Output<>("next", "Next", SignalType.INSTANCE); + + signal.onSignal((ctx) -> { + player.getValue(ctx).tryUse(ctx, p -> { + Space space = SpaceManager.getSpaceForPlayer(p); + BossBarManager bossBarManager = space.bossBarManager; + bossBarManager.clearBossBars(p); + }); + ctx.sendSignal(next); + }); + } + + @Override + public Node copy() { + return new ClearBossbarsNode(); + } +} diff --git a/src/main/java/de/blazemcworld/fireflow/code/node/impl/player/visual/bossbar/RemoveBossbarNode.java b/src/main/java/de/blazemcworld/fireflow/code/node/impl/player/visual/bossbar/RemoveBossbarNode.java new file mode 100644 index 0000000..ffc85dd --- /dev/null +++ b/src/main/java/de/blazemcworld/fireflow/code/node/impl/player/visual/bossbar/RemoveBossbarNode.java @@ -0,0 +1,44 @@ +package de.blazemcworld.fireflow.code.node.impl.player.visual.bossbar; + +import de.blazemcworld.fireflow.code.node.Node; +import de.blazemcworld.fireflow.code.type.NumberType; +import de.blazemcworld.fireflow.code.type.PlayerType; +import de.blazemcworld.fireflow.code.type.SignalType; +import de.blazemcworld.fireflow.code.type.TextType; +import de.blazemcworld.fireflow.code.value.PlayerValue; +import de.blazemcworld.fireflow.space.BossBarManager; +import de.blazemcworld.fireflow.space.Space; +import de.blazemcworld.fireflow.space.SpaceManager; +import net.minecraft.entity.boss.BossBar; +import net.minecraft.entity.boss.ServerBossBar; +import net.minecraft.item.Items; +import net.minecraft.text.Text; + +import java.util.List; + +public class RemoveBossbarNode extends Node { + + public RemoveBossbarNode() { + super("remove_bossbar", "Remove Bossbar", "Removes a bossbar from a player", Items.PALE_OAK_SIGN); + + Input signal = new Input<>("signal", "Signal", SignalType.INSTANCE); + Input player = new Input<>("player", "Player", PlayerType.INSTANCE); + Input position = new Input<>("position", "Position", NumberType.INSTANCE); + + Output next = new Output<>("next", "Next", SignalType.INSTANCE); + + signal.onSignal((ctx) -> { + player.getValue(ctx).tryUse(ctx, p -> { + Space space = SpaceManager.getSpaceForPlayer(p); + BossBarManager bossBarManager = space.bossBarManager; + bossBarManager.removeBossBarAtIndex(p,position.getValue(ctx).intValue()); + }); + ctx.sendSignal(next); + }); + } + + @Override + public Node copy() { + return new RemoveBossbarNode(); + } +} diff --git a/src/main/java/de/blazemcworld/fireflow/code/node/impl/player/visual/bossbar/SetBossbarNode.java b/src/main/java/de/blazemcworld/fireflow/code/node/impl/player/visual/bossbar/SetBossbarNode.java new file mode 100644 index 0000000..8d6c909 --- /dev/null +++ b/src/main/java/de/blazemcworld/fireflow/code/node/impl/player/visual/bossbar/SetBossbarNode.java @@ -0,0 +1,78 @@ +package de.blazemcworld.fireflow.code.node.impl.player.visual.bossbar; + +import de.blazemcworld.fireflow.code.node.Node; +import de.blazemcworld.fireflow.code.type.*; +import de.blazemcworld.fireflow.code.value.PlayerValue; +import de.blazemcworld.fireflow.space.BossBarManager; +import de.blazemcworld.fireflow.space.Space; +import de.blazemcworld.fireflow.space.SpaceManager; +import net.minecraft.entity.boss.BossBar; +import net.minecraft.entity.boss.ServerBossBar; +import net.minecraft.item.Items; +import net.minecraft.text.Text; + +import java.util.List; + +public class SetBossbarNode extends Node { + + public SetBossbarNode() { + super("set_bossbar", "Set Bossbar", "Sets a bossbar for a player", Items.BIRCH_SIGN); + + Input signal = new Input<>("signal", "Signal", SignalType.INSTANCE); + Input player = new Input<>("player", "Player", PlayerType.INSTANCE); + Input title = new Input<>("title", "Title", TextType.INSTANCE); + Input current_health = new Input<>("current_health", "Current Health", NumberType.INSTANCE); + Input max_health = new Input<>("max_health", "Maximum Health", NumberType.INSTANCE); + Input position = new Input<>("position", "Position", NumberType.INSTANCE); + Input barColor = new Input<>("bar_color", "Bar Color", StringType.INSTANCE).options("Red","Purple","Pink","Blue","Green","Yellow","White"); + Input barStyle = new Input<>("bar_style", "Bar Style", StringType.INSTANCE).options("Solid","6 Segments","10 Segments","12 Segments","20 Segments"); + Input skyEffect = new Input<>("sky_effect", "Sky Effect", StringType.INSTANCE).options("None","Thicken Fog","Darken Sky","Both"); + + Output next = new Output<>("next", "Next", SignalType.INSTANCE); + + signal.onSignal((ctx) -> { + player.getValue(ctx).tryUse(ctx, p -> { + Space space = SpaceManager.getSpaceForPlayer(p); + BossBarManager bossBarManager = space.bossBarManager; + BossBar.Color color = switch(barColor.getValue(ctx)) { + case "Red" -> BossBar.Color.RED; + case "Purple" -> BossBar.Color.PURPLE; + case "Pink" -> BossBar.Color.PINK; + case "Blue" -> BossBar.Color.BLUE; + case "Green" -> BossBar.Color.GREEN; + case "Yellow" -> BossBar.Color.YELLOW; + default -> BossBar.Color.WHITE; + }; + BossBar.Style style = switch(barStyle.getValue(ctx)) { + case "6 Segments" -> BossBar.Style.NOTCHED_6; + case "10 Segments" -> BossBar.Style.NOTCHED_10; + case "12 Segments" -> BossBar.Style.NOTCHED_12; + case "20 Segments" -> BossBar.Style.NOTCHED_20; + default -> BossBar.Style.PROGRESS; + }; + ServerBossBar bossBar = new ServerBossBar( + title.getValue(ctx), + color, + style + ); + switch(skyEffect.getValue(ctx)) { + case "Thicken Fog" -> bossBar.setThickenFog(true); + case "Darken Sky" -> bossBar.setDarkenSky(true); + case "Both" -> { + bossBar.setThickenFog(true); + bossBar.setDarkenSky(true); + } + } + bossBar.setPercent(current_health.getValue(ctx).floatValue()/max_health.getValue(ctx).floatValue()); + List bossBars = bossBarManager.getBossBars(p); + bossBarManager.setBossBarAtIndex(p,position.getValue(ctx).intValue(), bossBar); + }); + ctx.sendSignal(next); + }); + } + + @Override + public Node copy() { + return new SetBossbarNode(); + } +} diff --git a/src/main/java/de/blazemcworld/fireflow/code/node/impl/vector/DotProductNode.java b/src/main/java/de/blazemcworld/fireflow/code/node/impl/vector/DotProductNode.java new file mode 100644 index 0000000..57e986d --- /dev/null +++ b/src/main/java/de/blazemcworld/fireflow/code/node/impl/vector/DotProductNode.java @@ -0,0 +1,26 @@ +package de.blazemcworld.fireflow.code.node.impl.vector; + +import de.blazemcworld.fireflow.code.node.Node; +import de.blazemcworld.fireflow.code.type.NumberType; +import de.blazemcworld.fireflow.code.type.VectorType; +import net.minecraft.item.Items; +import net.minecraft.util.math.Vec3d; +import org.apache.logging.log4j.core.lookup.Interpolator; + +public class DotProductNode extends Node { + + public DotProductNode() { + super("dot_product", "Dot Product", "Gets the Dot Product of two vectors", Items.GUNPOWDER); + + Input first = new Input<>("first", "First", VectorType.INSTANCE); + Input second = new Input<>("second", "Second", VectorType.INSTANCE); + Output result = new Output<>("result", "Result", NumberType.INSTANCE); + + result.valueFrom(ctx -> first.getValue(ctx).dotProduct(second.getValue(ctx))); + } + + @Override + public Node copy() { + return new DotProductNode(); + } +} diff --git a/src/main/java/de/blazemcworld/fireflow/code/node/impl/vector/GetVectorLengthNode.java b/src/main/java/de/blazemcworld/fireflow/code/node/impl/vector/GetVectorLengthNode.java new file mode 100644 index 0000000..90dcfce --- /dev/null +++ b/src/main/java/de/blazemcworld/fireflow/code/node/impl/vector/GetVectorLengthNode.java @@ -0,0 +1,37 @@ +package de.blazemcworld.fireflow.code.node.impl.vector; + +import de.blazemcworld.fireflow.code.node.Node; +import de.blazemcworld.fireflow.code.type.NumberType; +import de.blazemcworld.fireflow.code.type.StringType; +import de.blazemcworld.fireflow.code.type.VectorType; +import net.minecraft.item.Items; +import net.minecraft.util.math.Vec3d; + +public class GetVectorLengthNode extends Node { + public GetVectorLengthNode() { + super("get_vector_length", "Get Vector Length", "Gets the length of a vector", Items.BREEZE_ROD); + Input vector = new Input<>("vector", "Vector", VectorType.INSTANCE); + Input lengthType = new Input<>("length_type", "Length Type", StringType.INSTANCE).options("Normal","Squared"); + Output length = new Output<>("length", "Length", NumberType.INSTANCE); + + length.valueFrom(ctx -> { + Vec3d v = vector.getValue(ctx); + switch(lengthType.getValue(ctx)) { + case "Normal" -> { + return v.length(); + } + case "Squared" -> { + return v.lengthSquared(); + } + default -> { + return 0.0; + } + } + }); + } + + @Override + public Node copy() { + return new GetVectorLengthNode(); + } +} diff --git a/src/main/java/de/blazemcworld/fireflow/code/node/impl/world/TimestampNode.java b/src/main/java/de/blazemcworld/fireflow/code/node/impl/world/TimestampNode.java new file mode 100644 index 0000000..1273c28 --- /dev/null +++ b/src/main/java/de/blazemcworld/fireflow/code/node/impl/world/TimestampNode.java @@ -0,0 +1,21 @@ +package de.blazemcworld.fireflow.code.node.impl.world; + +import de.blazemcworld.fireflow.code.node.Node; +import de.blazemcworld.fireflow.code.type.NumberType; +import net.minecraft.item.Items; + +public class TimestampNode extends Node { + + public TimestampNode() { + super("timestamp", "Timestamp", "Returns the elapsed seconds since the Unix epoch.", Items.CLOCK); + + Output usage = new Output<>("timestamp", "Timestamp", NumberType.INSTANCE); + usage.valueFrom(ctx -> (double) System.currentTimeMillis() / 1000); + } + + @Override + public Node copy() { + return new TimestampNode(); + } + +} diff --git a/src/main/java/de/blazemcworld/fireflow/code/widget/NodeMenuWidget.java b/src/main/java/de/blazemcworld/fireflow/code/widget/NodeMenuWidget.java index 8cfc36e..c7a4e86 100644 --- a/src/main/java/de/blazemcworld/fireflow/code/widget/NodeMenuWidget.java +++ b/src/main/java/de/blazemcworld/fireflow/code/widget/NodeMenuWidget.java @@ -61,7 +61,7 @@ public NodeMenuWidget(WidgetVec pos, NodeList.Category category, List { if (interaction.type() != CodeInteraction.Type.RIGHT_CLICK) return false; diff --git a/src/main/java/de/blazemcworld/fireflow/space/BossBarManager.java b/src/main/java/de/blazemcworld/fireflow/space/BossBarManager.java new file mode 100644 index 0000000..919fd07 --- /dev/null +++ b/src/main/java/de/blazemcworld/fireflow/space/BossBarManager.java @@ -0,0 +1,62 @@ +package de.blazemcworld.fireflow.space; + +import net.minecraft.entity.boss.ServerBossBar; +import net.minecraft.server.network.ServerPlayerEntity; +import java.util.*; + +public class BossBarManager { + private final Map> bossBars = new HashMap<>(); + + public void setBossBarAtIndex(ServerPlayerEntity player, int index, ServerBossBar newBossBar) { + List bars = bossBars.computeIfAbsent(player.getUuid(), k -> new ArrayList<>()); + + while (bars.size() <= index) { + bars.add(null); + } + + ServerBossBar existing = bars.get(index); + if (existing != null) { + existing.setName(newBossBar.getName()); + existing.setPercent(newBossBar.getPercent()); + existing.setColor(newBossBar.getColor()); + existing.setStyle(newBossBar.getStyle()); + existing.setDarkenSky(newBossBar.shouldDarkenSky()); + existing.setThickenFog(newBossBar.shouldThickenFog()); + existing.addPlayer(player); + } else { + bars.set(index, newBossBar); + for (ServerBossBar bar : bars) { + if(bar == null) continue; + bar.removePlayer(player); + bar.addPlayer(player); + } + } + } + + + + public void removeBossBarAtIndex(ServerPlayerEntity player, int index) { + List bars = getBossBars(player); + if (bars != null && index >= 0 && index < bars.size()) { + ServerBossBar bar = bars.get(index); + bar.removePlayer(player); + bars.remove(index); + } + } + + public void clearBossBars(ServerPlayerEntity player) { + for (ServerBossBar bar : getBossBars(player)) { + if(bar == null) continue; + bar.removePlayer(player); + } + bossBars.remove(player.getUuid()); + } + + public List getBossBars(ServerPlayerEntity player) { + return bossBars.getOrDefault(player.getUuid(), Collections.emptyList()); + } + + public void reset() { + bossBars.clear(); + } +} diff --git a/src/main/java/de/blazemcworld/fireflow/space/Space.java b/src/main/java/de/blazemcworld/fireflow/space/Space.java index c8569a0..61d2c4b 100644 --- a/src/main/java/de/blazemcworld/fireflow/space/Space.java +++ b/src/main/java/de/blazemcworld/fireflow/space/Space.java @@ -28,6 +28,7 @@ public class Space { private int emptyTimer = 0; public CodeEvaluator evaluator; public final DummyManager dummyManager; + public final BossBarManager bossBarManager; public Space(SpaceInfo info) { this.info = info; @@ -51,6 +52,7 @@ public Space(SpaceInfo info) { editor.load(); evaluator = new CodeEvaluator(this); dummyManager = new DummyManager(this); + bossBarManager = new BossBarManager(); } public void save() { @@ -69,6 +71,7 @@ public boolean isInactive() { protected void unload(Runnable callback) { dummyManager.reset(); + bossBarManager.reset(); for (ServerPlayerEntity player : new ArrayList<>(playWorld.getPlayers())) { ModeManager.move(player, ModeManager.Mode.LOBBY, this); } @@ -118,12 +121,14 @@ public Path path() { public void reload() { dummyManager.reset(); for (ServerPlayerEntity player : new ArrayList<>(playWorld.getPlayers())) { + bossBarManager.clearBossBars(player); if (info.isOwnerOrDeveloper(player.getUuid())) { ModeManager.move(player, ModeManager.Mode.CODE, this); } else { ModeManager.move(player, ModeManager.Mode.LOBBY, this); } } + bossBarManager.reset(); evaluator.stop(); playWorld.getChunkManager().chunkLoadingManager.unloadChunks(() -> true); evaluator = new CodeEvaluator(this);