Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduces toggle effect & expression #4154

Open
wants to merge 104 commits into
base: dev/feature
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 90 commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
ddb40a8
feat(changemode): introduces toggle mode
Olyno Jul 3, 2021
7c6dfb5
merge: master
Olyno Jul 3, 2021
f5d6762
fix(unreachable): remove unecessary statement
Olyno Jul 3, 2021
9f53cc5
fix(unreachable): remove unecessary statement
Olyno Jul 3, 2021
7c799fe
fix(condition): missing pipe sign
Olyno Jul 3, 2021
62af771
revert(ExprWhitelist): reset mode affected
Olyno Jul 3, 2021
717cb84
fix(ExprGlowing): missing toggle mode in acceptChange
Olyno Jul 3, 2021
c9c87be
Merge branch 'feature/toggleChanger' of github.com:Olyno/Skript into …
Olyno Jul 3, 2021
59f8e68
Merge branch 'master' into feature/toggleChanger
Olyno Jul 3, 2021
e6ddeea
Merge branch 'master' into feature/toggleChanger
Olyno Sep 1, 2021
d6cd4d6
fix(conflict): merge master
Olyno Nov 23, 2021
759e1f0
chore(toggle): replaces ChangeMode.TOGGLE with ChangeMode.SET
Olyno Nov 23, 2021
a95f19e
docs(toggle): add missing version update
Olyno Nov 23, 2021
37408c7
chore(toggle): remove syntax conflict & unwanted changes
Olyno Nov 23, 2021
dd8c9d0
chore(toggle): remove unwanted changes
Olyno Nov 23, 2021
fb3af6f
chore(toggle): remove unwanted changes
Olyno Nov 23, 2021
2ade451
chore(toggle): remove missing unwanted changes
Olyno Nov 23, 2021
c4fb185
fix: tests
Olyno Nov 23, 2021
cb93dd8
chore(toggle): move toggle booleans to EffToggle
Olyno Nov 23, 2021
63e0ff7
fix(toggle): check parsing type
Olyno Nov 23, 2021
7ac2de5
fix(toggle): make tests work
Olyno Nov 23, 2021
f6438c8
fix(typo): description of toggle effect
Olyno Nov 24, 2021
6f88032
fix(toggle): make init check work
Olyno Nov 24, 2021
8070373
fix(toggle): make requiered changes
Olyno Nov 24, 2021
7f3cef9
chore: merge changes
Olyno Nov 24, 2021
8ae20b5
chore(toggle): remove unwanted stuff
Olyno Nov 25, 2021
dbc20e6
Merge branch 'master' into feature/toggleChanger
Olyno Feb 11, 2022
3075255
Merge branch 'master' of github.com:SkriptLang/Skript into feature/to…
Olyno Feb 23, 2022
8397e24
fix: indentation
Olyno Feb 23, 2022
912f0d8
docs(ExprToggled): precise we toggle a boolean value
Olyno Feb 23, 2022
d3b07a5
fix(ExprToggled): wrong annotation indentation
Olyno Feb 23, 2022
0da3b69
fix(EffToggle): remove boilerplate and unecessary code
Olyno Feb 23, 2022
4565ff4
fix(EffToggle): boolean value check
Olyno Feb 23, 2022
026a132
fix: conflict
Olyno Feb 23, 2022
9cc2f23
fix(EffToggle): apply change to lists
Olyno Feb 23, 2022
ef85caf
fix(ExprToggled): issue with Expression#stream method
Olyno Feb 25, 2022
f6667d7
Merge branch 'master' into feature/toggleChanger
Olyno Feb 25, 2022
94dd2b0
Merge branch 'master' into feature/toggleChanger
Olyno Mar 14, 2022
d8b81c6
fix: toggle condition
Olyno Mar 18, 2022
2ffed85
feat: optimize toggle operation
Olyno Mar 18, 2022
338f097
fix: typing
Olyno Mar 18, 2022
1fd0cdc
fix: returning only boolean
Olyno Mar 24, 2022
29b1496
test: add block test
Olyno Mar 24, 2022
a41d1c4
Merge branch 'master' into feature/toggleChanger
Olyno Jul 9, 2022
533ecaa
More readable patterns
Olyno Jul 9, 2022
0ca5809
Remove comment
Olyno Jul 9, 2022
6d33a9c
Improve code quality
Olyno Jul 9, 2022
fa349dc
revert: asked
Olyno Oct 5, 2022
c51a1ea
chore: remove empty line
Olyno Oct 5, 2022
7d2b381
chore: change pattern of ExprToggle
Olyno Oct 5, 2022
63df787
Merge branch 'feature/toggleChanger' of github.com:Olyno/Skript into …
Olyno Oct 5, 2022
f1c249f
merge: master
Olyno Oct 5, 2022
9ca79a9
revert: add missing new line for test
Olyno Oct 5, 2022
1611bb3
chore: rename ExprToggled to ExprInverse
Olyno Oct 5, 2022
6cd8135
fix: toggle test
Olyno Oct 5, 2022
702206d
fix(typo): apply review
Olyno Oct 6, 2022
876933a
Merge branch 'master' of github.com:SkriptLang/Skript into feature/to…
Olyno Oct 26, 2022
3af8951
revert: unecessary change
Olyno Oct 26, 2022
c60cd74
ups
Olyno Oct 26, 2022
0c02931
chore: remove unused imports
Olyno Oct 26, 2022
bb053c0
docs: remove comment
Olyno Nov 17, 2022
eab9c59
docs: update description
Olyno Dec 26, 2022
3bfb357
chore: short code
Olyno Dec 26, 2022
83e461a
Merge branch 'master' into feature/toggleChanger
Olyno Dec 26, 2022
964c998
Merge branch 'master' into feature/toggleChanger
Olyno Dec 30, 2022
b3884c0
chore: adds check before toggle
Olyno Jan 18, 2023
596644c
Merge branch 'master' into feature/toggleChanger
Olyno Jan 18, 2023
ab8b35f
chore: add missing closures
Olyno Jan 18, 2023
2fb4096
chore: remove finals
Olyno Jan 18, 2023
b813df0
chore: simplify workflow
Olyno Jan 18, 2023
e397038
fix: toggle wasn't working correctly
Olyno Feb 11, 2023
23d711a
Merge branch 'master' into feature/toggleChanger
Olyno Apr 25, 2023
832374d
fix: missing value when boolean toggle
Olyno Apr 30, 2023
07601b3
merge: master
Olyno Apr 30, 2023
08397f5
Merge branch 'master' into feature/toggleChanger
Olyno Apr 30, 2023
27b9169
fix: incompatibility Java version method
Olyno May 1, 2023
54fbcca
Merge branch 'feature/toggleChanger' of github.com:Olyno/Skript into …
Olyno May 1, 2023
6a3f2a2
fix: block wasn't added to the list
Olyno May 1, 2023
0cfa688
Merge branch 'master' into feature/toggleChanger
Olyno May 1, 2023
e3f1622
test: rename test name
Olyno May 1, 2023
68fead4
chore: remove unecessary part
Olyno May 1, 2023
439639c
chore: update code with review
Olyno May 1, 2023
9121b2a
Merge branch 'master' into feature/toggleChanger
Olyno May 2, 2023
64bd9c3
Merge branch 'master' into feature/toggleChanger
Olyno May 9, 2023
75d999e
Merge branch 'dev/feature' into feature/toggleChanger
Moderocky Oct 14, 2023
c20f01f
Merge branch 'dev/feature' into feature/toggleChanger
Moderocky Apr 3, 2024
14cc4e0
Merge branch 'dev/feature' into feature/toggleChanger
Olyno Apr 8, 2024
fa7d13c
Merge branch 'dev/feature' into feature/toggleChanger
sovdeeth May 6, 2024
fc6840c
Merge branch 'dev/feature' into feature/toggleChanger
Moderocky May 8, 2024
6cde78c
Merge branch 'dev/feature' into feature/toggleChanger
Olyno May 9, 2024
5d5cb4a
chore(formatting): fix formatting
Olyno Jun 3, 2024
9bb3ed5
chore(formatting): fix formatting
Olyno Jun 3, 2024
ae5960f
chore(formatting): fix formatting
Olyno Jun 3, 2024
8ee2c1b
chore(formatting): fix formatting
Olyno Jun 3, 2024
1315872
chore: collect as array directly
Olyno Jun 3, 2024
bbabd72
Merge branch 'dev/feature' into feature/toggleChanger
Olyno Jun 3, 2024
b5dd7b5
chore: rename 'toggledExpr' to 'togglables'
Olyno Jun 15, 2024
41a45fe
fix(toggle): try to fix unexpected behavior
Olyno Jun 15, 2024
15a8bf2
Merge branch 'dev/feature' into feature/toggleChanger
Olyno Jun 15, 2024
7259c54
Merge branch 'dev/feature' into feature/toggleChanger
sovdeeth Aug 16, 2024
565fe7d
Merge branch 'dev/feature' into feature/toggleChanger
Olyno Nov 15, 2024
ab9b399
chore(EffToggle): check if accepts more than single value
Olyno Nov 15, 2024
8bc1de4
fix(EffToggle): avoid index reset when possible
Olyno Nov 15, 2024
adf2438
fix(test): rephrase error
Olyno Nov 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 63 additions & 41 deletions src/main/java/ch/njol/skript/effects/EffToggle.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,20 @@
*/
package ch.njol.skript.effects;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Openable;
import org.bukkit.block.data.Powerable;
import org.bukkit.event.Event;
import org.eclipse.jdt.annotation.Nullable;

