Skip to content

Commit

Permalink
Adds some command block syntax (#6859)
Browse files Browse the repository at this point in the history
* Adds command block syntax
- An expression to get/set the command of a command block or minecart with command block
- An effect and condition for whether a command block is conditional or not
- Tests for both

* Adds Skript annotations

* Apply suggestion from review

Co-authored-by: sovdee <10354869+sovdeeth@users.noreply.github.com>

* Suggestions

* Hopefully fixes tests

* Hopefully fixes tests

* Uses setNegated and hopefully fixes tests

* Suggestions

* Suggestions and stuff

* Changes effect pattern to be more clear

* Fixes test syntax

* Pattern matching in CondIsCommandBlockConditional

---------

Co-authored-by: sovdee <10354869+sovdeeth@users.noreply.github.com>
Co-authored-by: Moderocky <admin@moderocky.com>
  • Loading branch information
3 people authored Oct 13, 2024
1 parent 3420038 commit 22dfe9f
Show file tree
Hide file tree
Showing 5 changed files with 249 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package ch.njol.skript.conditions;

import ch.njol.skript.conditions.base.PropertyCondition;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Examples;
import ch.njol.skript.doc.Name;
import ch.njol.skript.doc.Since;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.util.Kleenean;
import org.bukkit.block.Block;
import org.bukkit.block.data.type.CommandBlock;

@Name("Is Conditional")
@Description(
"Checks whether a command block is conditional or not."
)
@Examples({
"if {_block} is conditional:",
"\tmake {_block} unconditional"
})
@Since("INSERT VERSION")
public class CondIsCommandBlockConditional extends PropertyCondition<Block> {

static {
register(CondIsCommandBlockConditional.class, "[:un]conditional", "blocks");
}

@Override
@SuppressWarnings("unchecked")
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
setExpr((Expression<Block>) exprs[0]);
setNegated(parseResult.hasTag("un") ^ matchedPattern == 1);
return true;
}

@Override
public boolean check(Block block) {
if (block.getBlockData() instanceof CommandBlock cmdBlock)
return cmdBlock.isConditional();
return false;
}

@Override
protected String getPropertyName() {
return "conditional";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package ch.njol.skript.effects;

import ch.njol.skript.Skript;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Examples;
import ch.njol.skript.doc.Name;
import ch.njol.skript.doc.Since;
import ch.njol.skript.lang.Effect;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.util.Kleenean;
import org.bukkit.block.Block;
import org.bukkit.block.data.type.CommandBlock;
import org.bukkit.event.Event;
import org.jetbrains.annotations.Nullable;

@Name("Conditional / Unconditional")
@Description(
"Sets whether the provided command blocks are conditional or not."
)
@Examples({
"make command block {_block} conditional",
"make command block {_block} unconditional if {_block} is conditional"
})
@Since("INSERT VERSION")
public class EffCommandBlockConditional extends Effect {

static {
Skript.registerEffect(EffCommandBlockConditional.class, "make command block[s] %blocks% [not:(un|not )]conditional");
}

private Expression<Block> blocks;
private boolean conditional;

@Override
@SuppressWarnings("unchecked")
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
blocks = (Expression<Block>) exprs[0];
conditional = !parseResult.hasTag("not");
return true;
}

@Override
protected void execute(Event event) {
for (Block block : blocks.getArray(event)) {
if (block.getBlockData() instanceof CommandBlock cmdBlock) {
cmdBlock.setConditional(conditional);
block.setBlockData(cmdBlock);
}
}
}

@Override
public String toString(@Nullable Event event, boolean debug) {
return "make command block " + blocks.toString(event, debug) + (conditional ? " " : " un") + "conditional";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package ch.njol.skript.expressions;

import ch.njol.skript.classes.Changer.ChangeMode;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Examples;
import ch.njol.skript.doc.Name;
import ch.njol.skript.doc.Since;
import ch.njol.skript.expressions.base.SimplePropertyExpression;
import ch.njol.util.coll.CollectionUtils;
import org.bukkit.block.Block;
import org.bukkit.block.CommandBlock;
import org.bukkit.entity.minecart.CommandMinecart;
import org.bukkit.event.Event;
import org.jetbrains.annotations.Nullable;

@Name("Command Block Command")
@Description(
"Gets or sets the command associated with a command block or minecart with command block."
)
@Examples({
"send command of {_block}",
"set command of {_cmdMinecart} to \"say asdf\""
})
@Since("INSERT VERSION")
public class ExprCommandBlockCommand extends SimplePropertyExpression<Object, String> {

static {
register(ExprCommandBlockCommand.class, String.class, "[command[ ]block] command", "blocks/entities");
}

@Override
public @Nullable String convert(Object holder) {
String command = "";
if (holder instanceof Block block && block.getState() instanceof CommandBlock cmdBlock) {
command = cmdBlock.getCommand();
} else if (holder instanceof CommandMinecart cmdMinecart) {
command = cmdMinecart.getCommand();
}
return (command.isEmpty()) ? null : command;
}

@Override
public Class<?> @Nullable [] acceptChange(ChangeMode mode) {
if (mode == ChangeMode.SET || mode == ChangeMode.DELETE || mode == ChangeMode.RESET)
return CollectionUtils.array(String.class);
return null;
}

@Override
public void change(Event event, Object @Nullable [] delta, ChangeMode mode) {
String newCommand = delta == null ? null : ((String) delta[0]);
for (Object holder : getExpr().getArray(event)) {
switch (mode) {
case RESET:
case DELETE:
case SET:
if (holder instanceof Block block && block.getState() instanceof CommandBlock cmdBlock) {
cmdBlock.setCommand(newCommand);
cmdBlock.update();
} else if (holder instanceof CommandMinecart cmdMinecart) {
cmdMinecart.setCommand(newCommand);
}
break;
default:
assert false;
}
}
}

@Override
public Class<? extends String> getReturnType() {
return String.class;
}

@Override
protected String getPropertyName() {
return "command block command";
}

}
22 changes: 22 additions & 0 deletions src/test/skript/tests/syntaxes/conditions/CondIsConditional.sk
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
test "is conditional":

set {_l} to location(0,0,0,world)
set {_original} to blockdata of block at {_l}
set block at {_l} to command block
set {_b} to block at {_l}

assert {_b} is not conditional with "a new command block shouldn't be conditional"

make command block {_b} conditional
assert {_b} is conditional with "making a command block conditional should do exactly that"

make command block {_b} unconditional
assert {_b} is unconditional with "making a command block unconditional should do exactly that"

set block at {_b} to stone
assert {_b} is not conditional with "a non-command block should not be conditional"

make command block {_b} conditional
assert {_b} is not conditional with "making a non-command block conditional shouldn't do anything"

set block at {_l} to {_original}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
test "command block command":

set {_l} to location(0,1,0,world)
set {_original} to blockdata of block at {_l}
set block at {_l} to command block
spawn a minecart with command block at (spawn of world "world"):
set {_e} to entity
spawn a zombie at (spawn of world "world"):
set {_z} to entity
set {_b} to block at {_l}

assert command block command of {_b} is not set with "a new command block shouldn't have an associated command"
assert command block command of {_e} is not set with "a new minecart with command block shouldn't have an associated command"

set command block command of {_b} to "say asdf"
set command block command of {_e} to "say asdf"
assert command block command of {_b} is "say asdf" with "setting the command of a command block should do exactly that"
assert command block command of {_e} is "say asdf" with "setting the command of a minecart with command block should do exactly that"
assert command of {_b} is "say asdf" with "testing for possible future conflicts (block)"
assert command of {_e} is "say asdf" with "testing for possible future conflicts (entity)"

clear command block command of {_b}
clear command block command of {_e}
assert command block command of {_b} is not set with "clearing/deleting/resetting the command of a command block should return null"
assert command block command of {_e} is not set with "clearing/deleting/resetting the command of a minecart with command block should return null"
assert command of {_b} is not set with "testing for possible future conflicts (block)"
assert command of {_e} is not set with "testing for possible future conflicts (entity)"

set block at {_b} to stone
assert command block command of {_b} is not set with "the command of a non-command block should return null"
assert command block command of {_z} is not set with "the command of a non-minecart with command block should return null"

set command block command of {_b} to "say asdf"
set command block command of {_z} to "say asdf"
assert command block command of {_b} is not set with "setting the command of a non-command block shouldn't do anything"
assert command block command of {_z} is not set with "setting the command of a non-minecart with command block shouldn't do anything"

delete entity within {_e}
delete entity within {_z}
set block at {_l} to {_original}

0 comments on commit 22dfe9f

Please sign in to comment.