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

Update ExprTime #7082

Merged
merged 10 commits into from
Sep 22, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
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
152 changes: 76 additions & 76 deletions src/main/java/ch/njol/skript/expressions/ExprTime.java
Original file line number Diff line number Diff line change
@@ -1,27 +1,5 @@
/**
* 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.World;
import org.bukkit.event.Event;
import org.jetbrains.annotations.Nullable;

import ch.njol.skript.Skript;
import ch.njol.skript.classes.Changer.ChangeMode;
import ch.njol.skript.doc.Description;
Expand All @@ -32,40 +10,53 @@
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.ExpressionType;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.registrations.Classes;
import ch.njol.skript.util.Getter;
import ch.njol.skript.util.Time;
import ch.njol.skript.util.Timeperiod;
import ch.njol.skript.util.Timespan;
import ch.njol.util.Kleenean;
import ch.njol.util.coll.CollectionUtils;
import org.bukkit.World;
import org.bukkit.event.Event;
import org.jetbrains.annotations.Nullable;

/**
* @author Peter Güttinger
*/
@Name("Time")
@Description("The <a href='classes.html#time'>time</a> of a world.")
@Examples({"time in world is between 18:00 and 6:00:",
" broadcast \"It's night-time, watch out for monsters!\""})
@Description({
"The <a href='classes.html#time'>time</a> of a world.",
"Use the \"minecraft <a href='classes.html#timespan'>timespan</a>\" syntax to change the time according " +
"to Minecraft's time intervals.",
"Since Minecraft uses discrete intervals for time (ticks), " +
"changing the time by real-world minutes or real-world seconds only changes it approximately.",
"Removing an amount of time from a world's time will move the clock forward a day."
})
@Examples({
"set time of world \"world\" to 2:00",
"add 2 minecraft hours to time of world \"world\"",
"add 54 real seconds to time of world \"world\" # approximately 1 minecraft hour"
})
@Since("1.0")
public class ExprTime extends PropertyExpression<World, Time> {

private static final int TIME_TO_TIMESPAN_OFFSET = 18000;
Efnilite marked this conversation as resolved.
Show resolved Hide resolved

static {
Skript.registerExpression(ExprTime.class, Time.class, ExpressionType.PROPERTY, "[the] time[s] [([with]in|of) %worlds%]", "%worlds%'[s] time[s]");
Skript.registerExpression(ExprTime.class, Time.class, ExpressionType.PROPERTY,
"[the] time[s] [([with]in|of) %worlds%]", "%worlds%'[s] time[s]");
Efnilite marked this conversation as resolved.
Show resolved Hide resolved
}
@SuppressWarnings({"unchecked", "null"})

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

@Override
protected Time[] get(final Event e, final World[] source) {
return get(source, new Getter<Time, World>() {
protected Time[] get(Event event, World[] worlds) {
return get(worlds, new Getter<>() {
Efnilite marked this conversation as resolved.
Show resolved Hide resolved
@Override
public Time get(final World w) {
return new Time((int) w.getTime());
public Time get(World world) {
return new Time((int) world.getTime());
}
});
}
Expand All @@ -76,56 +67,65 @@ public Class<?>[] acceptChange(final ChangeMode mode) {
switch (mode) {
case ADD:
case REMOVE:
return CollectionUtils.array(Timespan.class);
// allow time to avoid conversion to timespan, which causes all sorts of headaches
return CollectionUtils.array(Time.class, Timespan.class);
case SET:
return CollectionUtils.array(Time.class, Timeperiod.class);
Efnilite marked this conversation as resolved.
Show resolved Hide resolved
case DELETE:
case REMOVE_ALL:
case RESET:
Efnilite marked this conversation as resolved.
Show resolved Hide resolved
default:
return null;
}
}

@Override
public void change(final Event e, final @Nullable Object[] delta, final ChangeMode mode) {
final World[] worlds = getExpr().getArray(e);
int mod = 1;
switch (mode) {
case SET:
assert delta != null;
final int time = delta[0] instanceof Time ? ((Time) delta[0]).getTicks() : ((Timeperiod) delta[0]).start;
for (final World w : worlds) {
w.setTime(time);
}
break;
case REMOVE:
mod = -1;
//$FALL-THROUGH$
case ADD:
assert delta != null;
final Timespan ts = (Timespan) delta[0];
for (final World w : worlds) {
w.setTime(w.getTime() + mod * ts.getTicks());
}
break;
case DELETE:
case REMOVE_ALL:
case RESET:
assert false;
public void change(Event event, Object @Nullable [] delta, ChangeMode mode) {
if (getExpr() == null || delta == null)
return;

Object time = delta[0];
if (time == null)
return;

World[] worlds = getExpr().getArray(event);

long ticks = 0;
if (time instanceof Time) {
if (mode != ChangeMode.SET) {
ticks = ((Time) time).getTicks() - TIME_TO_TIMESPAN_OFFSET; // allows for using "add 2:00" without going to new day
} else {
ticks = ((Time) time).getTicks();
}
} else if (time instanceof Timespan) {
ticks = ((Timespan) time).getAs(Timespan.TimePeriod.TICK);
} else if (time instanceof Timeperiod) {
ticks = ((Timeperiod) time).start;
sovdeeth marked this conversation as resolved.
Show resolved Hide resolved
}

for (World world : worlds) {
switch (mode) {
case ADD:
world.setTime(world.getTime() + ticks);
break;
case REMOVE:
world.setTime(world.getTime() - ticks);
break;
case SET:
world.setTime(ticks);
break;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

you could add the for loop to a helper method, and call the method in each of the instanceof checks, this avoids the need for the ticks variable (except for in time instanceof Time)

of course you dont have to do this, i just think it'll look a little neater

Copy link
Member Author

Choose a reason for hiding this comment

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

good idea but i think this is easier to understand. if the team thinks your approach is better, i'll change it

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

@Override
public Class<Time> getReturnType() {
return Time.class;
}

@Override
public String toString(final @Nullable Event event, final boolean debug) {
if (event == null)
return "the time in " + getExpr().toString(event, debug);
return Classes.getDebugMessage(getAll(event));
public String toString(@Nullable Event event, boolean debug) {
if (getExpr() == null)
return "the time";

return "the time in " + getExpr().toString(event, debug);
Efnilite marked this conversation as resolved.
Show resolved Hide resolved
}

}
29 changes: 29 additions & 0 deletions src/test/skript/tests/regressions/7081-time in worlds.sk
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
test "time in worlds":

set {_w} to world "world"
set {_startTime} to time in {_w}

Efnilite marked this conversation as resolved.
Show resolved Hide resolved
set time of {_w} to 00:00
assert time of {_w} is 00:00 with "time in world should be 00:00"
add 1 hour and 20 minutes to time of {_w} # add 4 Minecraft days
assert time of {_w} is 00:00 with "time in world should be 00:00"
add 1 minecraft hour and 20 minecraft minutes to time of {_w}
assert time of {_w} is 01:20 with "time in world should be 01:20"
add 1 minecraft day to time of {_w}
assert time of {_w} is 01:20 with "time in world should be 01:20"

remove 1 hour and 20 minutes from time of {_w} # remove 4 Minecraft days
assert time of {_w} is 01:20 with "time in world should be 01:20"
remove 1 minecraft hour and 20 minecraft minutes from time of {_w}
assert time of {_w} is 00:00 with "time in world should be 00:00"

add 1 minecraft hour to time of {_w}
assert time of {_w} is 01:00 with "time in world should be 01:00"
add 01:01 to time of {_w}
assert time of {_w} is 02:01 with "time in world should be 02:01"
remove 01:01 from time of {_w}
assert time of {_w} is 01:00 with "time in world should be 01:00"
remove 1 minecraft hour from time of {_w}
assert time of {_w} is 00:00 with "time in world should be 00:00"

set time of {_w} to {_startTime}