Skip to content

Commit

Permalink
⚒️ Fix Time Played NSME (SkriptLang#4938)
Browse files Browse the repository at this point in the history
* Fix Time Played NSME
  • Loading branch information
AyhamAl-Ali authored Sep 16, 2022
1 parent 9764611 commit f564093
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 32 deletions.
84 changes: 52 additions & 32 deletions src/main/java/ch/njol/skript/expressions/ExprTimePlayed.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,68 +18,73 @@
*/
package ch.njol.skript.expressions;

import ch.njol.skript.classes.Changer.ChangeMode;
import org.bukkit.OfflinePlayer;
import org.bukkit.Statistic;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.eclipse.jdt.annotation.Nullable;

import ch.njol.skript.Skript;
import ch.njol.skript.classes.Changer;
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.RequiredPlugins;
import ch.njol.skript.doc.Since;
import ch.njol.skript.expressions.base.SimplePropertyExpression;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.util.Timespan;
import ch.njol.util.Kleenean;
import ch.njol.util.coll.CollectionUtils;
import org.bukkit.OfflinePlayer;
import org.bukkit.Statistic;
import org.bukkit.event.Event;
import org.eclipse.jdt.annotation.Nullable;

@Name("Time Played")
@Description("The amount of time a player has played for on the server. This info is stored in the player's statistics in " +
"the main world's data folder. Changing this will also change the player's stats which can be views in the client's statistics menu.")
@Examples({"set {_t} to time played of player",
@Description({
"The amount of time a player has played for on the server. This info is stored in the player's statistics in " +
"the main world's data folder. Changing this will also change the player's stats which can be views in the client's statistics menu.",
"Using this expression on offline players on Minecraft 1.14 and below will return nothing <code>&lt;none&gt;</code>."
})
@Examples({
"set {_t} to time played of player",
"if player's time played is greater than 10 minutes:",
"\tgive player a diamond sword",
"set player's time played to 0 seconds"})
@Since("2.5")
"",
"set player's time played to 0 seconds"
})
@RequiredPlugins("MC 1.15+ (offline players)")
@Since("2.5, INSERT VERSION (offline players)")
public class ExprTimePlayed extends SimplePropertyExpression<OfflinePlayer, Timespan> {

private static final boolean IS_OFFLINE_SUPPORTED = Skript.methodExists(OfflinePlayer.class, "getStatistic", Statistic.class);

static {
register(ExprTimePlayed.class, Timespan.class, "time played", "offlineplayers");
}

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

@Nullable
@Override
public Timespan convert(OfflinePlayer offlinePlayer) {
return Timespan.fromTicks_i(offlinePlayer.getStatistic(Statistic.PLAY_ONE_MINUTE));
return getTimePlayed(offlinePlayer);
}

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

@Override
public void change(Event e, @Nullable Object[] delta, ChangeMode mode) {
public void change(Event event, @Nullable Object[] delta, ChangeMode mode) {
if (delta == null)
return;

long ticks = ((Timespan) delta[0]).getTicks_i();
for (OfflinePlayer offlinePlayer : getExpr().getArray(e)) {
long playerTicks = offlinePlayer.getStatistic(Statistic.PLAY_ONE_MINUTE);
for (OfflinePlayer offlinePlayer : getExpr().getArray(event)) {
if (!IS_OFFLINE_SUPPORTED && !offlinePlayer.isOnline())
continue;

Timespan playerTimespan = getTimePlayed(offlinePlayer);
if (playerTimespan == null)
continue;

long playerTicks = playerTimespan.getTicks_i();
switch (mode) {
case ADD:
ticks = playerTicks + ticks;
Expand All @@ -88,7 +93,12 @@ public void change(Event e, @Nullable Object[] delta, ChangeMode mode) {
ticks = playerTicks - ticks;
break;
}
offlinePlayer.setStatistic(Statistic.PLAY_ONE_MINUTE, (int) ticks);

if (IS_OFFLINE_SUPPORTED) {
offlinePlayer.setStatistic(Statistic.PLAY_ONE_MINUTE, (int) ticks);
} else if (offlinePlayer.isOnline()) {
offlinePlayer.getPlayer().setStatistic(Statistic.PLAY_ONE_MINUTE, (int) ticks); // No NPE due to isOnline check
}
}
}

Expand All @@ -101,5 +111,15 @@ public Class<? extends Timespan> getReturnType() {
protected String getPropertyName() {
return "time played";
}

@Nullable
private Timespan getTimePlayed(OfflinePlayer offlinePlayer) {
if (IS_OFFLINE_SUPPORTED) {
return Timespan.fromTicks_i(offlinePlayer.getStatistic(Statistic.PLAY_ONE_MINUTE));
} else if (offlinePlayer.isOnline()) {
return Timespan.fromTicks_i(offlinePlayer.getPlayer().getStatistic(Statistic.PLAY_ONE_MINUTE));
}
return null;
}

}
6 changes: 6 additions & 0 deletions src/test/skript/tests/regressions/4938-time played.sk
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
test "time played":
set {_time} to time played of "Notch" parsed as offlineplayer
if running minecraft "1.15":
assert {_time} is equal to 0 seconds with "Notch hacked your server and built a dirt house on your server (time: %{_time}%)"
else:
assert {_time} is not set with "Played time of offline players are not supported but seems like Notch is a hacker! (time: %{_time}%)"

0 comments on commit f564093

Please sign in to comment.