Skip to content

Commit

Permalink
🚀 Item cooldown expression + condition (SkriptLang#4198)
Browse files Browse the repository at this point in the history
  • Loading branch information
AyhamAl-Ali authored and NotSoDelayed committed Oct 30, 2023
1 parent 7b628ec commit ba2e68f
Show file tree
Hide file tree
Showing 3 changed files with 233 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/main/java/ch/njol/skript/aliases/ItemType.java
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,14 @@ public boolean hasBlock() {
}
return false;
}

/**
* Useful for checking if materials represent an item or a block. Materials that are not items don't have ItemData
* @return Whether this ItemType has at least one ItemData that represents it whether it's a block or an item
*/
public boolean hasType() {
return !types.isEmpty();
}

/**
* Sets the given block to this ItemType
Expand Down
81 changes: 81 additions & 0 deletions src/main/java/ch/njol/skript/conditions/CondHasItemCooldown.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* 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.conditions;

import ch.njol.skript.Skript;
import ch.njol.skript.aliases.ItemType;
import ch.njol.skript.conditions.base.PropertyCondition;
import ch.njol.skript.conditions.base.PropertyCondition.PropertyType;
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.Condition;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.util.Kleenean;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.eclipse.jdt.annotation.Nullable;

@Name("Has Item Cooldown")
@Description("Check whether a cooldown is active on the specified material for a specific player.")
@Examples({
"if player has player's tool on cooldown:",
"\tsend \"You can't use this item right now. Wait %item cooldown of player's tool for player%\""
})
@Since("INSERT VERSION")
public class CondHasItemCooldown extends Condition {

static {
Skript.registerCondition(CondHasItemCooldown.class,
"%players% (has|have) [([an] item|a)] cooldown (on|for) %itemtypes%",
"%players% (has|have) %itemtypes% on [(item|a)] cooldown",
"%players% (doesn't|does not|do not|don't) have [([an] item|a)] cooldown (on|for) %itemtypes%",
"%players% (doesn't|does not|do not|don't) have %itemtypes% on [(item|a)] cooldown");
}

private Expression<Player> players;
private Expression<ItemType> itemtypes;

@Override
@SuppressWarnings("unchecked")
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
players = (Expression<Player>) exprs[0];
itemtypes = (Expression<ItemType>) exprs[1];
setNegated(matchedPattern > 1);
return true;
}

@Override
public boolean check(Event event) {
return players.check(event, (player) ->
itemtypes.check(event, (itemType) ->
itemType.hasType() && player.hasCooldown(itemType.getMaterial())
)
);
}

@Override
public String toString(@Nullable Event event, boolean debug) {
return PropertyCondition.toString(this, PropertyType.HAVE, event, debug, players,
itemtypes.toString(event, debug) + " on cooldown");
}

}
144 changes: 144 additions & 0 deletions src/main/java/ch/njol/skript/expressions/ExprItemCooldown.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/**
* 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 ch.njol.skript.Skript;
import ch.njol.skript.aliases.ItemType;
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.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.skript.util.Timespan;
import ch.njol.util.Kleenean;
import ch.njol.util.coll.CollectionUtils;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.eclipse.jdt.annotation.Nullable;

import java.util.List;
import java.util.stream.Collectors;

@Name("Item Cooldown")
@Description("Change the cooldown of a specific material to a certain amount of <a href='./classes.html#timespan'>Timespan</a>.")
@Examples({
"on right click using stick:",
"\tset item cooldown of player's tool for player to 1 minute",
"\tset item cooldown of stone and grass for all players to 20 seconds",
"\treset item cooldown of cobblestone and dirt for all players"
})
@Since("INSERT VERSION")
public class ExprItemCooldown extends SimpleExpression<Timespan> {

static {
Skript.registerExpression(ExprItemCooldown.class, Timespan.class, ExpressionType.COMBINED,
"[the] [item] cooldown of %itemtypes% for %players%",
"%players%'[s] [item] cooldown for %itemtypes%");
}

@SuppressWarnings("NotNullFieldNotInitialized")
private Expression<Player> players;
@SuppressWarnings("NotNullFieldNotInitialized")
private Expression<ItemType> itemtypes;

@Override
@SuppressWarnings("unchecked")
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
players = (Expression<Player>) exprs[matchedPattern ^ 1];
itemtypes = (Expression<ItemType>) exprs[matchedPattern];
return true;
}

@Override
protected Timespan[] get(Event event) {
Player[] players = this.players.getArray(event);

List<ItemType> itemTypes = this.itemtypes.stream(event)
.filter(ItemType::hasType)
.collect(Collectors.toList());

Timespan[] timespan = new Timespan[players.length * itemTypes.size()];

int i = 0;
for (Player player : players) {
for (ItemType itemType : itemTypes) {
timespan[i++] = Timespan.fromTicks_i(player.getCooldown(itemType.getMaterial()));
}
}
return timespan;
}

@Override
@Nullable
public Class<?>[] acceptChange(ChangeMode mode) {
return mode == ChangeMode.REMOVE_ALL ? null : CollectionUtils.array(Timespan.class);
}

@Override
public void change(Event event, Object @Nullable [] delta, ChangeMode mode) {
if (mode != ChangeMode.RESET && mode != ChangeMode.DELETE && delta == null)
return;

int ticks = delta != null ? (int) ((Timespan) delta[0]).getTicks_i() : 0; // 0 for DELETE/RESET
Player[] players = this.players.getArray(event);
List<ItemType> itemTypes = this.itemtypes.stream(event)
.filter(ItemType::hasType)
.collect(Collectors.toList());

for (Player player : players) {
for (ItemType itemtype : itemTypes) {
Material material = itemtype.getMaterial();
switch (mode) {
case RESET:
case DELETE:
case SET:
player.setCooldown(material, ticks);
break;
case REMOVE:
player.setCooldown(material, Math.max(player.getCooldown(material) - ticks, 0));
break;
case ADD:
player.setCooldown(material, player.getCooldown(material) + ticks);
break;
}
}
}
}

@Override
public boolean isSingle() {
return players.isSingle() && itemtypes.isSingle();
}

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

@Override
public String toString(@Nullable Event event, boolean debug) {
return "cooldown of " + itemtypes.toString(event, debug) + " for " + players.toString(event, debug);
}

}

0 comments on commit ba2e68f

Please sign in to comment.