import ch.njol.skript.Skript;
import ch.njol.skript.classes.Changer.ChangeMode;
import ch.njol.skript.classes.Changer.ChangerUtils;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Examples;
import ch.njol.skript.doc.Name;
Expand All @@ -40,63 +41,84 @@
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.util.Kleenean;

/**
* @author Peter Güttinger
*/
@SuppressWarnings("deprecation")
@Name("Toggle")
@Description("Toggle the state of a block.")
@Description("Toggle a boolean or the state of a block.")
@Examples({"# use arrows to toggle switches, doors, etc.",
"on projectile hit:",
"\tprojectile is arrow",
"\ttoggle the block at the arrow"})
@Since("1.4")
"\ttoggle the block at the arrow",
"",
"# With booleans",
"toggle gravity of player"
})
@Since("1.4, INSERT VERSION (booleans)")
public class EffToggle extends Effect {

static {
Skript.registerEffect(EffToggle.class, "(close|turn off|de[-]activate) %blocks%", "(toggle|switch) [[the] state of] %blocks%", "(open|turn on|activate) %blocks%");
Skript.registerEffect(EffToggle.class,
"(open|turn on|activate) %blocks%",
"(close|turn off|de[-]activate) %blocks%",
"(toggle|switch) [[the] state of] %booleans/blocks%"
);
Olyno marked this conversation as resolved.
Show resolved Hide resolved
}

private enum State {
ACTIVATE, DEACTIVATE, TOGGLE
Olyno marked this conversation as resolved.
Show resolved Hide resolved
}

@SuppressWarnings("null")
private Expression<Block> blocks;
private int toggle;
private Expression<?> toggledExpr;
Olyno marked this conversation as resolved.
Show resolved Hide resolved
private State state;

@SuppressWarnings({"unchecked", "null"})
@Override
public boolean init(final Expression<?>[] vars, final int matchedPattern, final Kleenean isDelayed, final ParseResult parseResult) {
blocks = (Expression<Block>) vars[0];
toggle = matchedPattern - 1;
public boolean init(Expression<?>[] vars, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
toggledExpr = (Expression<?>) vars[0];
state = State.values()[matchedPattern];
if (toggledExpr.getReturnType() == Boolean.class && !ChangerUtils.acceptsChange(toggledExpr, ChangeMode.SET, Boolean.class)) {
Skript.error(toggledExpr.toString(null, false) + " cannot be toggled");
return false;
}
return true;
}

@Override
protected void execute(final Event e) {
for (Block b : blocks.getArray(e)) {
BlockData data = b.getBlockData();
if (toggle == -1) {
if (data instanceof Openable)
((Openable) data).setOpen(false);
else if (data instanceof Powerable)
((Powerable) data).setPowered(false);
} else if (toggle == 1) {
if (data instanceof Openable)
((Openable) data).setOpen(true);
else if (data instanceof Powerable)
((Powerable) data).setPowered(true);
} else {
if (data instanceof Openable) // open = NOT was open
((Openable) data).setOpen(!((Openable) data).isOpen());
else if (data instanceof Powerable) // power = NOT power
((Powerable) data).setPowered(!((Powerable) data).isPowered());
protected void execute(Event event) {
ArrayList<Object> toggledValues = new ArrayList<>();
Olyno marked this conversation as resolved.
Show resolved Hide resolved
for (Object obj : toggledExpr.getArray(event)) {
if (obj instanceof Block) {
Block block = (Block) obj;
BlockData data = block.getBlockData();
if (state == State.TOGGLE) {
if (data instanceof Openable) // open = NOT was open
((Openable) data).setOpen(!((Openable) data).isOpen());
else if (data instanceof Powerable) // power = NOT power
((Powerable) data).setPowered(!((Powerable) data).isPowered());
Olyno marked this conversation as resolved.
Show resolved Hide resolved
} else {
boolean value = state == State.ACTIVATE;
if (data instanceof Openable)
((Openable) data).setOpen(value);
else if (data instanceof Powerable)
((Powerable) data).setPowered(value);
Olyno marked this conversation as resolved.
Show resolved Hide resolved
}

block.setBlockData(data);
toggledValues.add(block);
APickledWalrus marked this conversation as resolved.
Show resolved Hide resolved

} else if (obj instanceof Boolean) {
toggledValues.add(!(Boolean) obj);
}

b.setBlockData(data);
}
}

List<Object> filteredValues = toggledValues.stream().filter(
obj -> ChangerUtils.acceptsChange(toggledExpr, ChangeMode.SET, obj.getClass())
).collect(Collectors.toList());
toggledExpr.change(event, filteredValues.toArray(), ChangeMode.SET);
Olyno marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might need to note a behavior change here. For changing something like a list, I believe the indexes will now be lost, which was not prior behaviors. We might choose to only rewrite the list if it contains a boolean?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you're talking about the list, are you talking about the toggledExpr or the filteredValues, or even both?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we have a list like {_values::*} with:
{_values::pickle::name} = "APickledWalrus"
{_values::pickle::likesCake} = true
if we then do toggle {_values::*}, the indices such as name and likesCake will be lost (replaced by 1 and 2).
This is probably unavoidable. However, if we have a list like
{_values::pickle::name} = "APickledWalrus"
{_values::pickle::githubName} = "APickledWalrus"
if we then do toggle {_values::*}, there are no booleans to toggle, meaning we should not update the list (and cause it to lose its indices)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the code, don't i already do it?

https://github.com/SkriptLang/Skript/pull/4154/files#diff-4cdf11cdcad1ff81963a3380536868678c5781162395d093ecd42b33c71add01R74

Also, tests are failing, did i misunderstand what you meant?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There may have been some confusion, sorry.

Given a list containing "one" and "two", doing toggle {_list::*} should not modify the list since there is nothing to toggle (meaning the indexes will be preserved).

However, given a list containing "one", "two" and true, doing toggle {_list::*} should modify the list since the third value is a boolean (meaning the indexes will be lost).

I think the fix you made is correct, but the test is wrong.

Working with the testing you added, you should be testing:

set {_list::myFirstIndex::myFirstValue} to "hello"
set {_list::mySecondIndex::mySecondValue} to "world"
toggle {_list::*}
assert {_list::myFirstIndex::myFirstValue} is "hello" with "{_list::myFirstIndex::myFirstValue} should be toggled to 'hello'"
assert {_list::mySecondIndex::mySecondValue} is "world" with "{_list::mySecondIndex::mySecondValue} should be toggled to 'world'"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update: shouldn't we throw an error instead? If the user tries to toggle strings, it shouldn't work. If the variable list includes string, but also boolean, shouldn't we throw an error? Note that i don't think we should throw an error if all values are togglables.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, we can't really do runtime errors. I don't think it is just an issue to ignore the values and only change the ones that are actually togglable. You could also opt to not make any changes if there is an invalid type.

The main point still stands, though. If the list contains only blocks, we do not want to actually call the change method as it will reset the indices.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you confirm me the commit 8bc1de4 fixes this unexpected behavior?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it looks reasonable
you may want to check out #7120 changeInPlace utility method

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would need a usage example please. That being said, i will wait for this PR to be merged before doing any change regarding this change.

In terms of organization, either the changeInPlace PR is merged before this one, and so i will apply the change here, or this PR is merged before, and so i will apply the change in the other PR.

In any case, we need to merge one of them to move on the other.


Olyno marked this conversation as resolved.
Show resolved Hide resolved
}
Olyno marked this conversation as resolved.
Show resolved Hide resolved

@Override
public String toString(final @Nullable Event e, final boolean debug) {
return "toggle " + blocks.toString(e, debug);
public String toString(@Nullable Event event, final boolean debug) {
return "toggle " + toggledExpr.toString(event, debug);
}

}
82 changes: 82 additions & 0 deletions src/main/java/ch/njol/skript/expressions/ExprInverse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/**
* This file is part of Skript.
*
* Skript is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Skript is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Skript. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright Peter Güttinger, SkriptLang team and contributors
*/
package ch.njol.skript.expressions;

import org.bukkit.event.Event;
import org.eclipse.jdt.annotation.Nullable;

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.Expression;
import ch.njol.skript.lang.ExpressionType;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.lang.util.SimpleExpression;
import ch.njol.util.Kleenean;

@Name("Inverse Boolean")
@Description("An expression to obtain the inverse value of a boolean")
@Examples("set {_gravity} to inverse of player's flight mode")
@Since("INSERT VERSION")
public class ExprInverse extends SimpleExpression<Boolean> {

static {
Skript.registerExpression(ExprInverse.class, Boolean.class, ExpressionType.COMBINED,
"[the] (inverse|opposite) of %booleans%"
);
}

private Expression<Boolean> booleanExpr;

@Override
@SuppressWarnings("unchecked")
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
booleanExpr = (Expression<Boolean>) exprs[0];
return true;
}

@Override
@Nullable
protected Boolean[] get(Event event) {
Boolean[] original = booleanExpr.getArray(event);
Boolean[] toggled = new Boolean[original.length];
for (int i = 0; i < original.length; i++) {
toggled[i] = !original[i];
}
return toggled;
}

@Override
public boolean isSingle() {
return booleanExpr.isSingle();
}

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

@Override
public String toString(@Nullable Event event, boolean debug) {
return "inverse of " + booleanExpr.toString(event, debug);
}

}
27 changes: 27 additions & 0 deletions src/test/skript/tests/syntaxes/effects/EffToggle.sk
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
test "toggle effect":
set {_isToggled} to false
assert {_isToggled} is false with "{_isToggled} should be set to false"
toggle {_isToggled}
assert {_isToggled} is true with "{_isToggled} should be toggled to true"
set {_toggle::*} to false, false and false
assert {_toggle::1} is false with "{_toggle::1} should be set to false"
assert {_toggle::2} is false with "{_toggle::2} should be set to false"
assert {_toggle::3} is false with "{_toggle::3} should be set to false"
toggle {_toggle::*}
assert {_toggle::1} is true with "{_toggle::1} should be toggled to true"
assert {_toggle::2} is true with "{_toggle::2} should be toggled to true"
assert {_toggle::3} is true with "{_toggle::3} should be toggled to true"
assert inverse of {_isToggled} is false with "{_isToggled} should be toggled to false"

set {_block} to block at location(10, 10, 10, world "world")
set {_list::*} to true and {_block}
toggle {_list::*}
assert {_list::1} is false with "{_list::1} should be set to false"
assert amount of {_list::*} is 2 with "{_list::*} should be set to false and {_block}"
Olyno marked this conversation as resolved.
Show resolved Hide resolved

set block at location(10, 11, 10, world "world") to birch door
set {_door} to block at location(10, 11, 10, world "world")
assert {_door} is birch door with "{_door} should be birch door"
assert "%block data of {_door}%" contains "open=false" with "{_door} should be closed"
toggle {_door}
assert "%block data of {_door}%" contains "open=true" with "{_door} should be open"