diff --git a/engine/src/main/java/org/terasology/world/time/OnDawnEvent.java b/engine/src/main/java/org/terasology/world/time/OnDawnEvent.java new file mode 100644 index 00000000000..777dea66d80 --- /dev/null +++ b/engine/src/main/java/org/terasology/world/time/OnDawnEvent.java @@ -0,0 +1,28 @@ +/* + * Copyright 2013 MovingBlocks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.terasology.world.time; + +/** + * Sent to a world on dawn (beginning of a new day) + * + * @author Immortius + */ +public class OnDawnEvent extends TimeEventBase { + + public OnDawnEvent(long worldTimeMS) { + super(worldTimeMS); + } +} diff --git a/engine/src/main/java/org/terasology/world/time/OnDuskEvent.java b/engine/src/main/java/org/terasology/world/time/OnDuskEvent.java new file mode 100644 index 00000000000..2de56f552b7 --- /dev/null +++ b/engine/src/main/java/org/terasology/world/time/OnDuskEvent.java @@ -0,0 +1,28 @@ +/* + * Copyright 2013 MovingBlocks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.terasology.world.time; + +/** + * Sent to the world on dusk (half way through the day, when the sun sets) + * + * @author Immortius + */ +public class OnDuskEvent extends TimeEventBase { + + public OnDuskEvent(long worldTimeMS) { + super(worldTimeMS); + } +} diff --git a/engine/src/main/java/org/terasology/world/time/OnMiddayEvent.java b/engine/src/main/java/org/terasology/world/time/OnMiddayEvent.java new file mode 100644 index 00000000000..80f20129339 --- /dev/null +++ b/engine/src/main/java/org/terasology/world/time/OnMiddayEvent.java @@ -0,0 +1,28 @@ +/* + * Copyright 2013 MovingBlocks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.terasology.world.time; + +/** + * Sent to a world in the middle of daytime + * + * @author Immortius + */ +public class OnMiddayEvent extends TimeEventBase { + + public OnMiddayEvent(long worldTimeMS) { + super(worldTimeMS); + } +} diff --git a/engine/src/main/java/org/terasology/world/time/OnMidnightEvent.java b/engine/src/main/java/org/terasology/world/time/OnMidnightEvent.java new file mode 100644 index 00000000000..69f77f8489c --- /dev/null +++ b/engine/src/main/java/org/terasology/world/time/OnMidnightEvent.java @@ -0,0 +1,28 @@ +/* + * Copyright 2013 MovingBlocks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.terasology.world.time; + +/** + * Sent to a world at the middle of the night + * + * @author Immortius + */ +public class OnMidnightEvent extends TimeEventBase { + + public OnMidnightEvent(long worldTimeMS) { + super(worldTimeMS); + } +} diff --git a/engine/src/main/java/org/terasology/world/time/TimeEventBase.java b/engine/src/main/java/org/terasology/world/time/TimeEventBase.java new file mode 100644 index 00000000000..f15ceb49339 --- /dev/null +++ b/engine/src/main/java/org/terasology/world/time/TimeEventBase.java @@ -0,0 +1,64 @@ +/* + * Copyright 2014 MovingBlocks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.terasology.world.time; + +import org.terasology.entitySystem.event.Event; + +import com.google.common.math.LongMath; + +/** + * A base class for different timer events + * @author Martin Steiger + */ +public abstract class TimeEventBase implements Event { + + private long worldTimeMS; + private long timeInDay; + + public TimeEventBase(long worldTimeMS) { + this.worldTimeMS = worldTimeMS; + this.timeInDay = LongMath.mod(worldTimeMS, WorldTime.DAY_LENGTH); + } + + /** + * @return the time of day as a fraction + */ + public float getDayTime() { + return timeInDay / (float) WorldTime.DAY_LENGTH; + } + + /** + * @return the time of day in milli secs + */ + public long getDayTimeInMs() { + return timeInDay; + } + + /** + * @return the world time in days + */ + public float getWorldTime() { + return worldTimeMS / (float) WorldTime.DAY_LENGTH; + } + + /** + * @return the world time in milli secs + */ + public long getWorldTimeInMs() { + return worldTimeMS; + } +} diff --git a/engine/src/main/java/org/terasology/world/time/WorldTime.java b/engine/src/main/java/org/terasology/world/time/WorldTime.java index 1b0a318583c..3bed49f5542 100644 --- a/engine/src/main/java/org/terasology/world/time/WorldTime.java +++ b/engine/src/main/java/org/terasology/world/time/WorldTime.java @@ -24,14 +24,10 @@ public interface WorldTime extends ComponentSystem { long DAY_LENGTH = 1000 * 60 * 60 * 24; - long DAYS_TO_MS = (DAY_LENGTH); - float MS_TO_DAYS = 1.f / (DAYS_TO_MS); - - long DAWN_TIME = 0; - long MIDDAY_TIME = DAY_LENGTH / 4; - long DUSK_TIME = DAY_LENGTH / 2; - long MIDNIGHT_TIME = 3 * DAY_LENGTH / 4; - + /** + * The number of timer tick events per day + */ + long TICKS_PER_DAY = 100; /** * @return World time in milliseconds. diff --git a/engine/src/main/java/org/terasology/world/time/WorldTimeEvent.java b/engine/src/main/java/org/terasology/world/time/WorldTimeEvent.java index 7e61b90f9bc..b6b6707dbc0 100644 --- a/engine/src/main/java/org/terasology/world/time/WorldTimeEvent.java +++ b/engine/src/main/java/org/terasology/world/time/WorldTimeEvent.java @@ -15,121 +15,26 @@ */ package org.terasology.world.time; -import org.terasology.entitySystem.event.Event; - -import com.google.common.math.LongMath; - /** * A timer event that represents a (world-based) time instant * @author Immortius * @author Martin Steiger */ -public class WorldTimeEvent implements Event { - private long worldTimeMS; - private long timeInDay; +public class WorldTimeEvent extends TimeEventBase { public WorldTimeEvent(long worldTimeMS) { - this.worldTimeMS = worldTimeMS; - this.timeInDay = LongMath.mod(worldTimeMS, WorldTime.DAY_LENGTH); - } - - /** - * @return the world time in milli secs - */ - public long getWorldTimeMS() { - return worldTimeMS; - } - - /** - * @return the world time in days - */ - public float getWorldTime() { - return WorldTime.MS_TO_DAYS * worldTimeMS; - } - - /** - * @return true if at dawn/sunrise (true exactly once per day) - */ - public boolean isDawn() { - return timeInDay == WorldTime.DAWN_TIME; - } - - /** - * @return true if at midday/noon (true exactly once per day) - */ - public boolean isMidday() { - return timeInDay == WorldTime.MIDDAY_TIME; - } - - /** - * @return true if at dusk/sunset (true exactly once per day) - */ - public boolean isDusk() { - return timeInDay == WorldTime.DUSK_TIME; - } - - /** - * @return true if after DAWN and before MIDDAY - */ - public boolean isMorning() { - return timeInDay > WorldTime.DAWN_TIME && timeInDay < WorldTime.MIDDAY_TIME; - } - - /** - * @return true if after MIDDAY and before DUSK - */ - public boolean isAfternoon() { - return timeInDay > WorldTime.MIDDAY_TIME && timeInDay < WorldTime.DUSK_TIME; - } - - /** - * @return true if after DUSK and before DAWN - */ - public boolean isNight() { - return timeInDay > WorldTime.DUSK_TIME || timeInDay < WorldTime.DAWN_TIME; + super(worldTimeMS); } - /** - * @return true if at midnight (true exactly once per day) - */ - public boolean isMidnight() { - return timeInDay == WorldTime.MIDNIGHT_TIME; + public boolean matchesDaily(float fraction) { + if (Math.abs(getDayTime() - fraction) < 0.5f / WorldTime.TICKS_PER_DAY) { + System.out.println(Math.abs(getDayTime() - fraction)); + } + return Math.abs(getDayTime() - fraction) < 0.5f / WorldTime.TICKS_PER_DAY; } @Override public String toString() { - return String.format("WorldTimeEvent [%s ms -> %.2f days (%s)]", worldTimeMS, getWorldTime(), getDayTimeText()); - } - - private String getDayTimeText() { - if (isDusk()) { - return "dusk"; - } - - if (isMorning()) { - return "morning"; - } - - if (isMidday()) { - return "midday"; - } - - if (isAfternoon()) { - return "afternoon"; - } - - if (isDawn()) { - return "dawn"; - } - - if (isNight()) { - return "night"; - } - - if (isMidnight()) { - return "mignight"; - } - - return "UNDEFINED"; + return String.format("WorldTimeEvent [%s ms -> %.2f days]", getWorldTimeInMs(), getWorldTime()); } } diff --git a/engine/src/main/java/org/terasology/world/time/WorldTimeImpl.java b/engine/src/main/java/org/terasology/world/time/WorldTimeImpl.java index abba8752435..a105eddf5bf 100644 --- a/engine/src/main/java/org/terasology/world/time/WorldTimeImpl.java +++ b/engine/src/main/java/org/terasology/world/time/WorldTimeImpl.java @@ -23,6 +23,9 @@ import org.terasology.registry.In; import org.terasology.world.WorldComponent; +import com.google.common.math.LongMath; + +import java.math.RoundingMode; import java.util.concurrent.atomic.AtomicLong; /** @@ -30,9 +33,14 @@ */ public class WorldTimeImpl extends BaseComponentSystem implements WorldTime, UpdateSubscriberSystem { + private static final long DAWN_TIME = DAY_LENGTH; + private static final long MIDDAY_TIME = DAY_LENGTH / 4; + private static final long DUSK_TIME = DAY_LENGTH / 2; + private static final long MIDNIGHT_TIME = 3 * DAY_LENGTH / 4; + private static final float WORLD_TIME_MULTIPLIER = 48f; - private static final long TICK_RATE = DAYS_TO_MS / 100; + private static final long TICK_RATE = DAY_LENGTH / TICKS_PER_DAY; private AtomicLong worldTime = new AtomicLong(0); @@ -54,7 +62,7 @@ public float getSeconds() { @Override public float getDays() { - return MS_TO_DAYS * worldTime.get(); + return worldTime.get() / (float) DAY_LENGTH; } @Override @@ -70,16 +78,18 @@ public void setMilliseconds(long newWorldTime) { @Override public void setDays(float timeInDays) { - setMilliseconds((long) ((double) timeInDays * DAYS_TO_MS)); + setMilliseconds((long) ((double) timeInDays * DAY_LENGTH)); } @Override public void update(float delta) { long deltaMs = time.getDeltaInMs(); if (deltaMs > 0) { - deltaMs = (long) (deltaMs * WORLD_TIME_MULTIPLIER); + deltaMs = (long) (deltaMs * WORLD_TIME_MULTIPLIER * 1); long startTime = worldTime.getAndAdd(deltaMs); long endTime = startTime + deltaMs; + long timeInDay = LongMath.mod(startTime, DAY_LENGTH); + long day = LongMath.divide(startTime, DAY_LENGTH, RoundingMode.FLOOR); long startTick = startTime / TICK_RATE; long endTick = (endTime) / TICK_RATE; @@ -88,6 +98,26 @@ public void update(float delta) { long tick = endTime - endTime % TICK_RATE; getWorldEntity().send(new WorldTimeEvent(tick)); } + + if (timeInDay < MIDDAY_TIME && timeInDay + deltaMs >= MIDDAY_TIME) { + long tick = day * DAY_LENGTH + MIDDAY_TIME; + getWorldEntity().send(new OnMiddayEvent(tick)); + } + + if (timeInDay < DUSK_TIME && timeInDay + deltaMs >= DUSK_TIME) { + long tick = day * DAY_LENGTH + DUSK_TIME; + getWorldEntity().send(new OnDuskEvent(tick)); + } + + if (timeInDay < MIDNIGHT_TIME && timeInDay + deltaMs >= MIDNIGHT_TIME) { + long tick = day * DAY_LENGTH + MIDNIGHT_TIME; + getWorldEntity().send(new OnMidnightEvent(tick)); + } + + if (timeInDay < DAWN_TIME && timeInDay + deltaMs >= DAWN_TIME) { + long tick = day * DAY_LENGTH + DAWN_TIME; + getWorldEntity().send(new OnDawnEvent(tick)); + } } }