From 26d2942f6d27bfdf4e789f994962d0a5036ffa3a Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Sat, 2 May 2020 04:46:01 +0200 Subject: [PATCH 01/68] Bump forge version number --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index c115928..7c5f35a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ modVersion=0.1.1 groupName=yooksi minecraftVersion=1.15.2 -forgeVersion=31.1.46 +forgeVersion=31.1.63 mappingMCVersion=1.15.1 mappingBuild=20200225 From 632afff214cb24daedd89eea3c11859a6685e80a Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Sat, 2 May 2020 04:46:14 +0200 Subject: [PATCH 02/68] Bump MCP mapping build number --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 7c5f35a..e4255f0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,6 +10,6 @@ groupName=yooksi minecraftVersion=1.15.2 forgeVersion=31.1.63 mappingMCVersion=1.15.1 -mappingBuild=20200225 +mappingBuild=20200501 mixinBootstrapVer=1.0.2 From d4fa5eb247113fc3ef4652f1b035bf1b5eaed02c Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Sat, 2 May 2020 09:12:27 +0200 Subject: [PATCH 03/68] Remove redundant mixin class --- .../mixin/MinecraftServer_tickMixin.java | 25 ------------------- src/main/resources/timelib.mixins.json | 1 - 2 files changed, 26 deletions(-) delete mode 100644 src/main/java/io/yooksi/timelib/mixin/MinecraftServer_tickMixin.java diff --git a/src/main/java/io/yooksi/timelib/mixin/MinecraftServer_tickMixin.java b/src/main/java/io/yooksi/timelib/mixin/MinecraftServer_tickMixin.java deleted file mode 100644 index 2cc969e..0000000 --- a/src/main/java/io/yooksi/timelib/mixin/MinecraftServer_tickMixin.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.yooksi.timelib.mixin; - -import java.util.function.BooleanSupplier; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import io.yooksi.timelib.Tick; -import net.minecraft.server.MinecraftServer; - -@Mixin(MinecraftServer.class) -@SuppressWarnings("unused") -public abstract class MinecraftServer_tickMixin { - - @Inject(method = "tick", at = @At(value = "INVOKE", - target = "Lnet/minecraft/server/MinecraftServer;updateTimeLightAndEntities" + - "(Ljava/util/function/BooleanSupplier;)V", - shift = At.Shift.BEFORE, ordinal = 0) - ) - private void onTick(BooleanSupplier booleanSupplier_1, CallbackInfo ci) { - Tick.process_entities = true; - } -} diff --git a/src/main/resources/timelib.mixins.json b/src/main/resources/timelib.mixins.json index 2b213ac..2891b5e 100644 --- a/src/main/resources/timelib.mixins.json +++ b/src/main/resources/timelib.mixins.json @@ -5,7 +5,6 @@ "refmap": "main.refmap.json", "mixins": [ "MinecraftServer_runMixin", - "MinecraftServer_tickMixin", "CommandsMixin" ], "client": [ From 4bb4687c38481dc4e3796c714ec62e58100e1234 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Sat, 2 May 2020 09:15:42 +0200 Subject: [PATCH 04/68] Rename Tick class --- .../io/yooksi/timelib/{Tick.java => TickRate.java} | 12 ++++++------ .../io/yooksi/timelib/command/TickRateCommand.java | 2 +- .../timelib/mixin/MinecraftServer_runMixin.java | 6 +++--- .../yooksi/timelib/mixin/Timer_updateTimerMixin.java | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) rename src/main/java/io/yooksi/timelib/{Tick.java => TickRate.java} (71%) diff --git a/src/main/java/io/yooksi/timelib/Tick.java b/src/main/java/io/yooksi/timelib/TickRate.java similarity index 71% rename from src/main/java/io/yooksi/timelib/Tick.java rename to src/main/java/io/yooksi/timelib/TickRate.java index 9ff7c48..9445d72 100644 --- a/src/main/java/io/yooksi/timelib/Tick.java +++ b/src/main/java/io/yooksi/timelib/TickRate.java @@ -1,6 +1,6 @@ package io.yooksi.timelib; -public class Tick { +public class TickRate { public static final float DEFAULT_RATE = 20.0f; @@ -10,13 +10,13 @@ public class Tick { public static float changeRate(float rate) { - Tick.rate = rate; - long mspt = (long) (1000.0 / Tick.rate); + TickRate.rate = rate; + long mspt = (long) (1000.0 / TickRate.rate); if (mspt <= 0L) { - mspt = 1L; Tick.rate = 1000.0f; + mspt = 1L; TickRate.rate = 1000.0f; } - Tick.mspt = (float) mspt; - return Tick.rate; + TickRate.mspt = (float) mspt; + return TickRate.rate; } public static float resetRate() { diff --git a/src/main/java/io/yooksi/timelib/command/TickRateCommand.java b/src/main/java/io/yooksi/timelib/command/TickRateCommand.java index 30ce592..6c7dd69 100644 --- a/src/main/java/io/yooksi/timelib/command/TickRateCommand.java +++ b/src/main/java/io/yooksi/timelib/command/TickRateCommand.java @@ -3,7 +3,7 @@ import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.FloatArgumentType; -import io.yooksi.timelib.Tick; +import io.yooksi.timelib.TickRate; import net.minecraft.command.CommandSource; import net.minecraft.command.Commands; import net.minecraft.util.text.StringTextComponent; diff --git a/src/main/java/io/yooksi/timelib/mixin/MinecraftServer_runMixin.java b/src/main/java/io/yooksi/timelib/mixin/MinecraftServer_runMixin.java index 660a49d..f05d6cc 100644 --- a/src/main/java/io/yooksi/timelib/mixin/MinecraftServer_runMixin.java +++ b/src/main/java/io/yooksi/timelib/mixin/MinecraftServer_runMixin.java @@ -10,7 +10,7 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import io.yooksi.timelib.Tick; +import io.yooksi.timelib.TickRate; import net.minecraft.profiler.DebugProfiler; import net.minecraft.server.MinecraftServer; import net.minecraft.util.Util; @@ -59,7 +59,7 @@ private void modifiedRunLoop(CallbackInfo ci) { while (this.serverRunning) { long msThisTick, long_1; - float tickMspt = Tick.getMspt(); + float tickMspt = TickRate.getMspt(); // Tickrate changed. Ensure that we use the correct value. if (Math.abs(msptAccum - tickMspt) > 1.0f) { @@ -69,7 +69,7 @@ private void modifiedRunLoop(CallbackInfo ci) { msptAccum += tickMspt - msThisTick; long_1 = Util.milliTime() - this.serverTime; - float float_1 = 1000L + 20 * Tick.getMspt(); + float float_1 = 1000L + 20 * TickRate.getMspt(); float float_2 = 10000L + 100 * tickMspt; //smoothed out delay to include mcpt component. With 50L gives defaults. diff --git a/src/main/java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java b/src/main/java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java index 703c2b8..e69bd3c 100644 --- a/src/main/java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java +++ b/src/main/java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java @@ -4,7 +4,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import io.yooksi.timelib.Tick; +import io.yooksi.timelib.TickRate; import net.minecraft.util.Timer; @SuppressWarnings("unused") From 2036b9d80a32771c372aba7b783c0a4562d86030 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Sat, 2 May 2020 09:16:14 +0200 Subject: [PATCH 05/68] Remove redundant class field --- src/main/java/io/yooksi/timelib/TickRate.java | 1 - .../java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/io/yooksi/timelib/TickRate.java b/src/main/java/io/yooksi/timelib/TickRate.java index 9445d72..9c5a5d5 100644 --- a/src/main/java/io/yooksi/timelib/TickRate.java +++ b/src/main/java/io/yooksi/timelib/TickRate.java @@ -4,7 +4,6 @@ public class TickRate { public static final float DEFAULT_RATE = 20.0f; - public static boolean process_entities = true; private static float rate = DEFAULT_RATE; private static float mspt = (float)(1000.0 / rate); diff --git a/src/main/java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java b/src/main/java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java index e69bd3c..a642063 100644 --- a/src/main/java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java +++ b/src/main/java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java @@ -15,6 +15,6 @@ public class Timer_updateTimerMixin { target = "Lnet/minecraft/util/Timer;tickLength:F") ) private float updateTickSpeed(Timer timer) { - return Tick.process_entities ? Math.max(50.0f, Tick.getMspt()) : 50f; + return Math.max(50.0f, TickRate.getMspt()); } } From 68643350301758be6c4742b0c5ee1c6e226b4a68 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Sat, 2 May 2020 09:17:05 +0200 Subject: [PATCH 06/68] Refactor TickRate class --- src/main/java/io/yooksi/timelib/TickRate.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/java/io/yooksi/timelib/TickRate.java b/src/main/java/io/yooksi/timelib/TickRate.java index 9c5a5d5..0842f0f 100644 --- a/src/main/java/io/yooksi/timelib/TickRate.java +++ b/src/main/java/io/yooksi/timelib/TickRate.java @@ -2,12 +2,11 @@ public class TickRate { - public static final float DEFAULT_RATE = 20.0f; - private static float rate = DEFAULT_RATE; + private static float rate = DEFAULT; private static float mspt = (float)(1000.0 / rate); - public static float changeRate(float rate) { + public static float set(float rate) { TickRate.rate = rate; long mspt = (long) (1000.0 / TickRate.rate); @@ -18,11 +17,11 @@ public static float changeRate(float rate) { return TickRate.rate; } - public static float resetRate() { - return changeRate(DEFAULT_RATE); + public static float reset() { + return set(DEFAULT); } - public static float getRate() { + public static float get() { return rate; } From 137e24963c7bf1f71001181df6277611e50f8ef6 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Sat, 2 May 2020 09:17:38 +0200 Subject: [PATCH 07/68] Add TickRate pre-set values --- src/main/java/io/yooksi/timelib/TickRate.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/io/yooksi/timelib/TickRate.java b/src/main/java/io/yooksi/timelib/TickRate.java index 0842f0f..cbd05c5 100644 --- a/src/main/java/io/yooksi/timelib/TickRate.java +++ b/src/main/java/io/yooksi/timelib/TickRate.java @@ -2,6 +2,9 @@ public class TickRate { + public static final float SLOW = 10.0f; + public static final float DEFAULT = 20.0f; + public static final float FAST = 30.0f; private static float rate = DEFAULT; private static float mspt = (float)(1000.0 / rate); From c1554ffd3082f9980a686dcb876defc5b4dfd1aa Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Sat, 2 May 2020 09:18:38 +0200 Subject: [PATCH 08/68] Refactor and improve TickRateCommand --- .../timelib/command/TickRateCommand.java | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/main/java/io/yooksi/timelib/command/TickRateCommand.java b/src/main/java/io/yooksi/timelib/command/TickRateCommand.java index 6c7dd69..3020d9e 100644 --- a/src/main/java/io/yooksi/timelib/command/TickRateCommand.java +++ b/src/main/java/io/yooksi/timelib/command/TickRateCommand.java @@ -3,6 +3,7 @@ import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.FloatArgumentType; +import com.mojang.brigadier.context.CommandContext; import io.yooksi.timelib.TickRate; import net.minecraft.command.CommandSource; import net.minecraft.command.Commands; @@ -16,17 +17,23 @@ public class TickRateCommand { public static void register(CommandDispatcher dispatcher) { - dispatcher.register(Commands.literal("t").executes((c) -> setTickRate(c.getSource())) - .then(Commands.argument("rate", FloatArgumentType.floatArg(0.1f, 20.0f)) - .executes((c) -> setTickRate(c.getSource(), c.getArgument("rate", Float.class))))); + dispatcher.register(Commands.literal("tickrate").then(Commands.literal( + "set").then(Commands.argument("value", FloatArgumentType.floatArg(0.1f, 20.0f)) + .executes((c) -> setTickRate(c, c.getArgument("value", Float.class)))) + .then(Commands.literal("slow").executes((c) -> setTickRate(c, TickRate.SLOW))) + .then(Commands.literal("normal").executes((c) -> setTickRate(c, TickRate.DEFAULT))) + .then(Commands.literal("fast").executes((c) -> setTickRate(c, TickRate.FAST))) + .then(Commands.literal("reset").executes((c) -> setTickRate(c, TickRate.DEFAULT))))); } /** Change tick rate to new value */ - private static int setTickRate(CommandSource source, float newRate) { + private static int setTickRate(CommandContext context, float newRate) { + + CommandSource source = context.getSource(); + final float currentRate = TickRate.get(); - final float currentRate = Tick.getRate(); if (newRate != currentRate) { sendFeedback(source, String.format(FEEDBACK_CHANGED, currentRate, newRate)); - return (int) Tick.changeRate(newRate); + return (int) TickRate.set(newRate); } else { sendFeedback(source, String.format(FEEDBACK_NOT_CHANGED, currentRate)); @@ -34,10 +41,10 @@ private static int setTickRate(CommandSource source, float newRate) { } } /** Reset tick rate to a default value */ - private static int setTickRate(CommandSource source) { + private static int setTickRate(CommandContext context) { - final float defaultRate = Tick.resetRate(); - sendFeedback(source, String.format(FEEDBACK_RESET, defaultRate)); + final float defaultRate = TickRate.reset(); + sendFeedback(context.getSource(), String.format(FEEDBACK_RESET, defaultRate)); return (int) defaultRate; } From 60b151f2e6c7cfc68f8e9f120d219ad6824f5984 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Sat, 2 May 2020 09:22:06 +0200 Subject: [PATCH 09/68] Move max tick rate in field --- src/main/java/io/yooksi/timelib/TickRate.java | 3 +++ src/main/java/io/yooksi/timelib/command/TickRateCommand.java | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/yooksi/timelib/TickRate.java b/src/main/java/io/yooksi/timelib/TickRate.java index cbd05c5..f068b84 100644 --- a/src/main/java/io/yooksi/timelib/TickRate.java +++ b/src/main/java/io/yooksi/timelib/TickRate.java @@ -2,6 +2,9 @@ public class TickRate { + // Hardcoded limit so users don't go crazy with values + public static final float MAXIMUM = 20.0f; + public static final float SLOW = 10.0f; public static final float DEFAULT = 20.0f; public static final float FAST = 30.0f; diff --git a/src/main/java/io/yooksi/timelib/command/TickRateCommand.java b/src/main/java/io/yooksi/timelib/command/TickRateCommand.java index 3020d9e..41f65f9 100644 --- a/src/main/java/io/yooksi/timelib/command/TickRateCommand.java +++ b/src/main/java/io/yooksi/timelib/command/TickRateCommand.java @@ -17,8 +17,8 @@ public class TickRateCommand { public static void register(CommandDispatcher dispatcher) { - dispatcher.register(Commands.literal("tickrate").then(Commands.literal( - "set").then(Commands.argument("value", FloatArgumentType.floatArg(0.1f, 20.0f)) + dispatcher.register(Commands.literal("tickrate").then(Commands.literal("set") + .then(Commands.argument("value", FloatArgumentType.floatArg(0.1f, TickRate.MAXIMUM)) .executes((c) -> setTickRate(c, c.getArgument("value", Float.class)))) .then(Commands.literal("slow").executes((c) -> setTickRate(c, TickRate.SLOW))) .then(Commands.literal("normal").executes((c) -> setTickRate(c, TickRate.DEFAULT))) From 3c9b254b95683c77734d95ef22296afa9646d5ab Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Sat, 2 May 2020 09:22:24 +0200 Subject: [PATCH 10/68] Increase max tick rate to 500 --- src/main/java/io/yooksi/timelib/TickRate.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/yooksi/timelib/TickRate.java b/src/main/java/io/yooksi/timelib/TickRate.java index f068b84..ef23325 100644 --- a/src/main/java/io/yooksi/timelib/TickRate.java +++ b/src/main/java/io/yooksi/timelib/TickRate.java @@ -3,7 +3,7 @@ public class TickRate { // Hardcoded limit so users don't go crazy with values - public static final float MAXIMUM = 20.0f; + public static final float MAXIMUM = 500.0f; public static final float SLOW = 10.0f; public static final float DEFAULT = 20.0f; From 649736cb007b08edcb49c8fc35bc8978bcce7931 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Sat, 2 May 2020 09:31:02 +0200 Subject: [PATCH 11/68] Create onAdvanceTime mixin --- .../timelib/mixin/World_advanceTimeMixin.java | 32 +++++++++++++++++++ src/main/resources/timelib.mixins.json | 1 + 2 files changed, 33 insertions(+) create mode 100644 src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java diff --git a/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java b/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java new file mode 100644 index 0000000..99822a9 --- /dev/null +++ b/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java @@ -0,0 +1,32 @@ +package io.yooksi.timelib.mixin; + +import net.minecraft.world.World; +import net.minecraft.world.storage.WorldInfo; +import net.minecraftforge.common.capabilities.CapabilityProvider; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(World.class) +public abstract class World_advanceTimeMixin extends CapabilityProvider { + + protected World_advanceTimeMixin(Class baseClass) { + super(baseClass); + } + + @Shadow protected WorldInfo worldInfo; + + @Shadow public abstract void setDayTime(long time); + + @Inject(method = "advanceTime", at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/World;setDayTime(J)V"), + cancellable = true + ) + private void onAdvanceTime(CallbackInfo ci) { + + this.setDayTime(this.worldInfo.getDayTime() + 1L); + ci.cancel(); + } +} diff --git a/src/main/resources/timelib.mixins.json b/src/main/resources/timelib.mixins.json index 2891b5e..c0d93e9 100644 --- a/src/main/resources/timelib.mixins.json +++ b/src/main/resources/timelib.mixins.json @@ -4,6 +4,7 @@ "compatibilityLevel": "JAVA_8", "refmap": "main.refmap.json", "mixins": [ + "World_advanceTimeMixin", "MinecraftServer_runMixin", "CommandsMixin" ], From 77f9d0d68d8f4c93559eb9b7a1044b5ce4fcec5e Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Sat, 2 May 2020 10:21:00 +0200 Subject: [PATCH 12/68] Create command helper class --- .../java/io/yooksi/timelib/command/CmdHelper.java | 14 ++++++++++++++ .../io/yooksi/timelib/command/TickRateCommand.java | 12 ++++-------- 2 files changed, 18 insertions(+), 8 deletions(-) create mode 100644 src/main/java/io/yooksi/timelib/command/CmdHelper.java diff --git a/src/main/java/io/yooksi/timelib/command/CmdHelper.java b/src/main/java/io/yooksi/timelib/command/CmdHelper.java new file mode 100644 index 0000000..5cf036a --- /dev/null +++ b/src/main/java/io/yooksi/timelib/command/CmdHelper.java @@ -0,0 +1,14 @@ +package io.yooksi.timelib.command; + +import net.minecraft.command.CommandSource; +import net.minecraft.util.text.StringTextComponent; + +public class CmdHelper { + + /** + * Send chat message to player using given {@code CommandSource}. + */ + static void sendFeedback(CommandSource source, String message) { + source.sendFeedback(new StringTextComponent(message), true); + } +} diff --git a/src/main/java/io/yooksi/timelib/command/TickRateCommand.java b/src/main/java/io/yooksi/timelib/command/TickRateCommand.java index 41f65f9..deb2510 100644 --- a/src/main/java/io/yooksi/timelib/command/TickRateCommand.java +++ b/src/main/java/io/yooksi/timelib/command/TickRateCommand.java @@ -7,7 +7,6 @@ import io.yooksi.timelib.TickRate; import net.minecraft.command.CommandSource; import net.minecraft.command.Commands; -import net.minecraft.util.text.StringTextComponent; public class TickRateCommand { @@ -32,11 +31,11 @@ private static int setTickRate(CommandContext context, float newR final float currentRate = TickRate.get(); if (newRate != currentRate) { - sendFeedback(source, String.format(FEEDBACK_CHANGED, currentRate, newRate)); + CmdHelper.sendFeedback(source, String.format(FEEDBACK_CHANGED, currentRate, newRate)); return (int) TickRate.set(newRate); } else { - sendFeedback(source, String.format(FEEDBACK_NOT_CHANGED, currentRate)); + CmdHelper.sendFeedback(source, String.format(FEEDBACK_NOT_CHANGED, currentRate)); return (int) currentRate; } } @@ -44,12 +43,9 @@ private static int setTickRate(CommandContext context, float newR private static int setTickRate(CommandContext context) { final float defaultRate = TickRate.reset(); - sendFeedback(context.getSource(), String.format(FEEDBACK_RESET, defaultRate)); + CmdHelper.sendFeedback(context.getSource(), String.format(FEEDBACK_RESET, defaultRate)); return (int) defaultRate; } - /** Send chat message to player */ - private static void sendFeedback(CommandSource source, String message) { - source.sendFeedback(new StringTextComponent(message), true); - } + } From d9be3436928aa9d13ec7817b5822dc56142254bc Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Sat, 2 May 2020 10:30:07 +0200 Subject: [PATCH 13/68] Do class code refactoring --- .../timelib/command/TickRateCommand.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/main/java/io/yooksi/timelib/command/TickRateCommand.java b/src/main/java/io/yooksi/timelib/command/TickRateCommand.java index deb2510..f82ab67 100644 --- a/src/main/java/io/yooksi/timelib/command/TickRateCommand.java +++ b/src/main/java/io/yooksi/timelib/command/TickRateCommand.java @@ -17,14 +17,18 @@ public class TickRateCommand { public static void register(CommandDispatcher dispatcher) { dispatcher.register(Commands.literal("tickrate").then(Commands.literal("set") - .then(Commands.argument("value", FloatArgumentType.floatArg(0.1f, TickRate.MAXIMUM)) - .executes((c) -> setTickRate(c, c.getArgument("value", Float.class)))) + .then(Commands.argument("value", + FloatArgumentType.floatArg(0.1f, TickRate.MAXIMUM)) + .executes((c) -> setTickRate(c, c.getArgument("value", Float.class)))) .then(Commands.literal("slow").executes((c) -> setTickRate(c, TickRate.SLOW))) .then(Commands.literal("normal").executes((c) -> setTickRate(c, TickRate.DEFAULT))) - .then(Commands.literal("fast").executes((c) -> setTickRate(c, TickRate.FAST))) - .then(Commands.literal("reset").executes((c) -> setTickRate(c, TickRate.DEFAULT))))); + .then(Commands.literal("fast").executes((c) -> setTickRate(c, TickRate.FAST)))) + .then(Commands.literal("reset").executes(TickRateCommand::setTickRate))); } - /** Change tick rate to new value */ + + /** + * Change tick rate to new value + */ private static int setTickRate(CommandContext context, float newRate) { CommandSource source = context.getSource(); @@ -39,13 +43,14 @@ private static int setTickRate(CommandContext context, float newR return (int) currentRate; } } - /** Reset tick rate to a default value */ + + /** + * Reset tick rate to default value + */ private static int setTickRate(CommandContext context) { final float defaultRate = TickRate.reset(); CmdHelper.sendFeedback(context.getSource(), String.format(FEEDBACK_RESET, defaultRate)); return (int) defaultRate; - } - } From c8e54eebf4023821d9a343a6ef8c6e54449a5ef7 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Sat, 2 May 2020 14:49:15 +0200 Subject: [PATCH 14/68] Implement time cycle mechanic --- .../java/io/yooksi/timelib/TimeCycle.java | 26 +++++++++++++++++++ .../timelib/mixin/World_advanceTimeMixin.java | 17 ++++++++++-- 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 src/main/java/io/yooksi/timelib/TimeCycle.java diff --git a/src/main/java/io/yooksi/timelib/TimeCycle.java b/src/main/java/io/yooksi/timelib/TimeCycle.java new file mode 100644 index 0000000..f2b2ec7 --- /dev/null +++ b/src/main/java/io/yooksi/timelib/TimeCycle.java @@ -0,0 +1,26 @@ +package io.yooksi.timelib; + +public class TimeCycle { + + public static final long MAX_SPEED = 100; + + public static final long SLOW_SPEED = -1; + public static final long DEFAULT_SPEED = 1; + public static final long FAST_SPEED = 2; + + private static long speed = DEFAULT_SPEED; + + public static long lastGameTime; + + public static long resetSpeed() { + return setSpeed(DEFAULT_SPEED); + } + + public static long setSpeed(long value) { + return speed = value; + } + + public static long getSpeed() { + return speed; + } +} diff --git a/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java b/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java index 99822a9..ccda751 100644 --- a/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java +++ b/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java @@ -1,5 +1,6 @@ package io.yooksi.timelib.mixin; +import io.yooksi.timelib.TimeCycle; import net.minecraft.world.World; import net.minecraft.world.storage.WorldInfo; import net.minecraftforge.common.capabilities.CapabilityProvider; @@ -26,7 +27,19 @@ protected World_advanceTimeMixin(Class baseClass) { ) private void onAdvanceTime(CallbackInfo ci) { - this.setDayTime(this.worldInfo.getDayTime() + 1L); - ci.cancel(); + final long cycleSpeed = TimeCycle.getSpeed(); + if (cycleSpeed < 0) + { + long currentGameTime = worldInfo.getGameTime(); + if (TimeCycle.lastGameTime + Math.abs(cycleSpeed) < currentGameTime) + { + this.setDayTime(this.worldInfo.getDayTime() + TimeCycle.DEFAULT_SPEED); + TimeCycle.lastGameTime = worldInfo.getGameTime(); + } + } + else if (cycleSpeed > 0) { + this.setDayTime(this.worldInfo.getDayTime() + cycleSpeed); + } + ci.cancel(); } } From 38e50137c50c981378bac9dab69bb29e2604c2b1 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Sat, 2 May 2020 14:49:30 +0200 Subject: [PATCH 15/68] Implement time cycle command --- .../timelib/command/TimeCycleCommand.java | 55 +++++++++++++++++++ .../yooksi/timelib/mixin/CommandsMixin.java | 3 + 2 files changed, 58 insertions(+) create mode 100644 src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java diff --git a/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java b/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java new file mode 100644 index 0000000..5ab6179 --- /dev/null +++ b/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java @@ -0,0 +1,55 @@ +package io.yooksi.timelib.command; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.LongArgumentType; +import com.mojang.brigadier.context.CommandContext; +import io.yooksi.timelib.TimeCycle; +import net.minecraft.command.CommandSource; +import net.minecraft.command.Commands; + +public class TimeCycleCommand { + + private static final String FEEDBACK_CHANGED_SPEED = "Day/night cycle speed changed to %d"; + private static final String FEEDBACK_NOT_CHANGED_SPEED = "Day/night cycle speed is already %d"; + private static final String FEEDBACK_RESET = "Day/night cycle speed was reset to %d"; + + public static void register(CommandDispatcher dispatcher) { + + dispatcher.register(Commands.literal("timecycle") + .then(Commands.literal("speed").then(Commands.argument("value", + LongArgumentType.longArg(-100, TimeCycle.MAX_SPEED)) + .executes((c) -> setTimeCycle(c, c.getArgument("value", Long.class)))) + .then(Commands.literal("slow").executes((c) -> setTimeCycle(c, TimeCycle.SLOW_SPEED))) + .then(Commands.literal("normal").executes((c) -> setTimeCycle(c, TimeCycle.DEFAULT_SPEED))) + .then(Commands.literal("fast").executes((c) -> setTimeCycle(c, TimeCycle.FAST_SPEED))) + .then(Commands.literal("reset").executes((c) -> setTimeCycle(c, TimeCycle.DEFAULT_SPEED))))); + } + + /** + * Change time cycle speed to new value + */ + private static int setTimeCycle(CommandContext context, long newSpeed) { + + CommandSource source = context.getSource(); + final long currentSpeed = TimeCycle.getSpeed(); + + if (newSpeed != currentSpeed) { + CmdHelper.sendFeedback(source, String.format(FEEDBACK_CHANGED_SPEED, newSpeed)); + return (int) TimeCycle.setSpeed(newSpeed); + } + else { + CmdHelper.sendFeedback(source, String.format(FEEDBACK_NOT_CHANGED_SPEED, currentSpeed)); + return (int) currentSpeed; + } + } + + /** + * Reset time cycle speed to default value + */ + private static int setTimeCycle(CommandContext context) { + + final long defaultSpeed = TimeCycle.resetSpeed(); + CmdHelper.sendFeedback(context.getSource(), String.format(FEEDBACK_RESET, defaultSpeed)); + return (int) defaultSpeed; + } +} diff --git a/src/main/java/io/yooksi/timelib/mixin/CommandsMixin.java b/src/main/java/io/yooksi/timelib/mixin/CommandsMixin.java index 90d4d62..d4fff8e 100644 --- a/src/main/java/io/yooksi/timelib/mixin/CommandsMixin.java +++ b/src/main/java/io/yooksi/timelib/mixin/CommandsMixin.java @@ -1,5 +1,6 @@ package io.yooksi.timelib.mixin; +import io.yooksi.timelib.command.TimeCycleCommand; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -21,6 +22,8 @@ public class CommandsMixin { @Inject(method = "", at = @At("RETURN")) private void onRegister(boolean boolean_1, CallbackInfo ci) { + TickRateCommand.register(dispatcher); + TimeCycleCommand.register(dispatcher); } } From 4ddd4c12a43503958709cc300e66997eea18da50 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Sat, 2 May 2020 17:18:45 +0200 Subject: [PATCH 16/68] Remove MixinBootstrap dependency Apparently it is not needed for building the jar. --- build.gradle | 5 ----- 1 file changed, 5 deletions(-) diff --git a/build.gradle b/build.gradle index cbc9687..9a3cd10 100644 --- a/build.gradle +++ b/build.gradle @@ -26,10 +26,6 @@ sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility repositories { mavenCentral() maven { url 'https://repo.spongepowered.org/maven' } - maven { - name "lxgaming" - url "https://dl.bintray.com/lxgaming/maven" - } maven { url 'https://jitpack.io' } } @@ -76,7 +72,6 @@ minecraft { dependencies { minecraft "net.minecraftforge:forge:${minecraftVersion}-${forgeVersion}" compile "org.spongepowered:mixin:0.8.1-SNAPSHOT" - implementation "com.github.LXGaming:MixinBootstrap:v${mixinBootstrapVer}" } // Get properties into the manifest for reading by the runtime.. From a0b3306cdb657fc84026516ff09bec5bfca70bea Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Sat, 2 May 2020 17:19:24 +0200 Subject: [PATCH 17/68] Fix mixin refmap definition Mixin folks say this is the correct way to do it. --- build.gradle | 4 ++-- src/main/resources/timelib.mixins.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 9a3cd10..d136bc8 100644 --- a/build.gradle +++ b/build.gradle @@ -29,8 +29,8 @@ repositories { maven { url 'https://jitpack.io' } } -sourceSets { - main { ext.refMap = "main.refmap.json" } +mixin { + add sourceSets.main, "mixins.${modId}.refmap.json" } minecraft { diff --git a/src/main/resources/timelib.mixins.json b/src/main/resources/timelib.mixins.json index c0d93e9..ae90e1d 100644 --- a/src/main/resources/timelib.mixins.json +++ b/src/main/resources/timelib.mixins.json @@ -2,7 +2,7 @@ "required": true, "package": "io.yooksi.timelib.mixin", "compatibilityLevel": "JAVA_8", - "refmap": "main.refmap.json", + "refmap": "mixins.timelib.refmap.json", "mixins": [ "World_advanceTimeMixin", "MinecraftServer_runMixin", From ca862c63d44dd742b997d39ae3a27d964810af60 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Sat, 2 May 2020 17:19:42 +0200 Subject: [PATCH 18/68] Add missing mixin manifest attribute --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index d136bc8..199db8d 100644 --- a/build.gradle +++ b/build.gradle @@ -85,6 +85,7 @@ jar { "Implementation-Version": "${version}", "Implementation-Vendor": "${groupName}", "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"), + "MixinConfigs": "${modId}.mixins.json" ]) } } From 26295277100ab0dae59cb1cd7fc9d72a83410a6d Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Sun, 3 May 2020 20:49:44 +0200 Subject: [PATCH 19/68] Move tick/cycle fields to common package --- .../java/io/yooksi/timelib/TickProfile.java | 12 ++++++++ .../java/io/yooksi/timelib/TimeProfile.java | 15 ++++++++++ src/main/java/io/yooksi/timelib/TickRate.java | 8 ++---- .../java/io/yooksi/timelib/TimeCycle.java | 11 ++------ .../timelib/command/TickRateCommand.java | 7 +++-- .../timelib/command/TimeCycleCommand.java | 28 +++++++++++++------ .../timelib/mixin/World_advanceTimeMixin.java | 3 +- 7 files changed, 57 insertions(+), 27 deletions(-) create mode 100644 src/common/java/io/yooksi/timelib/TickProfile.java create mode 100644 src/common/java/io/yooksi/timelib/TimeProfile.java diff --git a/src/common/java/io/yooksi/timelib/TickProfile.java b/src/common/java/io/yooksi/timelib/TickProfile.java new file mode 100644 index 0000000..2589be7 --- /dev/null +++ b/src/common/java/io/yooksi/timelib/TickProfile.java @@ -0,0 +1,12 @@ +package io.yooksi.timelib; + +public enum TickProfile { + + SLOW(10.0f), DEFAULT(20.0f), FAST(30.0f); + + public final float rate; + + TickProfile(float value) { + this.rate = value; + } +} diff --git a/src/common/java/io/yooksi/timelib/TimeProfile.java b/src/common/java/io/yooksi/timelib/TimeProfile.java new file mode 100644 index 0000000..c38fe87 --- /dev/null +++ b/src/common/java/io/yooksi/timelib/TimeProfile.java @@ -0,0 +1,15 @@ +package io.yooksi.timelib; + +public enum TimeProfile { + + INERT(0), + SLOW_SPEED(-1), + DEFAULT_SPEED(1), + FAST_SPEED(2); + + public final long value; + + TimeProfile(long value) { + this.value = value; + } +} diff --git a/src/main/java/io/yooksi/timelib/TickRate.java b/src/main/java/io/yooksi/timelib/TickRate.java index ef23325..bbd73ba 100644 --- a/src/main/java/io/yooksi/timelib/TickRate.java +++ b/src/main/java/io/yooksi/timelib/TickRate.java @@ -5,11 +5,7 @@ public class TickRate { // Hardcoded limit so users don't go crazy with values public static final float MAXIMUM = 500.0f; - public static final float SLOW = 10.0f; - public static final float DEFAULT = 20.0f; - public static final float FAST = 30.0f; - - private static float rate = DEFAULT; + private static float rate = TickProfile.DEFAULT.rate; private static float mspt = (float)(1000.0 / rate); public static float set(float rate) { @@ -24,7 +20,7 @@ public static float set(float rate) { } public static float reset() { - return set(DEFAULT); + return set(TickProfile.DEFAULT.rate); } public static float get() { diff --git a/src/main/java/io/yooksi/timelib/TimeCycle.java b/src/main/java/io/yooksi/timelib/TimeCycle.java index f2b2ec7..6f0b6b3 100644 --- a/src/main/java/io/yooksi/timelib/TimeCycle.java +++ b/src/main/java/io/yooksi/timelib/TimeCycle.java @@ -2,18 +2,11 @@ public class TimeCycle { - public static final long MAX_SPEED = 100; - - public static final long SLOW_SPEED = -1; - public static final long DEFAULT_SPEED = 1; - public static final long FAST_SPEED = 2; - - private static long speed = DEFAULT_SPEED; - + private static long speed = TimeProfile.DEFAULT_SPEED.value; public static long lastGameTime; public static long resetSpeed() { - return setSpeed(DEFAULT_SPEED); + return setSpeed(TimeProfile.DEFAULT_SPEED.value); } public static long setSpeed(long value) { diff --git a/src/main/java/io/yooksi/timelib/command/TickRateCommand.java b/src/main/java/io/yooksi/timelib/command/TickRateCommand.java index f82ab67..041013e 100644 --- a/src/main/java/io/yooksi/timelib/command/TickRateCommand.java +++ b/src/main/java/io/yooksi/timelib/command/TickRateCommand.java @@ -4,6 +4,7 @@ import com.mojang.brigadier.arguments.FloatArgumentType; import com.mojang.brigadier.context.CommandContext; +import io.yooksi.timelib.TickProfile; import io.yooksi.timelib.TickRate; import net.minecraft.command.CommandSource; import net.minecraft.command.Commands; @@ -20,9 +21,9 @@ public static void register(CommandDispatcher dispatcher) { .then(Commands.argument("value", FloatArgumentType.floatArg(0.1f, TickRate.MAXIMUM)) .executes((c) -> setTickRate(c, c.getArgument("value", Float.class)))) - .then(Commands.literal("slow").executes((c) -> setTickRate(c, TickRate.SLOW))) - .then(Commands.literal("normal").executes((c) -> setTickRate(c, TickRate.DEFAULT))) - .then(Commands.literal("fast").executes((c) -> setTickRate(c, TickRate.FAST)))) + .then(Commands.literal("slow").executes((c) -> setTickRate(c, TickProfile.SLOW.rate))) + .then(Commands.literal("normal").executes((c) -> setTickRate(c, TickProfile.DEFAULT.rate))) + .then(Commands.literal("fast").executes((c) -> setTickRate(c, TickProfile.FAST.rate)))) .then(Commands.literal("reset").executes(TickRateCommand::setTickRate))); } diff --git a/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java b/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java index 5ab6179..2090486 100644 --- a/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java +++ b/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java @@ -4,6 +4,7 @@ import com.mojang.brigadier.arguments.LongArgumentType; import com.mojang.brigadier.context.CommandContext; import io.yooksi.timelib.TimeCycle; +import io.yooksi.timelib.TimeProfile; import net.minecraft.command.CommandSource; import net.minecraft.command.Commands; @@ -17,20 +18,24 @@ public static void register(CommandDispatcher dispatcher) { dispatcher.register(Commands.literal("timecycle") .then(Commands.literal("speed").then(Commands.argument("value", - LongArgumentType.longArg(-100, TimeCycle.MAX_SPEED)) - .executes((c) -> setTimeCycle(c, c.getArgument("value", Long.class)))) - .then(Commands.literal("slow").executes((c) -> setTimeCycle(c, TimeCycle.SLOW_SPEED))) - .then(Commands.literal("normal").executes((c) -> setTimeCycle(c, TimeCycle.DEFAULT_SPEED))) - .then(Commands.literal("fast").executes((c) -> setTimeCycle(c, TimeCycle.FAST_SPEED))) - .then(Commands.literal("reset").executes((c) -> setTimeCycle(c, TimeCycle.DEFAULT_SPEED))))); + LongArgumentType.longArg(-TimeCycle.MAX_SPEED, TimeCycle.MAX_SPEED)) + .executes((c) -> setTimeCycle(c.getSource(), + c.getArgument("value", Long.class)))) + .then(Commands.literal("slow").executes((c) -> + setTimeCycle(c, TimeProfile.SLOW_SPEED))) + .then(Commands.literal("normal").executes((c) -> + setTimeCycle(c, TimeProfile.DEFAULT_SPEED))) + .then(Commands.literal("fast").executes((c) -> + setTimeCycle(c, TimeProfile.FAST_SPEED))) + .then(Commands.literal("reset").executes((c) -> + setTimeCycle(c, TimeProfile.DEFAULT_SPEED))))); } /** * Change time cycle speed to new value */ - private static int setTimeCycle(CommandContext context, long newSpeed) { + private static int setTimeCycle(CommandSource source, long newSpeed) { - CommandSource source = context.getSource(); final long currentSpeed = TimeCycle.getSpeed(); if (newSpeed != currentSpeed) { @@ -43,6 +48,13 @@ private static int setTimeCycle(CommandContext context, long newS } } + /** + * Change time cycle speed to new value + */ + private static int setTimeCycle(CommandContext context, TimeProfile profile) { + return setTimeCycle(context.getSource(), profile.value); + } + /** * Reset time cycle speed to default value */ diff --git a/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java b/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java index ccda751..a1efb83 100644 --- a/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java +++ b/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java @@ -1,6 +1,7 @@ package io.yooksi.timelib.mixin; import io.yooksi.timelib.TimeCycle; +import io.yooksi.timelib.TimeProfile; import net.minecraft.world.World; import net.minecraft.world.storage.WorldInfo; import net.minecraftforge.common.capabilities.CapabilityProvider; @@ -33,7 +34,7 @@ private void onAdvanceTime(CallbackInfo ci) { long currentGameTime = worldInfo.getGameTime(); if (TimeCycle.lastGameTime + Math.abs(cycleSpeed) < currentGameTime) { - this.setDayTime(this.worldInfo.getDayTime() + TimeCycle.DEFAULT_SPEED); + this.setDayTime(this.worldInfo.getDayTime() + TimeProfile.DEFAULT_SPEED.value); TimeCycle.lastGameTime = worldInfo.getGameTime(); } } From 183a4d34bc5f4b3af9bdfcc0da52f2a0313d6057 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Sun, 3 May 2020 21:00:46 +0200 Subject: [PATCH 20/68] Write TimeCycle javadoc --- .../java/io/yooksi/timelib/TimeCycle.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/main/java/io/yooksi/timelib/TimeCycle.java b/src/main/java/io/yooksi/timelib/TimeCycle.java index 6f0b6b3..69718dc 100644 --- a/src/main/java/io/yooksi/timelib/TimeCycle.java +++ b/src/main/java/io/yooksi/timelib/TimeCycle.java @@ -2,9 +2,37 @@ public class TimeCycle { + /** + * The maximum speed of the day/night cycle. + * + * This value also represents the maximum proportional length of days to vanilla. + * For example if we wanted the limit the days to be maximally {@code 3} times longer + * or shorter we would set this value to be {@code 3}. + */ + public static final long MAX_SPEED = 72; + + /** + * The speed of day/night cycle representing the proportional length of days to vanilla. + *
    + *
  • Positive values speed up the cycle.
  • + *
  • Negative values slow down the cycle.
  • + *
  • Value of {@code 0} disables the cycle.
  • + *
+ * For example, setting this value to {@code 3} would make days {@code 3} times longer, + * while setting it a value of {@code -3} would make them {@code 3} times shorter. + */ private static long speed = TimeProfile.DEFAULT_SPEED.value; + + /** + * Game time of last cycle update in {@code World#advanceTime()}.
+ * This should be the last recorded time of updating {@code dayTime}. + */ public static long lastGameTime; + /** + * Sets the time cycle speed to it's default value + * @return the value of {@link TimeProfile#DEFAULT_SPEED} + */ public static long resetSpeed() { return setSpeed(TimeProfile.DEFAULT_SPEED.value); } From 8eba3c9b02988c4d9c200a22365ffd67bf4c6899 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Sun, 3 May 2020 21:01:33 +0200 Subject: [PATCH 21/68] Define project sourceSets --- build.gradle | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/build.gradle b/build.gradle index 199db8d..7ff8637 100644 --- a/build.gradle +++ b/build.gradle @@ -23,6 +23,24 @@ archivesBaseName = project.modId compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility +sourceSets { + common { + java { srcDir 'src/common/java'} + } + api { + java { + compileClasspath += main.output + common.output + runtimeClasspath += main.output + common.output + } + } + main { + java { + compileClasspath += common.output + runtimeClasspath += common.output + } + } +} + repositories { mavenCentral() maven { url 'https://repo.spongepowered.org/maven' } From 06b0c66242bb1b4e2be0722032003746664d4aee Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Mon, 4 May 2020 00:53:27 +0200 Subject: [PATCH 22/68] Move define classes to api --- .../main/java/io/yooksi/timelib/define}/TickProfile.java | 6 ++++-- .../main/java/io/yooksi/timelib/define}/TimeProfile.java | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) rename {src/common/java/io/yooksi/timelib => api/src/main/java/io/yooksi/timelib/define}/TickProfile.java (58%) rename {src/common/java/io/yooksi/timelib => api/src/main/java/io/yooksi/timelib/define}/TimeProfile.java (83%) diff --git a/src/common/java/io/yooksi/timelib/TickProfile.java b/api/src/main/java/io/yooksi/timelib/define/TickProfile.java similarity index 58% rename from src/common/java/io/yooksi/timelib/TickProfile.java rename to api/src/main/java/io/yooksi/timelib/define/TickProfile.java index 2589be7..658e615 100644 --- a/src/common/java/io/yooksi/timelib/TickProfile.java +++ b/api/src/main/java/io/yooksi/timelib/define/TickProfile.java @@ -1,8 +1,10 @@ -package io.yooksi.timelib; +package io.yooksi.timelib.define; public enum TickProfile { - SLOW(10.0f), DEFAULT(20.0f), FAST(30.0f); + SLOW(10.0f), + DEFAULT(20.0f), + FAST(30.0f); public final float rate; diff --git a/src/common/java/io/yooksi/timelib/TimeProfile.java b/api/src/main/java/io/yooksi/timelib/define/TimeProfile.java similarity index 83% rename from src/common/java/io/yooksi/timelib/TimeProfile.java rename to api/src/main/java/io/yooksi/timelib/define/TimeProfile.java index c38fe87..0183973 100644 --- a/src/common/java/io/yooksi/timelib/TimeProfile.java +++ b/api/src/main/java/io/yooksi/timelib/define/TimeProfile.java @@ -1,4 +1,4 @@ -package io.yooksi.timelib; +package io.yooksi.timelib.define; public enum TimeProfile { From 49492382c865e5a41e531fd2054587025b4ad8bd Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Mon, 4 May 2020 00:56:18 +0200 Subject: [PATCH 23/68] Update class imports --- src/main/java/io/yooksi/timelib/command/TickRateCommand.java | 2 +- src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java | 2 +- .../java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/yooksi/timelib/command/TickRateCommand.java b/src/main/java/io/yooksi/timelib/command/TickRateCommand.java index 041013e..64b6f32 100644 --- a/src/main/java/io/yooksi/timelib/command/TickRateCommand.java +++ b/src/main/java/io/yooksi/timelib/command/TickRateCommand.java @@ -4,8 +4,8 @@ import com.mojang.brigadier.arguments.FloatArgumentType; import com.mojang.brigadier.context.CommandContext; -import io.yooksi.timelib.TickProfile; import io.yooksi.timelib.TickRate; +import io.yooksi.timelib.define.TickProfile; import net.minecraft.command.CommandSource; import net.minecraft.command.Commands; diff --git a/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java b/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java index 2090486..4102621 100644 --- a/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java +++ b/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java @@ -4,7 +4,7 @@ import com.mojang.brigadier.arguments.LongArgumentType; import com.mojang.brigadier.context.CommandContext; import io.yooksi.timelib.TimeCycle; -import io.yooksi.timelib.TimeProfile; +import io.yooksi.timelib.define.TimeProfile; import net.minecraft.command.CommandSource; import net.minecraft.command.Commands; diff --git a/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java b/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java index a1efb83..4b91caf 100644 --- a/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java +++ b/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java @@ -1,7 +1,7 @@ package io.yooksi.timelib.mixin; import io.yooksi.timelib.TimeCycle; -import io.yooksi.timelib.TimeProfile; +import io.yooksi.timelib.define.TimeProfile; import net.minecraft.world.World; import net.minecraft.world.storage.WorldInfo; import net.minecraftforge.common.capabilities.CapabilityProvider; From df317fd2f790aaa7c3fed267c093ae439ad5f43d Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Mon, 4 May 2020 08:38:05 +0200 Subject: [PATCH 24/68] Move data classes to api --- {src => api/src}/main/java/io/yooksi/timelib/TickRate.java | 0 {src => api/src}/main/java/io/yooksi/timelib/TimeCycle.java | 0 src/main/java/io/yooksi/timelib/command/TickRateCommand.java | 2 +- src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java | 2 +- .../java/io/yooksi/timelib/mixin/MinecraftServer_runMixin.java | 2 +- .../java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java | 2 +- .../java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java | 2 +- 7 files changed, 5 insertions(+), 5 deletions(-) rename {src => api/src}/main/java/io/yooksi/timelib/TickRate.java (100%) rename {src => api/src}/main/java/io/yooksi/timelib/TimeCycle.java (100%) diff --git a/src/main/java/io/yooksi/timelib/TickRate.java b/api/src/main/java/io/yooksi/timelib/TickRate.java similarity index 100% rename from src/main/java/io/yooksi/timelib/TickRate.java rename to api/src/main/java/io/yooksi/timelib/TickRate.java diff --git a/src/main/java/io/yooksi/timelib/TimeCycle.java b/api/src/main/java/io/yooksi/timelib/TimeCycle.java similarity index 100% rename from src/main/java/io/yooksi/timelib/TimeCycle.java rename to api/src/main/java/io/yooksi/timelib/TimeCycle.java diff --git a/src/main/java/io/yooksi/timelib/command/TickRateCommand.java b/src/main/java/io/yooksi/timelib/command/TickRateCommand.java index 64b6f32..387b806 100644 --- a/src/main/java/io/yooksi/timelib/command/TickRateCommand.java +++ b/src/main/java/io/yooksi/timelib/command/TickRateCommand.java @@ -4,8 +4,8 @@ import com.mojang.brigadier.arguments.FloatArgumentType; import com.mojang.brigadier.context.CommandContext; -import io.yooksi.timelib.TickRate; import io.yooksi.timelib.define.TickProfile; +import TickRate; import net.minecraft.command.CommandSource; import net.minecraft.command.Commands; diff --git a/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java b/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java index 4102621..411be54 100644 --- a/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java +++ b/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java @@ -3,7 +3,7 @@ import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.LongArgumentType; import com.mojang.brigadier.context.CommandContext; -import io.yooksi.timelib.TimeCycle; +import TimeCycle; import io.yooksi.timelib.define.TimeProfile; import net.minecraft.command.CommandSource; import net.minecraft.command.Commands; diff --git a/src/main/java/io/yooksi/timelib/mixin/MinecraftServer_runMixin.java b/src/main/java/io/yooksi/timelib/mixin/MinecraftServer_runMixin.java index f05d6cc..00a8eab 100644 --- a/src/main/java/io/yooksi/timelib/mixin/MinecraftServer_runMixin.java +++ b/src/main/java/io/yooksi/timelib/mixin/MinecraftServer_runMixin.java @@ -10,7 +10,7 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import io.yooksi.timelib.TickRate; +import TickRate; import net.minecraft.profiler.DebugProfiler; import net.minecraft.server.MinecraftServer; import net.minecraft.util.Util; diff --git a/src/main/java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java b/src/main/java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java index a642063..7ad4cac 100644 --- a/src/main/java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java +++ b/src/main/java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java @@ -4,7 +4,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import io.yooksi.timelib.TickRate; +import TickRate; import net.minecraft.util.Timer; @SuppressWarnings("unused") diff --git a/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java b/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java index 4b91caf..96bf43d 100644 --- a/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java +++ b/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java @@ -1,6 +1,6 @@ package io.yooksi.timelib.mixin; -import io.yooksi.timelib.TimeCycle; +import TimeCycle; import io.yooksi.timelib.define.TimeProfile; import net.minecraft.world.World; import net.minecraft.world.storage.WorldInfo; From df8a45fac6f6950fef8a3ff607355276b47ddd65 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Mon, 4 May 2020 00:57:24 +0200 Subject: [PATCH 25/68] Fix missing class import --- api/src/main/java/io/yooksi/timelib/TimeCycle.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/src/main/java/io/yooksi/timelib/TimeCycle.java b/api/src/main/java/io/yooksi/timelib/TimeCycle.java index 69718dc..7783e0e 100644 --- a/api/src/main/java/io/yooksi/timelib/TimeCycle.java +++ b/api/src/main/java/io/yooksi/timelib/TimeCycle.java @@ -1,5 +1,7 @@ package io.yooksi.timelib; +import io.yooksi.timelib.define.TimeProfile; + public class TimeCycle { /** From 7e6c6e39e5e0d79bc712d5b7e9ca2597ef3db9cb Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Mon, 4 May 2020 00:58:49 +0200 Subject: [PATCH 26/68] Remove redundant sourceSets --- build.gradle | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/build.gradle b/build.gradle index 7ff8637..199db8d 100644 --- a/build.gradle +++ b/build.gradle @@ -23,24 +23,6 @@ archivesBaseName = project.modId compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility -sourceSets { - common { - java { srcDir 'src/common/java'} - } - api { - java { - compileClasspath += main.output + common.output - runtimeClasspath += main.output + common.output - } - } - main { - java { - compileClasspath += common.output - runtimeClasspath += common.output - } - } -} - repositories { mavenCentral() maven { url 'https://repo.spongepowered.org/maven' } From be8b046f9eebd3605bbd8840801c933312ea3e13 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Mon, 4 May 2020 00:59:34 +0200 Subject: [PATCH 27/68] Include API as gradle project --- settings.gradle | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index 4b7188b..a798524 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,4 @@ -rootProject.name = "TimeLib" \ No newline at end of file +rootProject.name = "TimeLib" + +include ":api" +project(':api').name = "${rootProject.name}-api" From ea1a0cb93c91c321c97ecc942d33b2d6ace325c7 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Mon, 4 May 2020 00:59:55 +0200 Subject: [PATCH 28/68] Add build.gradle for api --- api/build.gradle | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 api/build.gradle diff --git a/api/build.gradle b/api/build.gradle new file mode 100644 index 0000000..3682cd1 --- /dev/null +++ b/api/build.gradle @@ -0,0 +1,21 @@ +plugins { + id 'java-library' +} + +group rootProject.group +version rootProject.version + +repositories { + mavenCentral() +} + +dependencies { +} + +publishing { + publications { + maven(MavenPublication) { + artifactId = "${rootProject.name}-api" + } + } +} \ No newline at end of file From cbc153da1be3990233dc43a020c34583966c8ad5 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Mon, 4 May 2020 01:00:13 +0200 Subject: [PATCH 29/68] Add api project as dependency --- build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.gradle b/build.gradle index 199db8d..32aba86 100644 --- a/build.gradle +++ b/build.gradle @@ -14,6 +14,7 @@ apply plugin: 'net.minecraftforge.gradle' apply plugin: 'org.spongepowered.mixin' apply plugin: 'eclipse' apply plugin: 'maven-publish' +apply plugin: 'java-library' version = "${minecraftVersion}-${modVersion}" group = "io.${groupName}.${modId}" @@ -70,6 +71,9 @@ minecraft { } dependencies { + // Project API + api project("${rootProject.name}-api") + minecraft "net.minecraftforge:forge:${minecraftVersion}-${forgeVersion}" compile "org.spongepowered:mixin:0.8.1-SNAPSHOT" } From 8171ac2a786f3534a25f37633d69cd05e831b209 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Mon, 4 May 2020 02:19:59 +0200 Subject: [PATCH 30/68] Update class imports --- api/src/main/java/io/yooksi/timelib/TickRate.java | 2 ++ src/main/java/io/yooksi/timelib/command/TickRateCommand.java | 2 +- src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java | 2 +- .../java/io/yooksi/timelib/mixin/MinecraftServer_runMixin.java | 3 +-- .../java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java | 3 +-- .../java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/api/src/main/java/io/yooksi/timelib/TickRate.java b/api/src/main/java/io/yooksi/timelib/TickRate.java index bbd73ba..2edbbde 100644 --- a/api/src/main/java/io/yooksi/timelib/TickRate.java +++ b/api/src/main/java/io/yooksi/timelib/TickRate.java @@ -1,5 +1,7 @@ package io.yooksi.timelib; +import io.yooksi.timelib.define.TickProfile; + public class TickRate { // Hardcoded limit so users don't go crazy with values diff --git a/src/main/java/io/yooksi/timelib/command/TickRateCommand.java b/src/main/java/io/yooksi/timelib/command/TickRateCommand.java index 387b806..64b6f32 100644 --- a/src/main/java/io/yooksi/timelib/command/TickRateCommand.java +++ b/src/main/java/io/yooksi/timelib/command/TickRateCommand.java @@ -4,8 +4,8 @@ import com.mojang.brigadier.arguments.FloatArgumentType; import com.mojang.brigadier.context.CommandContext; +import io.yooksi.timelib.TickRate; import io.yooksi.timelib.define.TickProfile; -import TickRate; import net.minecraft.command.CommandSource; import net.minecraft.command.Commands; diff --git a/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java b/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java index 411be54..4102621 100644 --- a/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java +++ b/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java @@ -3,7 +3,7 @@ import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.LongArgumentType; import com.mojang.brigadier.context.CommandContext; -import TimeCycle; +import io.yooksi.timelib.TimeCycle; import io.yooksi.timelib.define.TimeProfile; import net.minecraft.command.CommandSource; import net.minecraft.command.Commands; diff --git a/src/main/java/io/yooksi/timelib/mixin/MinecraftServer_runMixin.java b/src/main/java/io/yooksi/timelib/mixin/MinecraftServer_runMixin.java index 00a8eab..adc3461 100644 --- a/src/main/java/io/yooksi/timelib/mixin/MinecraftServer_runMixin.java +++ b/src/main/java/io/yooksi/timelib/mixin/MinecraftServer_runMixin.java @@ -2,6 +2,7 @@ import java.util.function.BooleanSupplier; +import io.yooksi.timelib.TickRate; import org.apache.logging.log4j.Logger; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -9,8 +10,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import TickRate; import net.minecraft.profiler.DebugProfiler; import net.minecraft.server.MinecraftServer; import net.minecraft.util.Util; diff --git a/src/main/java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java b/src/main/java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java index 7ad4cac..0ac45f3 100644 --- a/src/main/java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java +++ b/src/main/java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java @@ -1,10 +1,9 @@ package io.yooksi.timelib.mixin; +import io.yooksi.timelib.TickRate; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; - -import TickRate; import net.minecraft.util.Timer; @SuppressWarnings("unused") diff --git a/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java b/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java index 96bf43d..4b91caf 100644 --- a/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java +++ b/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java @@ -1,6 +1,6 @@ package io.yooksi.timelib.mixin; -import TimeCycle; +import io.yooksi.timelib.TimeCycle; import io.yooksi.timelib.define.TimeProfile; import net.minecraft.world.World; import net.minecraft.world.storage.WorldInfo; From 362608e5e72ed3a6ef87af6b8d7f6b71e799f59f Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Mon, 4 May 2020 01:44:19 +0200 Subject: [PATCH 31/68] Share plugins and dependencies --- api/build.gradle | 6 ++---- build.gradle | 15 ++++++++++----- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/api/build.gradle b/api/build.gradle index 3682cd1..9a82469 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -1,6 +1,3 @@ -plugins { - id 'java-library' -} group rootProject.group version rootProject.version @@ -9,7 +6,8 @@ repositories { mavenCentral() } -dependencies { +minecraft { + mappings channel: 'snapshot', version: "${mappingBuild}-${mappingMCVersion}" } publishing { diff --git a/build.gradle b/build.gradle index 32aba86..79e1400 100644 --- a/build.gradle +++ b/build.gradle @@ -10,11 +10,17 @@ buildscript { classpath 'org.spongepowered:mixingradle:0.7-SNAPSHOT' } } -apply plugin: 'net.minecraftforge.gradle' +allprojects { + apply plugin: 'net.minecraftforge.gradle' + apply plugin: 'eclipse' + apply plugin: 'maven-publish' + apply plugin: 'java-library' + + dependencies { + minecraft "net.minecraftforge:forge:${minecraftVersion}-${forgeVersion}" + } +} apply plugin: 'org.spongepowered.mixin' -apply plugin: 'eclipse' -apply plugin: 'maven-publish' -apply plugin: 'java-library' version = "${minecraftVersion}-${modVersion}" group = "io.${groupName}.${modId}" @@ -74,7 +80,6 @@ dependencies { // Project API api project("${rootProject.name}-api") - minecraft "net.minecraftforge:forge:${minecraftVersion}-${forgeVersion}" compile "org.spongepowered:mixin:0.8.1-SNAPSHOT" } From 5a1a60b1608b5986265665ecda3f9e80a165c1a6 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Mon, 4 May 2020 01:45:46 +0200 Subject: [PATCH 32/68] Add dependency URL as comments --- build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle b/build.gradle index 79e1400..5397cd2 100644 --- a/build.gradle +++ b/build.gradle @@ -7,6 +7,8 @@ buildscript { } dependencies { classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3.+', changing: true + + // https://github.com/SpongePowered/MixinGradle classpath 'org.spongepowered:mixingradle:0.7-SNAPSHOT' } } @@ -80,6 +82,7 @@ dependencies { // Project API api project("${rootProject.name}-api") + // https://github.com/SpongePowered/Mixin compile "org.spongepowered:mixin:0.8.1-SNAPSHOT" } From 61f1faa6a59f9301a171ed7095ec286748c97155 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Mon, 4 May 2020 08:30:13 +0200 Subject: [PATCH 33/68] Include api source set in jar --- build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.gradle b/build.gradle index 5397cd2..80ca87a 100644 --- a/build.gradle +++ b/build.gradle @@ -88,6 +88,8 @@ dependencies { // Get properties into the manifest for reading by the runtime.. jar { + // Include API main sourceSet in jar + from files(project("${rootProject.name}-api").sourceSets.main.output) manifest { attributes([ "Specification-Title": project.modId, From 417393da68c29be3535593841134f3a008730ba5 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Mon, 4 May 2020 08:40:12 +0200 Subject: [PATCH 34/68] Simplify project group name --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 80ca87a..d0a1867 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ allprojects { apply plugin: 'org.spongepowered.mixin' version = "${minecraftVersion}-${modVersion}" -group = "io.${groupName}.${modId}" +group = "io.${groupName}" archivesBaseName = project.modId // Need this here so eclipse task generates correctly. From f8d836d12db109c2d949b603e2aa8a10a811291c Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Mon, 4 May 2020 08:40:25 +0200 Subject: [PATCH 35/68] Clean gradle files --- build.gradle | 4 +--- gradle.properties | 2 -- settings.gradle | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index d0a1867..ac5cb41 100644 --- a/build.gradle +++ b/build.gradle @@ -33,9 +33,7 @@ compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility repositories { - mavenCentral() maven { url 'https://repo.spongepowered.org/maven' } - maven { url 'https://jitpack.io' } } mixin { @@ -86,7 +84,7 @@ dependencies { compile "org.spongepowered:mixin:0.8.1-SNAPSHOT" } -// Get properties into the manifest for reading by the runtime.. +// Get properties into the manifest for reading by the runtime jar { // Include API main sourceSet in jar from files(project("${rootProject.name}-api").sourceSets.main.output) diff --git a/gradle.properties b/gradle.properties index e4255f0..20160ce 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,5 +11,3 @@ minecraftVersion=1.15.2 forgeVersion=31.1.63 mappingMCVersion=1.15.1 mappingBuild=20200501 - -mixinBootstrapVer=1.0.2 diff --git a/settings.gradle b/settings.gradle index a798524..3e2228b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,4 @@ rootProject.name = "TimeLib" -include ":api" +include "api" project(':api').name = "${rootProject.name}-api" From 3e80e8ae9932dda1e8f27cb6cf26c306e08ec392 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Mon, 4 May 2020 22:25:52 +0200 Subject: [PATCH 36/68] Lowercase rootProject.name --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index 3e2228b..a378535 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,4 @@ -rootProject.name = "TimeLib" +rootProject.name = "timelib" include "api" project(':api').name = "${rootProject.name}-api" From 5f55a1fe3b58cadb60580068f7e1279d0a883fed Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Mon, 4 May 2020 22:35:59 +0200 Subject: [PATCH 37/68] Write additional TickRate javadoc --- .../main/java/io/yooksi/timelib/TickRate.java | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/api/src/main/java/io/yooksi/timelib/TickRate.java b/api/src/main/java/io/yooksi/timelib/TickRate.java index 2edbbde..6861e33 100644 --- a/api/src/main/java/io/yooksi/timelib/TickRate.java +++ b/api/src/main/java/io/yooksi/timelib/TickRate.java @@ -4,12 +4,31 @@ public class TickRate { - // Hardcoded limit so users don't go crazy with values + /** + * Maximum ticks per second allowed by TimeLib.
+ * This is to prevent users from going crazy with numbers. + */ public static final float MAXIMUM = 500.0f; private static float rate = TickProfile.DEFAULT.rate; private static float mspt = (float)(1000.0 / rate); + /** + * Set the game tick rate to a predefined profile value.
+ * For more gradual results see {@link #set(float)} + */ + public static void set(TickProfile profile) { + TickRate.set(profile.rate); + } + + /** + * Set the game tick rate to a desired value between negative and positive {@link #MAXIMUM}. + *

+ * Note that setting the tick rate to too high a value might negatively impact performance + * and setting it too low might increase the time it takes for the chat box to open + * + * @see #set(TickProfile) + */ public static float set(float rate) { TickRate.rate = rate; @@ -21,14 +40,23 @@ public static float set(float rate) { return TickRate.rate; } + /** + * Sets the game tick rate value to {@link TickProfile#DEFAULT} value. + */ public static float reset() { return set(TickProfile.DEFAULT.rate); } + /** + * @return current game tick rate as dictated by TimeLib. + */ public static float get() { return rate; } + /** + * @return the duration of each game tick measured in milliseconds. + */ public static float getMspt() { return mspt; } From f246d76fc694e447edf9ca410d7bdf308175a714 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Mon, 4 May 2020 22:37:49 +0200 Subject: [PATCH 38/68] Define jar attributes in var --- build.gradle | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/build.gradle b/build.gradle index ac5cb41..165c1ff 100644 --- a/build.gradle +++ b/build.gradle @@ -84,22 +84,22 @@ dependencies { compile "org.spongepowered:mixin:0.8.1-SNAPSHOT" } +final def jarAttributes = [ + "Specification-Title": project.modId, + "Specification-Vendor": "${groupName}", + "Specification-Version": "1", // We are version 1 of ourselves + "Implementation-Title": project.name, + "Implementation-Version": "${version}", + "Implementation-Vendor": "${groupName}", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"), + "MixinConfigs": "${modId}.mixins.json" +] + // Get properties into the manifest for reading by the runtime jar { // Include API main sourceSet in jar from files(project("${rootProject.name}-api").sourceSets.main.output) - manifest { - attributes([ - "Specification-Title": project.modId, - "Specification-Vendor": "${groupName}", - "Specification-Version": "1", // We are version 1 of ourselves - "Implementation-Title": project.name, - "Implementation-Version": "${version}", - "Implementation-Vendor": "${groupName}", - "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"), - "MixinConfigs": "${modId}.mixins.json" - ]) - } + manifest { attributes(jarAttributes) } } // Example configuration to allow publishing using the maven-publish task From f8e0c147556cd9994a4a1e62d866950cc934b30b Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Mon, 4 May 2020 22:39:18 +0200 Subject: [PATCH 39/68] Create dev and api jar tasks --- build.gradle | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/build.gradle b/build.gradle index 165c1ff..f2488dd 100644 --- a/build.gradle +++ b/build.gradle @@ -101,11 +101,36 @@ jar { from files(project("${rootProject.name}-api").sourceSets.main.output) manifest { attributes(jarAttributes) } } - // Example configuration to allow publishing using the maven-publish task // This is the preferred method to reobfuscate your jar file jar.finalizedBy('reobfJar') +task apiJar(type: Jar, dependsOn: classes) { + classifier = 'api' + from files(project("${rootProject.name}-api").sourceSets.main.output) +} +apiJar.finalizedBy('reobfJar') +build.dependsOn apiJar + +task devJar(type: Jar, dependsOn: classes) { + classifier = 'dev' + from sourceSets.main.output + // Include API main sourceSet in jar + from files(project("${rootProject.name}-api").sourceSets.main.output) + exclude("mixins.${modId}.refmap.json") + manifest { attributes(jarAttributes) } +} + +// Generate sources when building mod +task sourcesJar(type: Jar, dependsOn: classes) { + classifier = 'sources' + from sourceSets.main.allSource +} +build.dependsOn sourcesJar + +artifacts { + archives sourcesJar, devJar +} publishing { publications { mavenJava(MavenPublication) { @@ -119,16 +144,6 @@ publishing { } } -// Generate sources when building mod -task sourcesJar(type: Jar, dependsOn: classes) { - classifier = 'sources' - from sourceSets.main.allSource -} -build.dependsOn sourcesJar - -artifacts { - archives sourcesJar -} // Process resources on build and make sure that variables are // correctly inserted into mods.toml when the mod is built or run From cfe07191813c960be45c679c52897e8bcc013c15 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Mon, 4 May 2020 22:39:54 +0200 Subject: [PATCH 40/68] Include api jar in maven publish --- build.gradle | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f2488dd..94406bd 100644 --- a/build.gradle +++ b/build.gradle @@ -131,11 +131,15 @@ build.dependsOn sourcesJar artifacts { archives sourcesJar, devJar } + publishing { publications { mavenJava(MavenPublication) { artifact jar } + mavenJava(MavenPublication) { + artifact apiJar + } } repositories { maven { @@ -144,7 +148,6 @@ publishing { } } - // Process resources on build and make sure that variables are // correctly inserted into mods.toml when the mod is built or run processResources { From 8123d4867e7c92baa02e48aa8a8ef752f0eb1ade Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Wed, 13 May 2020 19:17:28 +0200 Subject: [PATCH 41/68] Remove empty API publication --- api/build.gradle | 8 -------- 1 file changed, 8 deletions(-) diff --git a/api/build.gradle b/api/build.gradle index 9a82469..31168d4 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -9,11 +9,3 @@ repositories { minecraft { mappings channel: 'snapshot', version: "${mappingBuild}-${mappingMCVersion}" } - -publishing { - publications { - maven(MavenPublication) { - artifactId = "${rootProject.name}-api" - } - } -} \ No newline at end of file From bc3d6a098f95c847961e6faecd4092a85f21b7c4 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Wed, 13 May 2020 19:17:56 +0200 Subject: [PATCH 42/68] Add mixin run config arg for server --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 94406bd..bb48f2e 100644 --- a/build.gradle +++ b/build.gradle @@ -64,6 +64,7 @@ minecraft { } server { workingDirectory project.file('run') + arg "-mixin.config=" + archivesBaseName + ".mixins.json" // Recommended logging data for a userdev environment property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' From 3b61ef800d0a3f2920a03122270cdf6168aedba4 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Wed, 13 May 2020 19:18:24 +0200 Subject: [PATCH 43/68] Start publishing sources --- build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle b/build.gradle index bb48f2e..720a24e 100644 --- a/build.gradle +++ b/build.gradle @@ -141,6 +141,9 @@ publishing { mavenJava(MavenPublication) { artifact apiJar } + mavenJava(MavenPublication) { + artifact sourcesJar + } } repositories { maven { From b6f5a07c86b181ddfbbc09912ad039c3ba8452f2 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Wed, 13 May 2020 19:18:33 +0200 Subject: [PATCH 44/68] Start publishing dev jar --- build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle b/build.gradle index 720a24e..9d07277 100644 --- a/build.gradle +++ b/build.gradle @@ -141,6 +141,9 @@ publishing { mavenJava(MavenPublication) { artifact apiJar } + mavenJava(MavenPublication) { + artifact devJar + } mavenJava(MavenPublication) { artifact sourcesJar } From 1b7b56aa20ca7b8d0f07e76b61df34cc30302ab6 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Wed, 13 May 2020 19:18:53 +0200 Subject: [PATCH 45/68] Stop creating api jar on build --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9d07277..04d3c2f 100644 --- a/build.gradle +++ b/build.gradle @@ -111,7 +111,6 @@ task apiJar(type: Jar, dependsOn: classes) { from files(project("${rootProject.name}-api").sourceSets.main.output) } apiJar.finalizedBy('reobfJar') -build.dependsOn apiJar task devJar(type: Jar, dependsOn: classes) { classifier = 'dev' From 5f57ff96c49158f0b8a3679de74ed1a1ce0e6c24 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Thu, 14 May 2020 19:16:51 +0200 Subject: [PATCH 46/68] Add and trim build.gradle docs --- build.gradle | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 04d3c2f..afb4502 100644 --- a/build.gradle +++ b/build.gradle @@ -12,6 +12,7 @@ buildscript { classpath 'org.spongepowered:mixingradle:0.7-SNAPSHOT' } } +// This part is common to api and main allprojects { apply plugin: 'net.minecraftforge.gradle' apply plugin: 'eclipse' @@ -36,15 +37,13 @@ repositories { maven { url 'https://repo.spongepowered.org/maven' } } +// Define which sourceSets will be covered by mixin refmap mixin { add sourceSets.main, "mixins.${modId}.refmap.json" } minecraft { - // The mappings can be changed at any time, and must be in the following format. - // snapshot_YYYYMMDD Snapshot are built nightly. - // stable_# Stables are built at the discretion of the MCP team. - // Use non-default mappings at your own risk. they may not always work. + // The mappings can be changed at any time, use non-default mappings at your own risk. // Simply re-run your setup task after changing the mappings to update your workspace. mappings channel: 'snapshot', version: "${mappingBuild}-${mappingMCVersion}" // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. @@ -106,12 +105,14 @@ jar { // This is the preferred method to reobfuscate your jar file jar.finalizedBy('reobfJar') +// API jar for library consumers task apiJar(type: Jar, dependsOn: classes) { classifier = 'api' from files(project("${rootProject.name}-api").sourceSets.main.output) } apiJar.finalizedBy('reobfJar') +// Non-obfuscated jar for developers task devJar(type: Jar, dependsOn: classes) { classifier = 'dev' from sourceSets.main.output From 082d924d8940157ec7819587b0dfe8bfdef8a49d Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Thu, 14 May 2020 19:18:01 +0200 Subject: [PATCH 47/68] Include apiJar under artifacts --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index afb4502..9d21797 100644 --- a/build.gradle +++ b/build.gradle @@ -130,7 +130,7 @@ task sourcesJar(type: Jar, dependsOn: classes) { build.dependsOn sourcesJar artifacts { - archives sourcesJar, devJar + archives sourcesJar, devJar, apiJar } publishing { From 6deb03a25e5899a23cf500cca2e3fafcd63a9c27 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Thu, 14 May 2020 19:33:39 +0200 Subject: [PATCH 48/68] Apply license notice to files Resolves #24 --- src/main/java/io/yooksi/timelib/Main.java | 13 +++++++++++++ .../java/io/yooksi/timelib/command/CmdHelper.java | 13 +++++++++++++ .../io/yooksi/timelib/command/TickRateCommand.java | 13 +++++++++++++ .../io/yooksi/timelib/command/TimeCycleCommand.java | 13 +++++++++++++ .../ClientPlayNetworkHandler_onChunkDataMixin.java | 13 +++++++++++++ .../java/io/yooksi/timelib/mixin/CommandsMixin.java | 13 +++++++++++++ .../timelib/mixin/MinecraftServer_runMixin.java | 13 +++++++++++++ .../timelib/mixin/Timer_updateTimerMixin.java | 13 +++++++++++++ .../timelib/mixin/World_advanceTimeMixin.java | 13 +++++++++++++ 9 files changed, 117 insertions(+) diff --git a/src/main/java/io/yooksi/timelib/Main.java b/src/main/java/io/yooksi/timelib/Main.java index 75bb00d..8b1189c 100644 --- a/src/main/java/io/yooksi/timelib/Main.java +++ b/src/main/java/io/yooksi/timelib/Main.java @@ -1,3 +1,16 @@ +/* + * Copyright (C) 2020 Matthew Cain + * + * This file is part of TimeLib. + * + * TimeLib 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. + * + * You should have received a copy of the GNU General Public License + * along with TimeLib. If not, see . + */ package io.yooksi.timelib; import org.apache.logging.log4j.LogManager; diff --git a/src/main/java/io/yooksi/timelib/command/CmdHelper.java b/src/main/java/io/yooksi/timelib/command/CmdHelper.java index 5cf036a..56cf550 100644 --- a/src/main/java/io/yooksi/timelib/command/CmdHelper.java +++ b/src/main/java/io/yooksi/timelib/command/CmdHelper.java @@ -1,3 +1,16 @@ +/* + * Copyright (C) 2020 Matthew Cain + * + * This file is part of TimeLib. + * + * TimeLib 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. + * + * You should have received a copy of the GNU General Public License + * along with TimeLib. If not, see . + */ package io.yooksi.timelib.command; import net.minecraft.command.CommandSource; diff --git a/src/main/java/io/yooksi/timelib/command/TickRateCommand.java b/src/main/java/io/yooksi/timelib/command/TickRateCommand.java index 64b6f32..277f588 100644 --- a/src/main/java/io/yooksi/timelib/command/TickRateCommand.java +++ b/src/main/java/io/yooksi/timelib/command/TickRateCommand.java @@ -1,3 +1,16 @@ +/* + * Copyright (C) 2020 Matthew Cain + * + * This file is part of TimeLib. + * + * TimeLib 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. + * + * You should have received a copy of the GNU General Public License + * along with TimeLib. If not, see . + */ package io.yooksi.timelib.command; import com.mojang.brigadier.CommandDispatcher; diff --git a/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java b/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java index 4102621..1036cb2 100644 --- a/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java +++ b/src/main/java/io/yooksi/timelib/command/TimeCycleCommand.java @@ -1,3 +1,16 @@ +/* + * Copyright (C) 2020 Matthew Cain + * + * This file is part of TimeLib. + * + * TimeLib 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. + * + * You should have received a copy of the GNU General Public License + * along with TimeLib. If not, see . + */ package io.yooksi.timelib.command; import com.mojang.brigadier.CommandDispatcher; diff --git a/src/main/java/io/yooksi/timelib/mixin/ClientPlayNetworkHandler_onChunkDataMixin.java b/src/main/java/io/yooksi/timelib/mixin/ClientPlayNetworkHandler_onChunkDataMixin.java index 25dd019..074c7c2 100644 --- a/src/main/java/io/yooksi/timelib/mixin/ClientPlayNetworkHandler_onChunkDataMixin.java +++ b/src/main/java/io/yooksi/timelib/mixin/ClientPlayNetworkHandler_onChunkDataMixin.java @@ -1,3 +1,16 @@ +/* + * Copyright (C) 2020 Matthew Cain + * + * This file is part of TimeLib. + * + * TimeLib 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. + * + * You should have received a copy of the GNU General Public License + * along with TimeLib. If not, see . + */ package io.yooksi.timelib.mixin; import java.util.Iterator; diff --git a/src/main/java/io/yooksi/timelib/mixin/CommandsMixin.java b/src/main/java/io/yooksi/timelib/mixin/CommandsMixin.java index d4fff8e..5642896 100644 --- a/src/main/java/io/yooksi/timelib/mixin/CommandsMixin.java +++ b/src/main/java/io/yooksi/timelib/mixin/CommandsMixin.java @@ -1,3 +1,16 @@ +/* + * Copyright (C) 2020 Matthew Cain + * + * This file is part of TimeLib. + * + * TimeLib 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. + * + * You should have received a copy of the GNU General Public License + * along with TimeLib. If not, see . + */ package io.yooksi.timelib.mixin; import io.yooksi.timelib.command.TimeCycleCommand; diff --git a/src/main/java/io/yooksi/timelib/mixin/MinecraftServer_runMixin.java b/src/main/java/io/yooksi/timelib/mixin/MinecraftServer_runMixin.java index adc3461..583ce94 100644 --- a/src/main/java/io/yooksi/timelib/mixin/MinecraftServer_runMixin.java +++ b/src/main/java/io/yooksi/timelib/mixin/MinecraftServer_runMixin.java @@ -1,3 +1,16 @@ +/* + * Copyright (C) 2020 Matthew Cain + * + * This file is part of TimeLib. + * + * TimeLib 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. + * + * You should have received a copy of the GNU General Public License + * along with TimeLib. If not, see . + */ package io.yooksi.timelib.mixin; import java.util.function.BooleanSupplier; diff --git a/src/main/java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java b/src/main/java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java index 0ac45f3..53868ce 100644 --- a/src/main/java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java +++ b/src/main/java/io/yooksi/timelib/mixin/Timer_updateTimerMixin.java @@ -1,3 +1,16 @@ +/* + * Copyright (C) 2020 Matthew Cain + * + * This file is part of TimeLib. + * + * TimeLib 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. + * + * You should have received a copy of the GNU General Public License + * along with TimeLib. If not, see . + */ package io.yooksi.timelib.mixin; import io.yooksi.timelib.TickRate; diff --git a/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java b/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java index 4b91caf..24d6a22 100644 --- a/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java +++ b/src/main/java/io/yooksi/timelib/mixin/World_advanceTimeMixin.java @@ -1,3 +1,16 @@ +/* + * Copyright (C) 2020 Matthew Cain + * + * This file is part of TimeLib. + * + * TimeLib 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. + * + * You should have received a copy of the GNU General Public License + * along with TimeLib. If not, see . + */ package io.yooksi.timelib.mixin; import io.yooksi.timelib.TimeCycle; From 010886cbabf0aba9cd5da252c2707931ac4be997 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Thu, 14 May 2020 19:34:05 +0200 Subject: [PATCH 49/68] Add IDEA copyright configs This will have to do since global copyright profiles are still not available: https://youtrack.jetbrains.com/issue/IDEA-136468 --- .idea/copyright/GPL.xml | 7 +++++++ .idea/copyright/profiles_settings.xml | 10 ++++++++++ 2 files changed, 17 insertions(+) create mode 100644 .idea/copyright/GPL.xml create mode 100644 .idea/copyright/profiles_settings.xml diff --git a/.idea/copyright/GPL.xml b/.idea/copyright/GPL.xml new file mode 100644 index 0000000..2db906b --- /dev/null +++ b/.idea/copyright/GPL.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..fb4a5c7 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file From dd1b1e070556595e62bea26c1ee8cd40e6dd7f15 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Thu, 14 May 2020 20:57:10 +0200 Subject: [PATCH 50/68] Move API classes to inner module --- api/build.gradle | 11 ----------- .../api}/java/io/yooksi/timelib/TickRate.java | 0 .../api}/java/io/yooksi/timelib/TimeCycle.java | 0 .../java/io/yooksi/timelib/define/TickProfile.java | 0 .../java/io/yooksi/timelib/define/TimeProfile.java | 0 5 files changed, 11 deletions(-) delete mode 100644 api/build.gradle rename {api/src/main => src/api}/java/io/yooksi/timelib/TickRate.java (100%) rename {api/src/main => src/api}/java/io/yooksi/timelib/TimeCycle.java (100%) rename {api/src/main => src/api}/java/io/yooksi/timelib/define/TickProfile.java (100%) rename {api/src/main => src/api}/java/io/yooksi/timelib/define/TimeProfile.java (100%) diff --git a/api/build.gradle b/api/build.gradle deleted file mode 100644 index 31168d4..0000000 --- a/api/build.gradle +++ /dev/null @@ -1,11 +0,0 @@ - -group rootProject.group -version rootProject.version - -repositories { - mavenCentral() -} - -minecraft { - mappings channel: 'snapshot', version: "${mappingBuild}-${mappingMCVersion}" -} diff --git a/api/src/main/java/io/yooksi/timelib/TickRate.java b/src/api/java/io/yooksi/timelib/TickRate.java similarity index 100% rename from api/src/main/java/io/yooksi/timelib/TickRate.java rename to src/api/java/io/yooksi/timelib/TickRate.java diff --git a/api/src/main/java/io/yooksi/timelib/TimeCycle.java b/src/api/java/io/yooksi/timelib/TimeCycle.java similarity index 100% rename from api/src/main/java/io/yooksi/timelib/TimeCycle.java rename to src/api/java/io/yooksi/timelib/TimeCycle.java diff --git a/api/src/main/java/io/yooksi/timelib/define/TickProfile.java b/src/api/java/io/yooksi/timelib/define/TickProfile.java similarity index 100% rename from api/src/main/java/io/yooksi/timelib/define/TickProfile.java rename to src/api/java/io/yooksi/timelib/define/TickProfile.java diff --git a/api/src/main/java/io/yooksi/timelib/define/TimeProfile.java b/src/api/java/io/yooksi/timelib/define/TimeProfile.java similarity index 100% rename from api/src/main/java/io/yooksi/timelib/define/TimeProfile.java rename to src/api/java/io/yooksi/timelib/define/TimeProfile.java From 4a1781ccff025062bff89601076e09ec94b8e72e Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Thu, 14 May 2020 20:57:45 +0200 Subject: [PATCH 51/68] Remove API project inclusion --- settings.gradle | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/settings.gradle b/settings.gradle index a378535..eb84a01 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1 @@ -rootProject.name = "timelib" - -include "api" -project(':api').name = "${rootProject.name}-api" +rootProject.name = "TimeLib" From 285d3274d1bab981c4b87f0e31ca9941aed0cee9 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Thu, 14 May 2020 21:21:27 +0200 Subject: [PATCH 52/68] Update build.gradle file --- build.gradle | 47 +++++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/build.gradle b/build.gradle index 9d21797..8097e69 100644 --- a/build.gradle +++ b/build.gradle @@ -12,17 +12,12 @@ buildscript { classpath 'org.spongepowered:mixingradle:0.7-SNAPSHOT' } } -// This part is common to api and main -allprojects { - apply plugin: 'net.minecraftforge.gradle' - apply plugin: 'eclipse' - apply plugin: 'maven-publish' - apply plugin: 'java-library' +apply plugin: 'net.minecraftforge.gradle' +apply plugin: 'eclipse' +apply plugin: 'maven' +apply plugin: 'maven-publish' +apply plugin: 'java-library' - dependencies { - minecraft "net.minecraftforge:forge:${minecraftVersion}-${forgeVersion}" - } -} apply plugin: 'org.spongepowered.mixin' version = "${minecraftVersion}-${modVersion}" @@ -37,6 +32,19 @@ repositories { maven { url 'https://repo.spongepowered.org/maven' } } +sourceSets { + api { + java { srcDir('src/api/java') } + } + impl { + java { + srcDir('src/main/java') + compileClasspath += api.output + runtimeClasspath += api.output + } + } +} + // Define which sourceSets will be covered by mixin refmap mixin { add sourceSets.main, "mixins.${modId}.refmap.json" @@ -77,11 +85,16 @@ minecraft { } dependencies { - // Project API - api project("${rootProject.name}-api") + // Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed + // that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied. + // The userdev artifact is a special name and will get all sorts of transformations applied to it. + minecraft "net.minecraftforge:forge:${minecraftVersion}-${forgeVersion}" // https://github.com/SpongePowered/Mixin compile "org.spongepowered:mixin:0.8.1-SNAPSHOT" + + runtime configurations.apiRuntime + runtime configurations.implRuntime } final def jarAttributes = [ @@ -95,10 +108,9 @@ final def jarAttributes = [ "MixinConfigs": "${modId}.mixins.json" ] -// Get properties into the manifest for reading by the runtime jar { - // Include API main sourceSet in jar - from files(project("${rootProject.name}-api").sourceSets.main.output) + from sourceSets.api.output + from sourceSets.main.output manifest { attributes(jarAttributes) } } // Example configuration to allow publishing using the maven-publish task @@ -108,16 +120,15 @@ jar.finalizedBy('reobfJar') // API jar for library consumers task apiJar(type: Jar, dependsOn: classes) { classifier = 'api' - from files(project("${rootProject.name}-api").sourceSets.main.output) + from sourceSets.api.output } apiJar.finalizedBy('reobfJar') // Non-obfuscated jar for developers task devJar(type: Jar, dependsOn: classes) { classifier = 'dev' + from sourceSets.api.output from sourceSets.main.output - // Include API main sourceSet in jar - from files(project("${rootProject.name}-api").sourceSets.main.output) exclude("mixins.${modId}.refmap.json") manifest { attributes(jarAttributes) } } From 267c34ecb25dfb5366117061ae561b1e773e12b7 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Thu, 14 May 2020 21:15:54 +0200 Subject: [PATCH 53/68] Add missing gradle-wrapper.jar --- .gitignore | 3 --- gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54708 bytes 2 files changed, 3 deletions(-) create mode 100644 gradle/wrapper/gradle-wrapper.jar diff --git a/.gitignore b/.gitignore index b23b446..ce23b75 100644 --- a/.gitignore +++ b/.gitignore @@ -20,9 +20,6 @@ build eclipse run -# package -*.jar - # log *.log diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..7a3265ee94c0ab25cf079ac8ccdf87f41d455d42 GIT binary patch literal 54708 zcmagFV|ZrKvM!pAZQHhO+qP}9lTNj?q^^Y^VFp)SH8qbSJ)2BQ2girk4u zvO<3q)c?v~^Z#E_K}1nTQbJ9gQ9<%vVRAxVj)8FwL5_iTdUB>&m3fhE=kRWl;g`&m z!W5kh{WsV%fO*%je&j+Lv4xxK~zsEYQls$Q-p&dwID|A)!7uWtJF-=Tm1{V@#x*+kUI$=%KUuf2ka zjiZ{oiL1MXE2EjciJM!jrjFNwCh`~hL>iemrqwqnX?T*MX;U>>8yRcZb{Oy+VKZos zLiFKYPw=LcaaQt8tj=eoo3-@bG_342HQ%?jpgAE?KCLEHC+DmjxAfJ%Og^$dpC8Xw zAcp-)tfJm}BPNq_+6m4gBgBm3+CvmL>4|$2N$^Bz7W(}fz1?U-u;nE`+9`KCLuqg} zwNstNM!J4Uw|78&Y9~9>MLf56to!@qGkJw5Thx%zkzj%Ek9Nn1QA@8NBXbwyWC>9H z#EPwjMNYPigE>*Ofz)HfTF&%PFj$U6mCe-AFw$U%-L?~-+nSXHHKkdgC5KJRTF}`G zE_HNdrE}S0zf4j{r_f-V2imSqW?}3w-4=f@o@-q+cZgaAbZ((hn))@|eWWhcT2pLpTpL!;_5*vM=sRL8 zqU##{U#lJKuyqW^X$ETU5ETeEVzhU|1m1750#f}38_5N9)B_2|v@1hUu=Kt7-@dhA zq_`OMgW01n`%1dB*}C)qxC8q;?zPeF_r;>}%JYmlER_1CUbKa07+=TV45~symC*g8 zW-8(gag#cAOuM0B1xG8eTp5HGVLE}+gYTmK=`XVVV*U!>H`~j4+ROIQ+NkN$LY>h4 zqpwdeE_@AX@PL};e5vTn`Ro(EjHVf$;^oiA%@IBQq>R7_D>m2D4OwwEepkg}R_k*M zM-o;+P27087eb+%*+6vWFCo9UEGw>t&WI17Pe7QVuoAoGHdJ(TEQNlJOqnjZ8adCb zI`}op16D@v7UOEo%8E-~m?c8FL1utPYlg@m$q@q7%mQ4?OK1h%ODjTjFvqd!C z-PI?8qX8{a@6d&Lb_X+hKxCImb*3GFemm?W_du5_&EqRq!+H?5#xiX#w$eLti-?E$;Dhu`{R(o>LzM4CjO>ICf z&DMfES#FW7npnbcuqREgjPQM#gs6h>`av_oEWwOJZ2i2|D|0~pYd#WazE2Bbsa}X@ zu;(9fi~%!VcjK6)?_wMAW-YXJAR{QHxrD5g(ou9mR6LPSA4BRG1QSZT6A?kelP_g- zH(JQjLc!`H4N=oLw=f3{+WmPA*s8QEeEUf6Vg}@!xwnsnR0bl~^2GSa5vb!Yl&4!> zWb|KQUsC$lT=3A|7vM9+d;mq=@L%uWKwXiO9}a~gP4s_4Yohc!fKEgV7WbVo>2ITbE*i`a|V!^p@~^<={#?Gz57 zyPWeM2@p>D*FW#W5Q`1`#5NW62XduP1XNO(bhg&cX`-LYZa|m-**bu|>}S;3)eP8_ zpNTnTfm8 ze+7wDH3KJ95p)5tlwk`S7mbD`SqHnYD*6`;gpp8VdHDz%RR_~I_Ar>5)vE-Pgu7^Y z|9Px+>pi3!DV%E%4N;ii0U3VBd2ZJNUY1YC^-e+{DYq+l@cGtmu(H#Oh%ibUBOd?C z{y5jW3v=0eV0r@qMLgv1JjZC|cZ9l9Q)k1lLgm))UR@#FrJd>w^`+iy$c9F@ic-|q zVHe@S2UAnc5VY_U4253QJxm&Ip!XKP8WNcnx9^cQ;KH6PlW8%pSihSH2(@{2m_o+m zr((MvBja2ctg0d0&U5XTD;5?d?h%JcRJp{_1BQW1xu&BrA3(a4Fh9hon-ly$pyeHq zG&;6q?m%NJ36K1Sq_=fdP(4f{Hop;_G_(i?sPzvB zDM}>*(uOsY0I1j^{$yn3#U(;B*g4cy$-1DTOkh3P!LQ;lJlP%jY8}Nya=h8$XD~%Y zbV&HJ%eCD9nui-0cw!+n`V~p6VCRqh5fRX z8`GbdZ@73r7~myQLBW%db;+BI?c-a>Y)m-FW~M=1^|<21_Sh9RT3iGbO{o-hpN%d6 z7%++#WekoBOP^d0$$|5npPe>u3PLvX_gjH2x(?{&z{jJ2tAOWTznPxv-pAv<*V7r$ z6&glt>7CAClWz6FEi3bToz-soY^{ScrjwVPV51=>n->c(NJngMj6TyHty`bfkF1hc zkJS%A@cL~QV0-aK4>Id!9dh7>0IV;1J9(myDO+gv76L3NLMUm9XyPauvNu$S<)-|F zZS}(kK_WnB)Cl`U?jsdYfAV4nrgzIF@+%1U8$poW&h^c6>kCx3;||fS1_7JvQT~CV zQ8Js+!p)3oW>Df(-}uqC`Tcd%E7GdJ0p}kYj5j8NKMp(KUs9u7?jQ94C)}0rba($~ zqyBx$(1ae^HEDG`Zc@-rXk1cqc7v0wibOR4qpgRDt#>-*8N3P;uKV0CgJE2SP>#8h z=+;i_CGlv+B^+$5a}SicVaSeaNn29K`C&=}`=#Nj&WJP9Xhz4mVa<+yP6hkrq1vo= z1rX4qg8dc4pmEvq%NAkpMK>mf2g?tg_1k2%v}<3`$6~Wlq@ItJ*PhHPoEh1Yi>v57 z4k0JMO)*=S`tKvR5gb-(VTEo>5Y>DZJZzgR+j6{Y`kd|jCVrg!>2hVjz({kZR z`dLlKhoqT!aI8=S+fVp(5*Dn6RrbpyO~0+?fy;bm$0jmTN|t5i6rxqr4=O}dY+ROd zo9Et|x}!u*xi~>-y>!M^+f&jc;IAsGiM_^}+4|pHRn{LThFFpD{bZ|TA*wcGm}XV^ zr*C6~@^5X-*R%FrHIgo-hJTBcyQ|3QEj+cSqp#>&t`ZzB?cXM6S(lRQw$I2?m5=wd z78ki`R?%;o%VUhXH?Z#(uwAn9$m`npJ=cA+lHGk@T7qq_M6Zoy1Lm9E0UUysN)I_x zW__OAqvku^>`J&CB=ie@yNWsaFmem}#L3T(x?a`oZ+$;3O-icj2(5z72Hnj=9Z0w% z<2#q-R=>hig*(t0^v)eGq2DHC%GymE-_j1WwBVGoU=GORGjtaqr0BNigOCqyt;O(S zKG+DoBsZU~okF<7ahjS}bzwXxbAxFfQAk&O@>LsZMsZ`?N?|CDWM(vOm%B3CBPC3o z%2t@%H$fwur}SSnckUm0-k)mOtht`?nwsDz=2#v=RBPGg39i#%odKq{K^;bTD!6A9 zskz$}t)sU^=a#jLZP@I=bPo?f-L}wpMs{Tc!m7-bi!Ldqj3EA~V;4(dltJmTXqH0r z%HAWKGutEc9vOo3P6Q;JdC^YTnby->VZ6&X8f{obffZ??1(cm&L2h7q)*w**+sE6dG*;(H|_Q!WxU{g)CeoT z(KY&bv!Usc|m+Fqfmk;h&RNF|LWuNZ!+DdX*L=s-=_iH=@i` z?Z+Okq^cFO4}_n|G*!)Wl_i%qiMBaH8(WuXtgI7EO=M>=i_+;MDjf3aY~6S9w0K zUuDO7O5Ta6+k40~xh~)D{=L&?Y0?c$s9cw*Ufe18)zzk%#ZY>Tr^|e%8KPb0ht`b( zuP@8#Ox@nQIqz9}AbW0RzE`Cf>39bOWz5N3qzS}ocxI=o$W|(nD~@EhW13Rj5nAp; zu2obEJa=kGC*#3=MkdkWy_%RKcN=?g$7!AZ8vBYKr$ePY(8aIQ&yRPlQ=mudv#q$q z4%WzAx=B{i)UdLFx4os?rZp6poShD7Vc&mSD@RdBJ=_m^&OlkEE1DFU@csgKcBifJ zz4N7+XEJhYzzO=86 z#%eBQZ$Nsf2+X0XPHUNmg#(sNt^NW1Y0|M(${e<0kW6f2q5M!2YE|hSEQ*X-%qo(V zHaFwyGZ0on=I{=fhe<=zo{=Og-_(to3?cvL4m6PymtNsdDINsBh8m>a%!5o3s(en) z=1I z6O+YNertC|OFNqd6P=$gMyvmfa`w~p9*gKDESFqNBy(~Zw3TFDYh}$iudn)9HxPBi zdokK@o~nu?%imcURr5Y~?6oo_JBe}t|pU5qjai|#JDyG=i^V~7+a{dEnO<(y>ahND#_X_fcEBNiZ)uc&%1HVtx8Ts z*H_Btvx^IhkfOB#{szN*n6;y05A>3eARDXslaE>tnLa>+`V&cgho?ED+&vv5KJszf zG4@G;7i;4_bVvZ>!mli3j7~tPgybF5|J6=Lt`u$D%X0l}#iY9nOXH@(%FFJLtzb%p zzHfABnSs;v-9(&nzbZytLiqqDIWzn>JQDk#JULcE5CyPq_m#4QV!}3421haQ+LcfO*>r;rg6K|r#5Sh|y@h1ao%Cl)t*u`4 zMTP!deC?aL7uTxm5^nUv#q2vS-5QbBKP|drbDXS%erB>fYM84Kpk^au99-BQBZR z7CDynflrIAi&ahza+kUryju5LR_}-Z27g)jqOc(!Lx9y)e z{cYc&_r947s9pteaa4}dc|!$$N9+M38sUr7h(%@Ehq`4HJtTpA>B8CLNO__@%(F5d z`SmX5jbux6i#qc}xOhumzbAELh*Mfr2SW99=WNOZRZgoCU4A2|4i|ZVFQt6qEhH#B zK_9G;&h*LO6tB`5dXRSBF0hq0tk{2q__aCKXYkP#9n^)@cq}`&Lo)1KM{W+>5mSed zKp~=}$p7>~nK@va`vN{mYzWN1(tE=u2BZhga5(VtPKk(*TvE&zmn5vSbjo zZLVobTl%;t@6;4SsZ>5+U-XEGUZGG;+~|V(pE&qqrp_f~{_1h@5ZrNETqe{bt9ioZ z#Qn~gWCH!t#Ha^n&fT2?{`}D@s4?9kXj;E;lWV9Zw8_4yM0Qg-6YSsKgvQ*fF{#Pq z{=(nyV>#*`RloBVCs;Lp*R1PBIQOY=EK4CQa*BD0MsYcg=opP?8;xYQDSAJBeJpw5 zPBc_Ft9?;<0?pBhCmOtWU*pN*;CkjJ_}qVic`}V@$TwFi15!mF1*m2wVX+>5p%(+R zQ~JUW*zWkalde{90@2v+oVlkxOZFihE&ZJ){c?hX3L2@R7jk*xjYtHi=}qb+4B(XJ z$gYcNudR~4Kz_WRq8eS((>ALWCO)&R-MXE+YxDn9V#X{_H@j616<|P(8h(7z?q*r+ zmpqR#7+g$cT@e&(%_|ipI&A%9+47%30TLY(yuf&*knx1wNx|%*H^;YB%ftt%5>QM= z^i;*6_KTSRzQm%qz*>cK&EISvF^ovbS4|R%)zKhTH_2K>jP3mBGn5{95&G9^a#4|K zv+!>fIsR8z{^x4)FIr*cYT@Q4Z{y}};rLHL+atCgHbfX*;+k&37DIgENn&=k(*lKD zG;uL-KAdLn*JQ?@r6Q!0V$xXP=J2i~;_+i3|F;_En;oAMG|I-RX#FwnmU&G}w`7R{ z788CrR-g1DW4h_`&$Z`ctN~{A)Hv_-Bl!%+pfif8wN32rMD zJDs$eVWBYQx1&2sCdB0!vU5~uf)=vy*{}t{2VBpcz<+~h0wb7F3?V^44*&83Z2#F` z32!rd4>uc63rQP$3lTH3zb-47IGR}f)8kZ4JvX#toIpXH`L%NnPDE~$QI1)0)|HS4 zVcITo$$oWWwCN@E-5h>N?Hua!N9CYb6f8vTFd>h3q5Jg-lCI6y%vu{Z_Uf z$MU{{^o~;nD_@m2|E{J)q;|BK7rx%`m``+OqZAqAVj-Dy+pD4-S3xK?($>wn5bi90CFAQ+ACd;&m6DQB8_o zjAq^=eUYc1o{#+p+ zn;K<)Pn*4u742P!;H^E3^Qu%2dM{2slouc$AN_3V^M7H_KY3H)#n7qd5_p~Za7zAj|s9{l)RdbV9e||_67`#Tu*c<8!I=zb@ z(MSvQ9;Wrkq6d)!9afh+G`!f$Ip!F<4ADdc*OY-y7BZMsau%y?EN6*hW4mOF%Q~bw z2==Z3^~?q<1GTeS>xGN-?CHZ7a#M4kDL zQxQr~1ZMzCSKFK5+32C%+C1kE#(2L=15AR!er7GKbp?Xd1qkkGipx5Q~FI-6zt< z*PTpeVI)Ngnnyaz5noIIgNZtb4bQdKG{Bs~&tf)?nM$a;7>r36djllw%hQxeCXeW^ z(i6@TEIuxD<2ulwLTt|&gZP%Ei+l!(%p5Yij6U(H#HMkqM8U$@OKB|5@vUiuY^d6X zW}fP3;Kps6051OEO(|JzmVU6SX(8q>*yf*x5QoxDK={PH^F?!VCzES_Qs>()_y|jg6LJlJWp;L zKM*g5DK7>W_*uv}{0WUB0>MHZ#oJZmO!b3MjEc}VhsLD~;E-qNNd?x7Q6~v zR=0$u>Zc2Xr}>x_5$-s#l!oz6I>W?lw;m9Ae{Tf9eMX;TI-Wf_mZ6sVrMnY#F}cDd z%CV*}fDsXUF7Vbw>PuDaGhu631+3|{xp<@Kl|%WxU+vuLlcrklMC!Aq+7n~I3cmQ! z`e3cA!XUEGdEPSu``&lZEKD1IKO(-VGvcnSc153m(i!8ohi`)N2n>U_BemYJ`uY>8B*Epj!oXRLV}XK}>D*^DHQ7?NY*&LJ9VSo`Ogi9J zGa;clWI8vIQqkngv2>xKd91K>?0`Sw;E&TMg&6dcd20|FcTsnUT7Yn{oI5V4@Ow~m zz#k~8TM!A9L7T!|colrC0P2WKZW7PNj_X4MfESbt<-soq*0LzShZ}fyUx!(xIIDwx zRHt^_GAWe0-Vm~bDZ(}XG%E+`XhKpPlMBo*5q_z$BGxYef8O!ToS8aT8pmjbPq)nV z%x*PF5ZuSHRJqJ!`5<4xC*xb2vC?7u1iljB_*iUGl6+yPyjn?F?GOF2_KW&gOkJ?w z3e^qc-te;zez`H$rsUCE0<@7PKGW?7sT1SPYWId|FJ8H`uEdNu4YJjre`8F*D}6Wh z|FQ`xf7yiphHIAkU&OYCn}w^ilY@o4larl?^M7&8YI;hzBIsX|i3UrLsx{QDKwCX< zy;a>yjfJ6!sz`NcVi+a!Fqk^VE^{6G53L?@Tif|j!3QZ0fk9QeUq8CWI;OmO-Hs+F zuZ4sHLA3{}LR2Qlyo+{d@?;`tpp6YB^BMoJt?&MHFY!JQwoa0nTSD+#Ku^4b{5SZVFwU9<~APYbaLO zu~Z)nS#dxI-5lmS-Bnw!(u15by(80LlC@|ynj{TzW)XcspC*}z0~8VRZq>#Z49G`I zgl|C#H&=}n-ajxfo{=pxPV(L*7g}gHET9b*s=cGV7VFa<;Htgjk>KyW@S!|z`lR1( zGSYkEl&@-bZ*d2WQ~hw3NpP=YNHF^XC{TMG$Gn+{b6pZn+5=<()>C!N^jncl0w6BJ zdHdnmSEGK5BlMeZD!v4t5m7ct7{k~$1Ie3GLFoHjAH*b?++s<|=yTF+^I&jT#zuMx z)MLhU+;LFk8bse|_{j+d*a=&cm2}M?*arjBPnfPgLwv)86D$6L zLJ0wPul7IenMvVAK$z^q5<^!)7aI|<&GGEbOr=E;UmGOIa}yO~EIr5xWU_(ol$&fa zR5E(2vB?S3EvJglTXdU#@qfDbCYs#82Yo^aZN6`{Ex#M)easBTe_J8utXu(fY1j|R z9o(sQbj$bKU{IjyhosYahY{63>}$9_+hWxB3j}VQkJ@2$D@vpeRSldU?&7I;qd2MF zSYmJ>zA(@N_iK}m*AMPIJG#Y&1KR)6`LJ83qg~`Do3v^B0>fU&wUx(qefuTgzFED{sJ65!iw{F2}1fQ3= ziFIP{kezQxmlx-!yo+sC4PEtG#K=5VM9YIN0z9~c4XTX?*4e@m;hFM!zVo>A`#566 z>f&3g94lJ{r)QJ5m7Xe3SLau_lOpL;A($wsjHR`;xTXgIiZ#o&vt~ zGR6KdU$FFbLfZCC3AEu$b`tj!9XgOGLSV=QPIYW zjI!hSP#?8pn0@ezuenOzoka8!8~jXTbiJ6+ZuItsWW03uzASFyn*zV2kIgPFR$Yzm zE<$cZlF>R8?Nr2_i?KiripBc+TGgJvG@vRTY2o?(_Di}D30!k&CT`>+7ry2!!iC*X z<@=U0_C#16=PN7bB39w+zPwDOHX}h20Ap);dx}kjXX0-QkRk=cr};GYsjSvyLZa-t zzHONWddi*)RDUH@RTAsGB_#&O+QJaaL+H<<9LLSE+nB@eGF1fALwjVOl8X_sdOYme z0lk!X=S(@25=TZHR7LlPp}fY~yNeThMIjD}pd9+q=j<_inh0$>mIzWVY+Z9p<{D^#0Xk+b_@eNSiR8;KzSZ#7lUsk~NGMcB8C2c=m2l5paHPq`q{S(kdA7Z1a zyfk2Y;w?^t`?@yC5Pz9&pzo}Hc#}mLgDmhKV|PJ3lKOY(Km@Fi2AV~CuET*YfUi}u zfInZnqDX(<#vaS<^fszuR=l)AbqG{}9{rnyx?PbZz3Pyu!eSJK`uwkJU!ORQXy4x83r!PNgOyD33}}L=>xX_93l6njNTuqL8J{l%*3FVn3MG4&Fv*`lBXZ z?=;kn6HTT^#SrPX-N)4EZiIZI!0ByXTWy;;J-Tht{jq1mjh`DSy7yGjHxIaY%*sTx zuy9#9CqE#qi>1misx=KRWm=qx4rk|}vd+LMY3M`ow8)}m$3Ggv&)Ri*ON+}<^P%T5 z_7JPVPfdM=Pv-oH<tecoE}(0O7|YZc*d8`Uv_M*3Rzv7$yZnJE6N_W=AQ3_BgU_TjA_T?a)U1csCmJ&YqMp-lJe`y6>N zt++Bi;ZMOD%%1c&-Q;bKsYg!SmS^#J@8UFY|G3!rtyaTFb!5@e(@l?1t(87ln8rG? z--$1)YC~vWnXiW3GXm`FNSyzu!m$qT=Eldf$sMl#PEfGmzQs^oUd=GIQfj(X=}dw+ zT*oa0*oS%@cLgvB&PKIQ=Ok?>x#c#dC#sQifgMwtAG^l3D9nIg(Zqi;D%807TtUUCL3_;kjyte#cAg?S%e4S2W>9^A(uy8Ss0Tc++ZTjJw1 z&Em2g!3lo@LlDyri(P^I8BPpn$RE7n*q9Q-c^>rfOMM6Pd5671I=ZBjAvpj8oIi$! zl0exNl(>NIiQpX~FRS9UgK|0l#s@#)p4?^?XAz}Gjb1?4Qe4?j&cL$C8u}n)?A@YC zfmbSM`Hl5pQFwv$CQBF=_$Sq zxsV?BHI5bGZTk?B6B&KLdIN-40S426X3j_|ceLla*M3}3gx3(_7MVY1++4mzhH#7# zD>2gTHy*%i$~}mqc#gK83288SKp@y3wz1L_e8fF$Rb}ex+`(h)j}%~Ld^3DUZkgez zOUNy^%>>HHE|-y$V@B}-M|_{h!vXpk01xaD%{l{oQ|~+^>rR*rv9iQen5t?{BHg|% zR`;S|KtUb!X<22RTBA4AAUM6#M?=w5VY-hEV)b`!y1^mPNEoy2K)a>OyA?Q~Q*&(O zRzQI~y_W=IPi?-OJX*&&8dvY0zWM2%yXdFI!D-n@6FsG)pEYdJbuA`g4yy;qrgR?G z8Mj7gv1oiWq)+_$GqqQ$(ZM@#|0j7})=#$S&hZwdoijFI4aCFLVI3tMH5fLreZ;KD zqA`)0l~D2tuIBYOy+LGw&hJ5OyE+@cnZ0L5+;yo2pIMdt@4$r^5Y!x7nHs{@>|W(MzJjATyWGNwZ^4j+EPU0RpAl-oTM@u{lx*i0^yyWPfHt6QwPvYpk9xFMWfBFt!+Gu6TlAmr zeQ#PX71vzN*_-xh&__N`IXv6`>CgV#eA_%e@7wjgkj8jlKzO~Ic6g$cT`^W{R{606 zCDP~+NVZ6DMO$jhL~#+!g*$T!XW63#(ngDn#Qwy71yj^gazS{e;3jGRM0HedGD@pt z?(ln3pCUA(ekqAvvnKy0G@?-|-dh=eS%4Civ&c}s%wF@0K5Bltaq^2Os1n6Z3%?-Q zAlC4goQ&vK6TpgtzkHVt*1!tBYt-`|5HLV1V7*#45Vb+GACuU+QB&hZ=N_flPy0TY zR^HIrdskB#<$aU;HY(K{a3(OQa$0<9qH(oa)lg@Uf>M5g2W0U5 zk!JSlhrw8quBx9A>RJ6}=;W&wt@2E$7J=9SVHsdC?K(L(KACb#z)@C$xXD8^!7|uv zZh$6fkq)aoD}^79VqdJ!Nz-8$IrU(_-&^cHBI;4 z^$B+1aPe|LG)C55LjP;jab{dTf$0~xbXS9!!QdcmDYLbL^jvxu2y*qnx2%jbL%rB z{aP85qBJe#(&O~Prk%IJARcdEypZ)vah%ZZ%;Zk{eW(U)Bx7VlzgOi8)x z`rh4l`@l_Ada7z&yUK>ZF;i6YLGwI*Sg#Fk#Qr0Jg&VLax(nNN$u-XJ5=MsP3|(lEdIOJ7|(x3iY;ea)5#BW*mDV%^=8qOeYO&gIdJVuLLN3cFaN=xZtFB=b zH{l)PZl_j^u+qx@89}gAQW7ofb+k)QwX=aegihossZq*+@PlCpb$rpp>Cbk9UJO<~ zDjlXQ_Ig#W0zdD3&*ei(FwlN#3b%FSR%&M^ywF@Fr>d~do@-kIS$e%wkIVfJ|Ohh=zc zF&Rnic^|>@R%v?@jO}a9;nY3Qrg_!xC=ZWUcYiA5R+|2nsM*$+c$TOs6pm!}Z}dfM zGeBhMGWw3$6KZXav^>YNA=r6Es>p<6HRYcZY)z{>yasbC81A*G-le8~QoV;rtKnkx z;+os8BvEe?0A6W*a#dOudsv3aWs?d% z0oNngyVMjavLjtjiG`!007#?62ClTqqU$@kIY`=x^$2e>iqIy1>o|@Tw@)P)B8_1$r#6>DB_5 zmaOaoE~^9TolgDgooKFuEFB#klSF%9-~d2~_|kQ0Y{Ek=HH5yq9s zDq#1S551c`kSiWPZbweN^A4kWiP#Qg6er1}HcKv{fxb1*BULboD0fwfaNM_<55>qM zETZ8TJDO4V)=aPp_eQjX%||Ud<>wkIzvDlpNjqW>I}W!-j7M^TNe5JIFh#-}zAV!$ICOju8Kx)N z0vLtzDdy*rQN!7r>Xz7rLw8J-(GzQlYYVH$WK#F`i_i^qVlzTNAh>gBWKV@XC$T-` z3|kj#iCquDhiO7NKum07i|<-NuVsX}Q}mIP$jBJDMfUiaWR3c|F_kWBMw0_Sr|6h4 zk`_r5=0&rCR^*tOy$A8K;@|NqwncjZ>Y-75vlpxq%Cl3EgH`}^^~=u zoll6xxY@a>0f%Ddpi;=cY}fyG!K2N-dEyXXmUP5u){4VnyS^T4?pjN@Ot4zjL(Puw z_U#wMH2Z#8Pts{olG5Dy0tZj;N@;fHheu>YKYQU=4Bk|wcD9MbA`3O4bj$hNRHwzb zSLcG0SLV%zywdbuwl(^E_!@&)TdXge4O{MRWk2RKOt@!8E{$BU-AH(@4{gxs=YAz9LIob|Hzto0}9cWoz6Tp2x0&xi#$ zHh$dwO&UCR1Ob2w00-2eG7d4=cN(Y>0R#$q8?||q@iTi+7-w-xR%uMr&StFIthC<# zvK(aPduwuNB}oJUV8+Zl)%cnfsHI%4`;x6XW^UF^e4s3Z@S<&EV8?56Wya;HNs0E> z`$0dgRdiUz9RO9Au3RmYq>K#G=X%*_dUbSJHP`lSfBaN8t-~@F>)BL1RT*9I851A3 z<-+Gb#_QRX>~av#Ni<#zLswtu-c6{jGHR>wflhKLzC4P@b%8&~u)fosoNjk4r#GvC zlU#UU9&0Hv;d%g72Wq?Ym<&&vtA3AB##L}=ZjiTR4hh7J)e>ei} zt*u+>h%MwN`%3}b4wYpV=QwbY!jwfIj#{me)TDOG`?tI!%l=AwL2G@9I~}?_dA5g6 zCKgK(;6Q0&P&K21Tx~k=o6jwV{dI_G+Ba*Zts|Tl6q1zeC?iYJTb{hel*x>^wb|2RkHkU$!+S4OU4ZOKPZjV>9OVsqNnv5jK8TRAE$A&^yRwK zj-MJ3Pl?)KA~fq#*K~W0l4$0=8GRx^9+?w z!QT8*-)w|S^B0)ZeY5gZPI2G(QtQf?DjuK(s^$rMA!C%P22vynZY4SuOE=wX2f8$R z)A}mzJi4WJnZ`!bHG1=$lwaxm!GOnRbR15F$nRC-M*H<*VfF|pQw(;tbSfp({>9^5 zw_M1-SJ9eGF~m(0dvp*P8uaA0Yw+EkP-SWqu zqal$hK8SmM7#Mrs0@OD+%_J%H*bMyZiWAZdsIBj#lkZ!l2c&IpLu(5^T0Ge5PHzR} zn;TXs$+IQ_&;O~u=Jz+XE0wbOy`=6>m9JVG} zJ~Kp1e5m?K3x@@>!D)piw^eMIHjD4RebtR`|IlckplP1;r21wTi8v((KqNqn%2CB< zifaQc&T}*M&0i|LW^LgdjIaX|o~I$`owHolRqeH_CFrqCUCleN130&vH}dK|^kC>) z-r2P~mApHotL4dRX$25lIcRh_*kJaxi^%ZN5-GAAMOxfB!6flLPY-p&QzL9TE%ho( zRwftE3sy5<*^)qYzKkL|rE>n@hyr;xPqncY6QJ8125!MWr`UCWuC~A#G1AqF1@V$kv>@NBvN&2ygy*{QvxolkRRb%Ui zsmKROR%{*g*WjUUod@@cS^4eF^}yQ1>;WlGwOli z+Y$(8I`0(^d|w>{eaf!_BBM;NpCoeem2>J}82*!em=}}ymoXk>QEfJ>G(3LNA2-46 z5PGvjr)Xh9>aSe>vEzM*>xp{tJyZox1ZRl}QjcvX2TEgNc^(_-hir@Es>NySoa1g^ zFow_twnHdx(j?Q_3q51t3XI7YlJ4_q&(0#)&a+RUy{IcBq?)eaWo*=H2UUVIqtp&lW9JTJiP&u zw8+4vo~_IJXZIJb_U^&=GI1nSD%e;P!c{kZALNCm5c%%oF+I3DrA63_@4)(v4(t~JiddILp7jmoy+>cD~ivwoctFfEL zP*#2Rx?_&bCpX26MBgp^4G>@h`Hxc(lnqyj!*t>9sOBcXN(hTwEDpn^X{x!!gPX?1 z*uM$}cYRwHXuf+gYTB}gDTcw{TXSOUU$S?8BeP&sc!Lc{{pEv}x#ELX>6*ipI1#>8 zKes$bHjiJ1OygZge_ak^Hz#k;=od1wZ=o71ba7oClBMq>Uk6hVq|ePPt)@FM5bW$I z;d2Or@wBjbTyZj|;+iHp%Bo!Vy(X3YM-}lasMItEV_QrP-Kk_J4C>)L&I3Xxj=E?| zsAF(IfVQ4w+dRRnJ>)}o^3_012YYgFWE)5TT=l2657*L8_u1KC>Y-R{7w^ShTtO;VyD{dezY;XD@Rwl_9#j4Uo!1W&ZHVe0H>f=h#9k>~KUj^iUJ%@wU{Xuy z3FItk0<;}6D02$u(RtEY#O^hrB>qgxnOD^0AJPGC9*WXw_$k%1a%-`>uRIeeAIf3! zbx{GRnG4R$4)3rVmg63gW?4yIWW_>;t3>4@?3}&ct0Tk}<5ljU>jIN1 z&+mzA&1B6`v(}i#vAzvqWH~utZzQR;fCQGLuCN|p0hey7iCQ8^^dr*hi^wC$bTk`8M(JRKtQuXlSf$d(EISvuY0dM z7&ff;p-Ym}tT8^MF5ACG4sZmAV!l;0h&Mf#ZPd--_A$uv2@3H!y^^%_&Iw$*p79Uc5@ZXLGK;edg%)6QlvrN`U7H@e^P*0Atd zQB%>4--B1!9yeF(3vk;{>I8+2D;j`zdR8gd8dHuCQ_6|F(5-?gd&{YhLeyq_-V--4 z(SP#rP=-rsSHJSHDpT1{dMAb7-=9K1-@co_!$dG^?c(R-W&a_C5qy2~m3@%vBGhgnrw|H#g9ABb7k{NE?m4xD?;EV+fPdE>S2g$U(&_zGV+TPvaot>W_ zf8yY@)yP8k$y}UHVgF*uxtjW2zX4Hc3;W&?*}K&kqYpi%FHarfaC$ETHpSoP;A692 zR*LxY1^BO1ry@7Hc9p->hd==U@cuo*CiTnozxen;3Gct=?{5P94TgQ(UJoBb`7z@BqY z;q&?V2D1Y%n;^Dh0+eD)>9<}=A|F5{q#epBu#sf@lRs`oFEpkE%mrfwqJNFCpJC$| zy6#N;GF8XgqX(m2yMM2yq@TxStIR7whUIs2ar$t%Avh;nWLwElVBSI#j`l2$lb-!y zK|!?0hJ1T-wL{4uJhOFHp4?@28J^Oh61DbeTeSWub(|dL-KfxFCp0CjQjV`WaPW|U z=ev@VyC>IS@{ndzPy||b3z-bj5{Y53ff}|TW8&&*pu#?qs?)#&M`ACfb;%m+qX{Or zb+FNNHU}mz!@!EdrxmP_6eb3Cah!mL0ArL#EA1{nCY-!jL8zzz7wR6wAw(8K|IpW; zUvH*b1wbuRlwlUt;dQhx&pgsvJcUpm67rzkNc}2XbC6mZAgUn?VxO6YYg=M!#e=z8 zjX5ZLyMyz(VdPVyosL0}ULO!Mxu>hh`-MItnGeuQ;wGaU0)gIq3ZD=pDc(Qtk}APj z#HtA;?idVKNF)&0r|&w#l7DbX%b91b2;l2=L8q#}auVdk{RuYn3SMDo1%WW0tD*62 zaIj65Y38;?-~@b82AF!?Nra2;PU)t~qYUhl!GDK3*}%@~N0GQH7zflSpfP-ydOwNe zOK~w((+pCD&>f!b!On);5m+zUBFJtQ)mV^prS3?XgPybC2%2LiE5w+S4B|lP z+_>3$`g=%P{IrN|1Oxz30R{kI`}ZL!r|)RS@8Do;ZD3_=PbBrrP~S@EdsD{V+`!4v z{MSF}j!6odl33rA+$odIMaK%ersg%xMz>JQ^R+!qNq$5S{KgmGN#gAApX*3ib)TDsVVi>4ypIX|Ik4d6E}v z=8+hs9J=k3@Eiga^^O|ESMQB-O6i+BL*~*8coxjGs{tJ9wXjGZ^Vw@j93O<&+bzAH z9+N^ALvDCV<##cGoo5fX;wySGGmbH zHsslio)cxlud=iP2y=nM>v8vBn*hJ0KGyNOy7dr8yJKRh zywBOa4Lhh58y06`5>ESYXqLt8ZM1axd*UEp$wl`APU}C9m1H8-ModG!(wfSUQ%}rT3JD*ud~?WJdM}x>84)Cra!^J9wGs6^G^ze~eV(d&oAfm$ z_gwq4SHe=<#*FN}$5(0d_NumIZYaqs|MjFtI_rJb^+ZO?*XQ*47mzLNSL7~Nq+nw8 zuw0KwWITC43`Vx9eB!0Fx*CN9{ea$xjCvtjeyy>yf!ywxvv6<*h0UNXwkEyRxX{!e$TgHZ^db3r;1qhT)+yt@|_!@ zQG2aT`;lj>qjY`RGfQE?KTt2mn=HmSR>2!E38n8PlFs=1zsEM}AMICb z86Dbx(+`!hl$p=Z)*W~+?_HYp+CJacrCS-Fllz!7E>8*!E(yCh-cWbKc7)mPT6xu= zfKpF3I+p%yFXkMIq!ALiXF89-aV{I6v+^k#!_xwtQ*Nl#V|hKg=nP=fG}5VB8Ki7) z;19!on-iq&Xyo#AowvpA)RRgF?YBdDc$J8*)2Wko;Y?V6XMOCqT(4F#U2n1jg*4=< z8$MfDYL|z731iEKB3WW#kz|c3qh7AXjyZ}wtSg9xA(ou-pLoxF{4qk^KS?!d3J0!! zqE#R9NYGUyy>DEs%^xW;oQ5Cs@fomcrsN}rI2Hg^6y9kwLPF`K3llX00aM_r)c?ay zevlHA#N^8N+AI=)vx?4(=?j^ba^{umw140V#g58#vtnh8i7vRs*UD=lge;T+I zl1byCNr5H%DF58I2(rk%8hQ;zuCXs=sipbQy?Hd;umv4!fav@LE4JQ^>J{aZ=!@Gc~p$JudMy%0{=5QY~S8YVP zaP6gRqfZ0>q9nR3p+Wa8icNyl0Zn4k*bNto-(+o@-D8cd1Ed7`}dN3%wezkFxj_#_K zyV{msOOG;n+qbU=jBZk+&S$GEwJ99zSHGz8hF1`Xxa^&l8aaD8OtnIVsdF0cz=Y)? zP$MEdfKZ}_&#AC)R%E?G)tjrKsa-$KW_-$QL}x$@$NngmX2bHJQG~77D1J%3bGK!- zl!@kh5-uKc@U4I_Er;~epL!gej`kdX>tSXVFP-BH#D-%VJOCpM(-&pOY+b#}lOe)Z z0MP5>av1Sy-dfYFy%?`p`$P|`2yDFlv(8MEsa++Qv5M?7;%NFQK0E`Ggf3@2aUwtBpCoh`D}QLY%QAnJ z%qcf6!;cjOTYyg&2G27K(F8l^RgdV-V!~b$G%E=HP}M*Q*%xJV3}I8UYYd)>*nMvw zemWg`K6Rgy+m|y!8&*}=+`STm(dK-#b%)8nLsL&0<8Zd^|# z;I2gR&e1WUS#v!jX`+cuR;+yi(EiDcRCouW0AHNd?;5WVnC_Vg#4x56#0FOwTH6_p z#GILFF0>bb_tbmMM0|sd7r%l{U!fI0tGza&?65_D7+x9G zf3GA{c|mnO(|>}y(}%>|2>p0X8wRS&Eb0g)rcICIctfD_I9Wd+hKuEqv?gzEZBxG-rG~e!-2hqaR$Y$I@k{rLyCccE}3d)7Fn3EvfsEhA|bnJ374&pZDq&i zr(9#eq(g8^tG??ZzVk(#jU+-ce`|yiQ1dgrJ)$|wk?XLEqv&M+)I*OZ*oBCizjHuT zjZ|mW=<1u$wPhyo#&rIO;qH~pu4e3X;!%BRgmX%?&KZ6tNl386-l#a>ug5nHU2M~{fM2jvY*Py< zbR&^o&!T19G6V-pV@CB)YnEOfmrdPG%QByD?=if99ihLxP6iA8$??wUPWzptC{u5H z38Q|!=IW`)5Gef4+pz|9fIRXt>nlW)XQvUXBO8>)Q=$@gtwb1iEkU4EOWI4`I4DN5 zTC-Pk6N>2%7Hikg?`Poj5lkM0T_i zoCXfXB&}{TG%IB)ENSfI_Xg3=lxYc6-P059>oK;L+vGMy_h{y9soj#&^q5E!pl(Oq zl)oCBi56u;YHkD)d`!iOAhEJ0A^~T;uE9~Yp0{E%G~0q|9f34F!`P56-ZF{2hSaWj zio%9RR%oe~he22r@&j_d(y&nAUL*ayBY4#CWG&gZ8ybs#UcF?8K#HzziqOYM-<`C& z1gD?j)M0bp1w*U>X_b1@ag1Fx=d*wlr zEAcpmI#5LtqcX95LeS=LXlzh*l;^yPl_6MKk)zPuTz_p8ynQ5;oIOUAoPED=+M6Q( z8YR!DUm#$zTM9tbNhxZ4)J0L&Hpn%U>wj3z<=g;`&c_`fGufS!o|1%I_sA&;14bRC z3`BtzpAB-yl!%zM{Aiok8*X%lDNrPiAjBnzHbF0=Ua*3Lxl(zN3Thj2x6nWi^H7Jlwd2fxIvnI-SiC%*j z2~wIWWKT^5fYipo-#HSrr;(RkzzCSt?THVEH2EPvV-4c#Gu4&1X% z<1zTAM7ZM(LuD@ZPS?c30Ur`;2w;PXPVevxT)Ti25o}1JL>MN5i1^(aCF3 zbp>RI?X(CkR9*Hnv!({Ti@FBm;`Ip%e*D2tWEOc62@$n7+gWb;;j}@G()~V)>s}Bd zw+uTg^ibA(gsp*|&m7Vm=heuIF_pIukOedw2b_uO8hEbM4l=aq?E-7M_J`e(x9?{5 zpbgu7h}#>kDQAZL;Q2t?^pv}Y9Zlu=lO5e18twH&G&byq9XszEeXt$V93dQ@Fz2DV zs~zm*L0uB`+o&#{`uVYGXd?)Fv^*9mwLW4)IKoOJ&(8uljK?3J`mdlhJF1aK;#vlc zJdTJc2Q>N*@GfafVw45B03)Ty8qe>Ou*=f#C-!5uiyQ^|6@Dzp9^n-zidp*O`YuZ|GO28 zO0bqi;)fspT0dS2;PLm(&nLLV&&=Ingn(0~SB6Fr^AxPMO(r~y-q2>gRWv7{zYW6c zfiuqR)Xc41A7Eu{V7$-yxYT-opPtqQIJzMVkxU)cV~N0ygub%l9iHT3eQtB>nH0c` zFy}Iwd9vocxlm!P)eh0GwKMZ(fEk92teSi*fezYw3qRF_E-EcCh-&1T)?beW?9Q_+pde8&UW*(avPF4P}M#z*t~KlF~#5TT!&nu z>FAKF8vQl>Zm(G9UKi4kTqHj`Pf@Z@Q(bmZkseb1^;9k*`a9lKXceKX#dMd@ds`t| z2~UPsbn2R0D9Nm~G*oc@(%oYTD&yK)scA?36B7mndR9l*hNg!3?6>CR+tF1;6sr?V zzz8FBrZ@g4F_!O2igIGZcWd zRe_0*{d6cyy9QQ(|Ct~WTM1pC3({5qHahk*M*O}IPE6icikx48VZ?!0Oc^FVoq`}eu~ zpRq0MYHaBA-`b_BVID}|oo-bem76;B2zo7j7yz(9JiSY6JTjKz#+w{9mc{&#x}>E? zSS3mY$_|scfP3Mo_F5x;r>y&Mquy*Q1b3eF^*hg3tap~%?@ASeyodYa=dF&k=ZyWy z3C+&C95h|9TAVM~-8y(&xcy0nvl}6B*)j0FOlSz%+bK-}S4;F?P`j55*+ZO0Ogk7D z5q30zE@Nup4lqQoG`L%n{T?qn9&WC94%>J`KU{gHIq?n_L;75kkKyib;^?yXUx6BO zju%DyU(l!Vj(3stJ>!pMZ*NZFd60%oSAD1JUXG0~2GCXpB0Am(YPyhzQda-e)b^+f zzFaEZdVTJRJXPJo%w z$?T;xq^&(XjmO>0bNGsT|1{1UqGHHhasPC;H!oX52(AQ7h9*^npOIRdQbNrS0X5#5G?L4V}WsAYcpq-+JNXhSl)XbxZ)L@5Q+?wm{GAU z9a7X8hAjAo;4r_eOdZfXGL@YpmT|#qECEcPTQ;nsjIkQ;!0}g?T>Zr*Fg}%BZVA)4 zCAzvWr?M&)KEk`t9eyFi_GlPV9a2kj9G(JgiZadd_&Eb~#DyZ%2Zcvrda_A47G&uW z^6TnBK|th;wHSo8ivpScU?AM5HDu2+ayzExMJc@?4{h-c`!b($ExB`ro#vkl<;=BA z961c*n(4OR!ebT*7UV7sqL;rZ3+Z)BYs<1I|9F|TOKebtLPxahl|ZXxj4j!gjj!3*+iSb5Zni&EKVt$S{0?2>A}d@3PSF3LUu)5 z*Y#a1uD6Y!$=_ghsPrOqX!OcIP`IW};tZzx1)h_~mgl;0=n zdP|Te_7)~R?c9s>W(-d!@nzQyxqakrME{Tn@>0G)kqV<4;{Q?Z-M)E-|IFLTc}WQr z1Qt;u@_dN2kru_9HMtz8MQx1aDYINH&3<+|HA$D#sl3HZ&YsjfQBv~S>4=u z7gA2*X6_cI$2}JYLIq`4NeXTz6Q3zyE717#>RD&M?0Eb|KIyF;xj;+3#DhC-xOj~! z$-Kx#pQ)_$eHE3Zg?V>1z^A%3jW0JBnd@z`kt$p@lch?A9{j6hXxt$(3|b>SZiBxOjA%LsIPii{=o(B`yRJ>OK;z_ELTi8xHX)il z--qJ~RWsZ%9KCNuRNUypn~<2+mQ=O)kd59$Lul?1ev3c&Lq5=M#I{ zJby%%+Top_ocqv!jG6O6;r0Xwb%vL6SP{O(hUf@8riADSI<|y#g`D)`x^vHR4!&HY`#TQMqM`Su}2(C|KOmG`wyK>uh@3;(prdL{2^7T3XFGznp{-sNLLJH@mh* z^vIyicj9yH9(>~I-Ev7p=yndfh}l!;3Q65}K}()(jp|tC;{|Ln1a+2kbctWEX&>Vr zXp5=#pw)@-O6~Q|><8rd0>H-}0Nsc|J6TgCum{XnH2@hFB09FsoZ_ow^Nv@uGgz3# z<6dRDt1>>-!kN58&K1HFrgjTZ^q<>hNI#n8=hP&pKAL4uDcw*J66((I?!pE0fvY6N zu^N=X8lS}(=w$O_jlE(;M9F={-;4R(K5qa=P#ZVW>}J&s$d0?JG8DZJwZcx3{CjLg zJA>q-&=Ekous)vT9J>fbnZYNUtvox|!Rl@e^a6ue_4-_v=(sNB^I1EPtHCFEs!>kK6B@-MS!(B zST${=v9q6q8YdSwk4}@c6cm$`qZ86ipntH8G~51qIlsYQ)+2_Fg1@Y-ztI#aa~tFD_QUxb zU-?g5B}wU@`tnc_l+B^mRogRghXs!7JZS=A;In1|f(1T(+xfIi zvjccLF$`Pkv2w|c5BkSj>>k%`4o6#?ygojkV78%zzz`QFE6nh{(SSJ9NzVdq>^N>X zpg6+8u7i(S>c*i*cO}poo7c9%i^1o&3HmjY!s8Y$5aO(!>u1>-eai0;rK8hVzIh8b zL53WCXO3;=F4_%CxMKRN^;ggC$;YGFTtHtLmX%@MuMxvgn>396~ zEp>V(dbfYjBX^!8CSg>P2c5I~HItbe(dl^Ax#_ldvCh;D+g6-%WD|$@S6}Fvv*eHc zaKxji+OG|_KyMe2D*fhP<3VP0J1gTgs6JZjE{gZ{SO-ryEhh;W237Q0 z{yrDobsM6S`bPMUzr|lT|99m6XDI$RzW4tQ$|@C2RjhBYPliEXFV#M*5G4;Kb|J8E z0IH}-d^S-53kFRZ)ZFrd2%~Sth-6BN?hnMa_PC4gdWyW3q-xFw&L^x>j<^^S$y_3_ zdZxouw%6;^mg#jG@7L!g9Kdw}{w^X9>TOtHgxLLIbfEG^Qf;tD=AXozE6I`XmOF=# zGt$Wl+7L<8^VI-eSK%F%dqXieK^b!Z3yEA$KL}X@>fD9)g@=DGt|=d(9W%8@Y@!{PI@`Nd zyF?Us(0z{*u6|X?D`kKSa}}Q*HP%9BtDEA^buTlI5ihwe)CR%OR46b+>NakH3SDbZmB2X>c8na&$lk zYg$SzY+EXtq2~$Ep_x<~+YVl<-F&_fbayzTnf<7?Y-un3#+T~ahT+eW!l83sofNt; zZY`eKrGqOux)+RMLgGgsJdcA3I$!#zy!f<$zL0udm*?M5w=h$Boj*RUk8mDPVUC1RC8A`@7PgoBIU+xjB7 z25vky+^7k_|1n1&jKNZkBWUu1VCmS}a|6_+*;fdUZAaIR4G!wv=bAZEXBhcjch6WH zdKUr&>z^P%_LIx*M&x{!w|gij?nigT8)Ol3VicXRL0tU}{vp2fi!;QkVc#I38op3O z=q#WtNdN{x)OzmH;)j{cor)DQ;2%m>xMu_KmTisaeCC@~rQwQTfMml7FZ_ zU2AR8yCY_CT$&IAn3n#Acf*VKzJD8-aphMg(12O9cv^AvLQ9>;f!4mjyxq_a%YH2+{~=3TMNE1 z#r3@ynnZ#p?RCkPK36?o{ILiHq^N5`si(T_cKvO9r3^4pKG0AgDEB@_72(2rvU^-; z%&@st2+HjP%H)u50t81p>(McL{`dTq6u-{JM|d=G1&h-mtjc2{W0%*xuZVlJpUSP-1=U6@5Q#g(|nTVN0icr-sdD~DWR=s}`$#=Wa zt5?|$`5`=TWZevaY9J9fV#Wh~Fw@G~0vP?V#Pd=|nMpSmA>bs`j2e{)(827mU7rxM zJ@ku%Xqhq!H)It~yXm=)6XaPk=$Rpk*4i4*aSBZe+h*M%w6?3&0>>|>GHL>^e4zR!o%aGzUn40SR+TdN%=Dbn zsRfXzGcH#vjc-}7v6yRhl{V5PhE-r~)dnmNz=sDt?*1knNZ>xI5&vBwrosF#qRL-Y z;{W)4W&cO0XMKy?{^d`Xh(2B?j0ioji~G~p5NQJyD6vouyoFE9w@_R#SGZ1DR4GnN z{b=sJ^8>2mq3W;*u2HeCaKiCzK+yD!^i6QhTU5npwO+C~A#5spF?;iuOE>o&p3m1C zmT$_fH8v+5u^~q^ic#pQN_VYvU>6iv$tqx#Sulc%|S7f zshYrWq7IXCiGd~J(^5B1nGMV$)lo6FCTm1LshfcOrGc?HW7g>pV%#4lFbnt#94&Rg{%Zbg;Rh?deMeOP(du*)HryI zCdhO$3|SeaWK<>(jSi%qst${Z(q@{cYz7NA^QO}eZ$K@%YQ^Dt4CXzmvx~lLG{ef8 zyckIVSufk>9^e_O7*w2z>Q$8me4T~NQDq=&F}Ogo#v1u$0xJV~>YS%mLVYqEf~g*j zGkY#anOI9{(f4^v21OvYG<(u}UM!-k;ziH%GOVU1`$0VuO@Uw2N{$7&5MYjTE?Er) zr?oZAc~Xc==KZx-pmoh9KiF_JKU7u0#b_}!dWgC>^fmbVOjuiP2FMq5OD9+4TKg^2 z>y6s|sQhI`=fC<>BnQYV433-b+jBi+N6unz%6EQR%{8L#=4sktI>*3KhX+qAS>+K#}y5KnJ8YuOuzG(Ea5;$*1P$-9Z+V4guyJ#s) zRPH(JPN;Es;H72%c8}(U)CEN}Xm>HMn{n!d(=r*YP0qo*^APwwU5YTTeHKy#85Xj< zEboiH=$~uIVMPg!qbx~0S=g&LZ*IyTJG$hTN zv%2>XF``@S9lnLPC?|myt#P)%7?%e_j*aU4TbTyxO|3!h%=Udp;THL+^oPp<6;TLlIOa$&xeTG_a*dbRDy+(&n1T=MU z+|G5{2UprrhN^AqODLo$9Z2h(3^wtdVIoSk@}wPajVgIoZipRft}^L)2Y@mu;X-F{LUw|s7AQD-0!otW#W9M@A~08`o%W;Bq-SOQavG*e-sy8) zwtaucR0+64B&Pm++-m56MQ$@+t{_)7l-|`1kT~1s!swfc4D9chbawUt`RUOdoxU|j z$NE$4{Ysr@2Qu|K8pD37Yv&}>{_I5N49a@0<@rGHEs}t zwh_+9T0oh@ptMbjy*kbz<&3>LGR-GNsT8{x1g{!S&V7{5tPYX(GF>6qZh>O&F)%_I zkPE-pYo3dayjNQAG+xrI&yMZy590FA1unQ*k*Zfm#f9Z5GljOHBj-B83KNIP1a?<^1vOhDJkma0o- zs(TP=@e&s6fRrU(R}{7eHL*(AElZ&80>9;wqj{|1YQG=o2Le-m!UzUd?Xrn&qd8SJ0mmEYtW;t(;ncW_j6 zGWh4y|KMK^s+=p#%fWxjXo434N`MY<8W`tNH-aM6x{@o?D3GZM&+6t4V3I*3fZd{a z0&D}DI?AQl{W*?|*%M^D5{E>V%;=-r&uQ>*e)cqVY52|F{ptA*`!iS=VKS6y4iRP6 zKUA!qpElT5vZvN}U5k-IpeNOr6KF`-)lN1r^c@HnT#RlZbi(;yuvm9t-Noh5AfRxL@j5dU-X37(?S)hZhRDbf5cbhDO5nSX@WtApyp` zT$5IZ*4*)h8wShkPI45stQH2Y7yD*CX^Dh@B%1MJSEn@++D$AV^ttKXZdQMU`rxiR z+M#45Z2+{N#uR-hhS&HAMFK@lYBWOzU^Xs-BlqQDyN4HwRtP2$kks@UhAr@wlJii%Rq?qy25?Egs z*a&iAr^rbJWlv+pYAVUq9lor}#Cm|D$_ev2d2Ko}`8kuP(ljz$nv3OCDc7zQp|j6W zbS6949zRvj`bhbO(LN3}Pq=$Ld3a_*9r_24u_n)1)}-gRq?I6pdHPYHgIsn$#XQi~ z%&m_&nnO9BKy;G%e~fa7i9WH#MEDNQ8WCXhqqI+oeE5R7hLZT_?7RWVzEGZNz4*Po ze&*a<^Q*ze72}UM&$c%FuuEIN?EQ@mnILwyt;%wV-MV+|d%>=;3f0(P46;Hwo|Wr0 z>&FS9CCb{?+lDpJMs`95)C$oOQ}BSQEv0Dor%-Qj0@kqlIAm1-qSY3FCO2j$br7_w zlpRfAWz3>Gh~5`Uh?ER?@?r0cXjD0WnTx6^AOFii;oqM?|M9QjHd*GK3WwA}``?dK15`ZvG>_nB2pSTGc{n2hYT6QF^+&;(0c`{)*u*X7L_ zaxqyvVm$^VX!0YdpSNS~reC+(uRqF2o>jqIJQkC&X>r8|mBHvLaduM^Mh|OI60<;G zDHx@&jUfV>cYj5+fAqvv(XSmc(nd@WhIDvpj~C#jhZ6@M3cWF2HywB1yJv2#=qoY| zIiaxLsSQa7w;4YE?7y&U&e6Yp+2m(sb5q4AZkKtey{904rT08pJpanm->Z75IdvW^ z!kVBy|CIUZn)G}92_MgoLgHa?LZJDp_JTbAEq8>6a2&uKPF&G!;?xQ*+{TmNB1H)_ z-~m@CTxDry_-rOM2xwJg{fcZ41YQDh{DeI$4!m8c;6XtFkFyf`fOsREJ`q+Bf4nS~ zKDYs4AE7Gugv?X)tu4<-M8ag{`4pfQ14z<(8MYQ4u*fl*DCpq66+Q1-gxNCQ!c$me zyTrmi7{W-MGP!&S-_qJ%9+e08_9`wWGG{i5yLJ;8qbt-n_0*Q371<^u@tdz|;>fPW zE=&q~;wVD_4IQ^^jyYX;2shIMiYdvIpIYRT>&I@^{kL9Ka2ECG>^l>Ae!GTn{r~o= z|I9=J#wNe)zYRqGZ7Q->L{dfewyC$ZYcLaoNormZ3*gfM=da*{heC)&46{yTS!t10 zn_o0qUbQOs$>YuY>YHi|NG^NQG<_@jD&WnZcW^NTC#mhVE7rXlZ=2>mZkx{bc=~+2 z{zVH=Xs0`*K9QAgq9cOtfQ^BHh-yr=qX8hmW*0~uCup89IJMvWy%#yt_nz@6dTS)L{O3vXye< zW4zUNb6d|Tx`XIVwMMgqnyk?c;Kv`#%F0m^<$9X!@}rI##T{iXFC?(ui{;>_9Din8 z7;(754q!Jx(~sb!6+6Lf*l{fqD7GW*v{>3wp+)@wq2abADBK!kI8To}7zooF%}g-z zJ1-1lp-lQI6w^bov9EfhpxRI}`$PTpJI3uo@ZAV729JJ2Hs68{r$C0U=!d$Bm+s(p z8Kgc(Ixf4KrN%_jjJjTx5`&`Ak*Il%!}D_V)GM1WF!k$rDJ-SudXd_Xhl#NWnET&e-P!rH~*nNZTzxj$?^oo3VWc-Ay^`Phze3(Ft!aNW-f_ zeMy&BfNCP^-FvFzR&rh!w(pP5;z1$MsY9Voozmpa&A}>|a{eu}>^2s)So>&kmi#7$ zJS_-DVT3Yi(z+ruKbffNu`c}s`Uo`ORtNpUHa6Q&@a%I%I;lm@ea+IbCLK)IQ~)JY zp`kdQ>R#J*i&Ljer3uz$m2&Un9?W=Ue|hHv?xlM`I&*-M;2{@so--0OAiraN1TLra z>EYQu#)Q@UszfJj&?kr%RraFyi*eG+HD_(!AWB;hPgB5Gd-#VDRxxv*VWMY0hI|t- zR=;TL%EKEg*oet7GtmkM zgH^y*1bfJ*af(_*S1^PWqBVVbejFU&#m`_69IwO!aRW>Rcp~+7w^ptyu>}WFYUf;) zZrgs;EIN9$Immu`$umY%$I)5INSb}aV-GDmPp!d_g_>Ar(^GcOY%2M)Vd7gY9llJR zLGm*MY+qLzQ+(Whs8-=ty2l)G9#82H*7!eo|B6B$q%ak6eCN%j?{SI9|K$u3)ORoz zw{bAGaWHrMb|X^!UL~_J{jO?l^}lI^|7jIn^p{n%JUq9{tC|{GM5Az3SrrPkuCt_W zq#u0JfDw{`wAq`tAJmq~sz`D_P-8qr>kmms>I|);7Tn zLl^n*Ga7l=U)bQmgnSo5r_&#Pc=eXm~W75X9Cyy0WDO|fbSn5 zLgpFAF4fa90T-KyR4%%iOq6$6BNs@3ZV<~B;7V=u zdlB8$lpe`w-LoS;0NXFFu@;^^bc?t@r3^XTe*+0;o2dt&>eMQeDit(SfDxYxuA$uS z**)HYK7j!vJVRNfrcokVc@&(ke5kJzvi};Lyl7@$!`~HM$T!`O`~MQ1k~ZH??fQr zNP)33uBWYnTntKRUT*5lu&8*{fv>syNgxVzEa=qcKQ86Vem%Lpae2LM=TvcJLs?`=o9%5Mh#k*_7zQD|U7;A%=xo^_4+nX{~b1NJ6@ z*=55;+!BIj1nI+)TA$fv-OvydVQB=KK zrGWLUS_Chm$&yoljugU=PLudtJ2+tM(xj|E>Nk?c{-RD$sGYNyE|i%yw>9gPItE{ zD|BS=M>V^#m8r?-3swQofD8j$h-xkg=F+KM%IvcnIvc)y zl?R%u48Jeq7E*26fqtLe_b=9NC_z|axW#$e0adI#r(Zsui)txQ&!}`;;Z%q?y2Kn! zXzFNe+g7+>>`9S0K1rmd)B_QVMD?syc3e0)X*y6(RYH#AEM9u?V^E0GHlAAR)E^4- zjKD+0K=JKtf5DxqXSQ!j?#2^ZcQoG5^^T+JaJa3GdFeqIkm&)dj76WaqGukR-*&`13ls8lU2ayVIR%;79HYAr5aEhtYa&0}l}eAw~qKjUyz4v*At z?})QplY`3cWB6rl7MI5mZx&#%I0^iJm3;+J9?RA(!JXjl?(XgmA-D#2cY-^?g1c*Q z3GVLh!8Jhe;QqecbMK#XIJxKMb=6dcs?1vbb?@ov-raj`hnYO92y8pv@>RVr=9Y-F zv`BK)9R6!m4Pfllu4uy0WBL+ZaUFFzbZZtI@J8{OoQ^wL-b$!FpGT)jYS-=vf~b-@ zIiWs7j~U2yI=G5;okQz%gh6}tckV5wN;QDbnu|5%%I(#)8Q#)wTq8YYt$#f9=id;D zJbC=CaLUyDIPNOiDcV9+=|$LE9v2;Qz;?L+lG{|g&iW9TI1k2_H;WmGH6L4tN1WL+ zYfSVWq(Z_~u~U=g!RkS|YYlWpKfZV!X%(^I3gpV%HZ_{QglPSy0q8V+WCC2opX&d@eG2BB#(5*H!JlUzl$DayI5_J-n zF@q*Fc-nlp%Yt;$A$i4CJ_N8vyM5fNN`N(CN53^f?rtya=p^MJem>JF2BEG|lW|E) zxf)|L|H3Oh7mo=9?P|Y~|6K`B3>T)Gw`0ESP9R`yKv}g|+qux(nPnU(kQ&&x_JcYg9+6`=; z-EI_wS~l{T3K~8}8K>%Ke`PY!kNt415_x?^3QOvX(QUpW&$LXKdeZM-pCI#%EZ@ta zv(q-(xXIwvV-6~(Jic?8<7ain4itN>7#AqKsR2y(MHMPeL)+f+v9o8Nu~p4ve*!d3 z{Lg*NRTZsi;!{QJknvtI&QtQM_9Cu%1QcD0f!Fz+UH4O#8=hvzS+^(e{iG|Kt7C#u zKYk7{LFc+9Il>d6)blAY-9nMd(Ff0;AKUo3B0_^J&ESV@4UP8PO0no7G6Gp_;Z;YnzW4T-mCE6ZfBy(Y zXOq^Of&?3#Ra?khzc7IJT3!%IKK8P(N$ST47Mr=Gv@4c!>?dQ-&uZihAL1R<_(#T8Y`Ih~soL6fi_hQmI%IJ5qN995<{<@_ z;^N8AGQE+?7#W~6X>p|t<4@aYC$-9R^}&&pLo+%Ykeo46-*Yc(%9>X>eZpb8(_p{6 zwZzYvbi%^F@)-}5%d_z^;sRDhjqIRVL3U3yK0{Q|6z!PxGp?|>!%i(!aQODnKUHsk^tpeB<0Qt7`ZBlzRIxZMWR+|+ z3A}zyRZ%0Ck~SNNov~mN{#niO**=qc(faGz`qM16H+s;Uf`OD1{?LlH!K!+&5xO%6 z5J80-41C{6)j8`nFvDaeSaCu_f`lB z_Y+|LdJX=YYhYP32M556^^Z9MU}ybL6NL15ZTV?kfCFfpt*Pw5FpHp#2|ccrz#zoO zhs=+jQI4fk*H0CpG?{fpaSCmXzU8bB`;kCLB8T{_3t>H&DWj0q0b9B+f$WG=e*89l zzUE)b9a#aWsEpgnJqjVQETpp~R7gn)CZd$1B8=F*tl+(iPH@s9jQtE33$dBDOOr=% ziOpR8R|1eLI?Rn*d+^;_U#d%bi$|#obe0(-HdB;K>=Y=mg{~jTA_WpChe8QquhF`N z>hJ}uV+pH`l_@d>%^KQNm*$QNJ(lufH>zv9M`f+C-y*;hAH(=h;kp@eL=qPBeXrAo zE7my75EYlFB30h9sdt*Poc9)2sNP9@K&4O7QVPQ^m$e>lqzz)IFJWpYrpJs)Fcq|P z5^(gnntu!+oujqGpqgY_o0V&HL72uOF#13i+ngg*YvPcqpk)Hoecl$dx>C4JE4DWp z-V%>N7P-}xWv%9Z73nn|6~^?w$5`V^xSQbZceV<_UMM&ijOoe{Y^<@3mLSq_alz8t zr>hXX;zTs&k*igKAen1t1{pj94zFB;AcqFwV)j#Q#Y8>hYF_&AZ?*ar1u%((E2EfZ zcRsy@s%C0({v=?8oP=DML`QsPgzw3|9|C22Y>;=|=LHSm7~+wQyI|;^WLG0_NSfrf zamq!5%EzdQ&6|aTP2>X=Z^Jl=w6VHEZ@=}n+@yeu^ke2Yurrkg9up3g$0SI8_O-WQu$bCsKc(juv|H;vz6}%7ONww zKF%!83W6zO%0X(1c#BM}2l^ddrAu^*`9g&1>P6m%x{gYRB)}U`40r>6YmWSH(|6Ic zH~QNgxlH*;4jHg;tJiKia;`$n_F9L~M{GiYW*sPmMq(s^OPOKm^sYbBK(BB9dOY`0 z{0!=03qe*Sf`rcp5Co=~pfQyqx|umPHj?a6;PUnO>EZGb!pE(YJgNr{j;s2+nNV(K zDi#@IJ|To~Zw)vqGnFwb2}7a2j%YNYxe2qxLk)VWJIux$BC^oII=xv-_}h@)Vkrg1kpKokCmX({u=lSR|u znu_fA0PhezjAW{#Gu0Mdhe8F4`!0K|lEy+<1v;$ijSP~A9w%q5-4Ft|(l7UqdtKao zs|6~~nmNYS>fc?Nc=yzcvWNp~B0sB5ForO5SsN(z=0uXxl&DQsg|Y?(zS)T|X``&8 z*|^p?~S!vk8 zg>$B{oW}%rYkgXepmz;iqCKY{R@%@1rcjuCt}%Mia@d8Vz5D@LOSCbM{%JU#cmIp! z^{4a<3m%-p@JZ~qg)Szb-S)k{jv92lqB(C&KL(jr?+#ES5=pUH$(;CO9#RvDdErmW z3(|f{_)dcmF-p*D%qUa^yYngNP&Dh2gq5hr4J!B5IrJ?ODsw@*!0p6Fm|(ebRT%l) z#)l22@;4b9RDHl1ys$M2qFc;4BCG-lp2CN?Ob~Be^2wQJ+#Yz}LP#8fmtR%o7DYzoo1%4g4D+=HonK7b!3nvL0f1=oQp93dPMTsrjZRI)HX-T}ApZ%B#B;`s? z9Kng{|G?yw7rxo(T<* z1+O`)GNRmXq3uc(4SLX?fPG{w*}xDCn=iYo2+;5~vhWUV#e5e=Yfn4BoS@3SrrvV9 zrM-dPU;%~+3&>(f3sr$Rcf4>@nUGG*vZ~qnxJznDz0irB(wcgtyATPd&gSuX^QK@+ z)7MGgxj!RZkRnMSS&ypR94FC$;_>?8*{Q110XDZ)L);&SA8n>72s1#?6gL>gydPs` zM4;ert4-PBGB@5E` zBaWT=CJUEYV^kV%@M#3(E8>g8Eg|PXg`D`;K8(u{?}W`23?JgtNcXkUxrH}@H_4qN zw_Pr@g%;CKkgP(`CG6VTIS4ZZ`C22{LO{tGi6+uPvvHkBFK|S6WO{zo1MeK$P zUBe}-)3d{55lM}mDVoU@oGtPQ+a<=wwDol}o=o1z*)-~N!6t09du$t~%MlhM9B5~r zy|zs^LmEF#yWpXZq!+Nt{M;bE%Q8z7L8QJDLie^5MKW|I1jo}p)YW(S#oLf(sWn~* zII>pocNM5#Z+-n2|495>?H?*oyr0!SJIl(}q-?r`Q;Jbqqr4*_G8I7agO298VUr9x z8ZcHdCMSK)ZO@Yr@c0P3{`#GVVdZ{zZ$WTO zuvO4ukug&& ze#AopTVY3$B>c3p8z^Yyo8eJ+(@FqyDWlR;uxy0JnSe`gevLF`+ZN6OltYr>oN(ZV z>76nIiVoll$rDNkck6_eh%po^u16tD)JXcii|#Nn(7=R9mA45jz>v}S%DeMc(%1h> zoT2BlF9OQ080gInWJ3)bO9j$ z`h6OqF0NL4D3Kz?PkE8nh;oxWqz?<3_!TlN_%qy*T7soZ>Pqik?hWWuya>T$55#G9 zxJv=G&=Tm4!|p1#!!hsf*uQe}zWTKJg`hkuj?ADST2MX6fl_HIDL7w`5Dw1Btays1 zz*aRwd&>4*H%Ji2bt-IQE$>sbCcI1Poble0wL`LAhedGRZp>%>X6J?>2F*j>`BX|P zMiO%!VFtr_OV!eodgp-WgcA-S=kMQ^zihVAZc!vdx*YikuDyZdHlpy@Y3i!r%JI85$-udM6|7*?VnJ!R)3Qfm4mMm~Z#cvNrGUy|i0u zb|(7WsYawjBK0u1>@lLhMn}@X>gyDlx|SMXQo|yzkg-!wIcqfGrA!|t<3NC2k` zq;po50dzvvHD>_mG~>W0iecTf@3-)<$PM5W@^yMcu@U;)(^eu@e4jAX7~6@XrSbIE zVG6v2miWY^g8bu5YH$c2QDdLkg2pU8xHnh`EUNT+g->Q8Tp4arax&1$?CH($1W&*} zW&)FQ>k5aCim$`Ph<9Zt?=%|pz&EX@_@$;3lQT~+;EoD(ho|^nSZDh*M0Z&&@9T+e zHYJ;xB*~UcF^*7a_T)9iV5}VTYKda8n*~PSy@>h7c(mH~2AH@qz{LMQCb+-enMhX} z2k0B1JQ+6`?Q3Lx&(*CBQOnLBcq;%&Nf<*$CX2<`8MS9c5zA!QEbUz1;|(Ua%CiuL zF2TZ>@t7NKQ->O#!;0s;`tf$veXYgq^SgG>2iU9tCm5&^&B_aXA{+fqKVQ*S9=58y zddWqy1lc$Y@VdB?E~_B5w#so`r552qhPR649;@bf63_V@wgb!>=ij=%ptnsq&zl8^ zQ|U^aWCRR3TnoKxj0m0QL2QHM%_LNJ(%x6aK?IGlO=TUoS%7YRcY{!j(oPcUq{HP=eR1>0o^(KFl-}WdxGRjsT);K8sGCkK0qVe{xI`# z@f+_kTYmLbOTxRv@wm2TNBKrl+&B>=VaZbc(H`WWLQhT=5rPtHf)#B$Q6m1f8We^)f6ylbO=t?6Y;{?&VL|j$VXyGV!v8eceRk zl>yOWPbk%^wv1t63Zd8X^Ck#12$*|yv`v{OA@2;-5Mj5sk#ptfzeX(PrCaFgn{3*hau`-a+nZhuJxO;Tis51VVeKAwFML#hF9g26NjfzLs8~RiM_MFl1mgDOU z=ywk!Qocatj1Q1yPNB|FW>!dwh=aJxgb~P%%7(Uydq&aSyi?&b@QCBiA8aP%!nY@c z&R|AF@8}p7o`&~>xq9C&X6%!FAsK8gGhnZ$TY06$7_s%r*o;3Y7?CenJUXo#V-Oag z)T$d-V-_O;H)VzTM&v8^Uk7hmR8v0)fMquWHs6?jXYl^pdM#dY?T5XpX z*J&pnyJ<^n-d<0@wm|)2SW9e73u8IvTbRx?Gqfy_$*LI_Ir9NZt#(2T+?^AorOv$j zcsk+t<#!Z!eC|>!x&#l%**sSAX~vFU0|S<;-ei}&j}BQ#ekRB-;c9~vPDIdL5r{~O zMiO3g0&m-O^gB}<$S#lCRxX@c3g}Yv*l)Hh+S^my28*fGImrl<-nbEpOw-BZ;WTHL zgHoq&ftG|~ouV<>grxRO6Z%{!O+j`Cw_4~BIzrjpkdA5jH40{1kDy|pEq#7`$^m*? zX@HxvW`e}$O$mJvm+65Oc4j7W@iVe)rF&-}R>KKz>rF&*Qi3%F0*tz!vNtl@m8L9= zyW3%|X}0KsW&!W<@tRNM-R>~~QHz?__kgnA(G`jWOMiEaFjLzCdRrqzKlP1vYLG`Y zh6_knD3=9$weMn4tBD|5=3a9{sOowXHu(z5y^RYrxJK z|L>TUvbDuO?3=YJ55N5}Kj0lC(PI*Te0>%eLNWLnawD54geX5>8AT(oT6dmAacj>o zC`Bgj-RV0m3Dl2N=w3e0>wWWG5!mcal`Xu<(1=2$b{k(;kC(2~+B}a(w;xaHPk^@V zGzDR|pt%?(1xwNxV!O6`JLCM!MnvpbLoHzKziegT_2LLWAi4}UHIo6uegj#WTQLet z9Dbjyr{8NAk+$(YCw~_@Az9N|iqsliRYtR7Q|#ONIV|BZ7VKcW$phH9`ZAlnMTW&9 zIBqXYuv*YY?g*cJRb(bXG}ts-t0*|HXId4fpnI>$9A?+BTy*FG8f8iRRKYRd*VF_$ zoo$qc+A(d#Lx0@`ck>tt5c$L1y7MWohMnZd$HX++I9sHoj5VXZRZkrq`v@t?dfvC} z>0h!c4HSb8%DyeF#zeU@rJL2uhZ^8dt(s+7FNHJeY!TZJtyViS>a$~XoPOhHsdRH* zwW+S*rIgW0qSPzE6w`P$Jv^5dsyT6zoby;@z=^yWLG^x;e557RnndY>ph!qCF;ov$ ztSW1h3@x{zm*IMRx|3lRWeI3znjpbS-0*IL4LwwkWyPF1CRpQK|s42dJ{ddA#BDDqio-Y+mF-XcP-z4bi zAhfXa2=>F0*b;F0ftEPm&O+exD~=W^qjtv&>|%(4q#H=wbA>7QorDK4X3~bqeeXv3 zV1Q<>_Fyo!$)fD`fd@(7(%6o-^x?&+s=)jjbQ2^XpgyYq6`}ISX#B?{I$a&cRcW?X zhx(i&HWq{=8pxlA2w~7521v-~lu1M>4wL~hDA-j(F2;9ICMg+6;Zx2G)ulp7j;^O_ zQJIRUWQam(*@?bYiRTKR<;l_Is^*frjr-Dj3(fuZtK{Sn8F;d*t*t{|_lnlJ#e=hx zT9?&_n?__2mN5CRQ}B1*w-2Ix_=CF@SdX-cPjdJN+u4d-N4ir*AJn&S(jCpTxiAms zzI5v(&#_#YrKR?B?d~ge1j*g<2yI1kp`Lx>8Qb;aq1$HOX4cpuN{2ti!2dXF#`AG{ zp<iD=Z#qN-yEwLwE7%8w8&LB<&6{WO$#MB-|?aEc@S1a zt%_p3OA|kE&Hs47Y8`bdbt_ua{-L??&}uW zmwE7X4Y%A2wp-WFYPP_F5uw^?&f zH%NCcbw_LKx!c!bMyOBrHDK1Wzzc5n7A7C)QrTj_Go#Kz7%+y^nONjnnM1o5Sw(0n zxU&@41(?-faq?qC^kO&H301%|F9U-Qm(EGd3}MYTFdO+SY8%fCMTPMU3}bY7ML1e8 zrdOF?E~1uT)v?UX(XUlEIUg3*UzuT^g@QAxEkMb#N#q0*;r zF6ACHP{ML*{Q{M;+^4I#5bh#c)xDGaIqWc#ka=0fh*_Hlu%wt1rBv$B z%80@8%MhIwa0Zw$1`D;Uj1Bq`lsdI^g_18yZ9XUz2-u6&{?Syd zHGEh-3~HH-vO<)_2^r|&$(q7wG{@Q~un=3)Nm``&2T99L(P+|aFtu1sTy+|gwL*{z z)WoC4rsxoWhz0H$rG|EwhDT z0zcOAod_k_Ql&Y`YV!#&Mjq{2ln|;LMuF$-G#jX_2~oNioTHb4GqFatn@?_KgsA7T z(ouy$cGKa!m}6$=C1Wmb;*O2p*@g?wi-}X`v|QA4bNDU*4(y8*jZy-Ku)S3iBN(0r ztfLyPLfEPqj6EV}xope=?b0Nyf*~vDz-H-Te@B`{ib?~F<*(MmG+8zoYS77$O*3vayg#1kkKN+Bu9J9;Soev<%2S&J zr8*_PKV4|?RVfb#SfNQ;TZC$8*9~@GR%xFl1 z3MD?%`1PxxupvVO>2w#8*zV<-!m&Lis&B>)pHahPQ@I_;rY~Z$1+!4V1jde&L8y0! zha7@F+rOENF{~0$+a~oId0R|_!PhO=8)$>LcO)ca6YeOQs?ZG;`4O`x=Pd??Bl?Qf zgkaNj7X5@3_==zlQ-u6?omteA!_e-6gfDtw6CBnP2o1wo-7U!Y@89rU1HFb|bIr!I z=qIz=AW(}L^m z=I9RiS{DRtTYS6jsnvt1zs)W;kSVFOK|WMyZ@dxs+8{*W9-aTmS79J4R{Cis>EIqS zw+~gJqwz)(!z>)KDyhS{lM*xQ-8mNvo$A=IwGu+iS564tgX`|MeEuis!aN-=7!L&e zhNs;g1MBqDyx{y@AI&{_)+-?EEg|5C*!=OgD#$>HklRVU+R``HYZZq5{F9C0KKo!d z$bE2XC(G=I^YUxYST+Hk>0T;JP_iAvCObcrPV1Eau865w6d^Wh&B?^#h2@J#!M2xp zLGAxB^i}4D2^?RayxFqBgnZ-t`j+~zVqr+9Cz9Rqe%1a)c*keP#r54AaR2*TH^}7j zmJ48DN);^{7+5|+GmbvY2v#qJy>?$B(lRlS#kyodlxA&Qj#9-y4s&|eq$5} zgI;4u$cZWKWj`VU%UY#SH2M$8?PjO-B-rNPMr=8d=-D(iLW#{RWJ}@5#Z#EK=2(&LvfW&{P4_jsDr^^rg9w#B7h`mBwdL9y)Ni;= zd$jFDxnW7n-&ptjnk#<0zmNNt{;_30vbQW!5CQ7SuEjR1be!vxvO53!30iOermrU1 zXhXaen8=4Q(574KO_h$e$^1khO&tQL59=)Dc^8iPxz8+tC3`G$w|yUzkGd%Wg4(3u zJ<&7r^HAaEfG?F8?2I64j4kPpsNQk7qBJa9_hFT;*j;A%H%;QI@QWqJaiOl=;u>G8 zG`5Ow4K5ifd=OS|7F;EFc1+GzLld0RCQxG>Fn?~5Wl5VHJ=$DeR-2zwBgzSrQsGG0 zBqrILuB+_SgLxh~S~^QNHWW(2P;Z?d!Rd1lnEM=z23xPzyrbO_L0k43zruDkrJO*D zlzN(peBMLji`xfgYUirul-7c#3t(*=x6A^KSU-L|$(0pp9A*43#=Q!cu%9ZHP!$J| zSk8k=Z8cl811Vvn(4p8xx+EdKQV(sjC4_mEvlWeuIfwEVcF2LiC{H!oW)LSW=0ul| zT?$5PCc(pf-zKzUH`p7I7coVvCK;Dv-3_c?%~bPz`#ehbfrSrFf{RAz0I5e*W1S)kTW{0gf5X2v2k=S=W{>pr44tQ?o` zih8gE29VGR_SL~YJtcA)lRLozPg!<3Mh(`Hp)5{bclb)reTScXzJ>7{?i^yR@{(^% z#=$BYXPIX%fhgsofP-T`3b<5#V(TTS)^$vlhV&Kn=(LXOTAADIR1v8UqmW5c`n`S% zC8SOW$e?>&0dwKD%Jt{+67PfCLnqX0{8K^(q_^^2#puPYPkJsyXWMa~?V?p5{flYi z-1!uqI2x%puPG)r7b8y+Pc0Z5C%aA6`Q1_?W9k!YbiVVJVJwGLL?)P0M&vo{^IgEE zrX3eTgrJl_AeXYmiciYX9OP?NPN%-7Ji%z3U`-iXX=T~OI0M=ek|5IvIsvXM$%S&v zKw{`Kj(JVc+Pp^?vLKEyoycfnk)Hd>et78P^Z*{#rBY~_>V7>{gtB$0G99nbNBt+r zyXvEg_2=#jjK+YX1A>cj5NsFz9rjB_LB%hhx4-2I73gr~CW_5pD=H|e`?#CQ2)p4& z^v?Dlxm-_j6bO5~eeYFZGjW3@AGkIxY=XB*{*ciH#mjQ`dgppNk4&AbaRYKKY-1CT z>)>?+ME)AcCM7RRZQsH5)db7y!&jY-qHp%Ex9N|wKbN$!86i>_LzaD=f4JFc6Dp(a z%z>%=q(sXlJ=w$y^|tcTy@j%AP`v1n0oAt&XC|1kA`|#jsW(gwI0vi3a_QtKcL+yh z1Y=`IRzhiUvKeZXH6>>TDej)?t_V8Z7;WrZ_7@?Z=HRhtXY+{hlY?x|;7=1L($?t3 z6R$8cmez~LXopZ^mH9=^tEeAhJV!rGGOK@sN_Zc-vmEr;=&?OBEN)8aI4G&g&gdOb zfRLZ~dVk3194pd;=W|Z*R|t{}Evk&jw?JzVERk%JNBXbMDX82q~|bv%!2%wFP9;~-H?={C1sZ( zuDvY5?M8gGX*DyN?nru)UvdL|Rr&mXzgZ;H<^KYvzIlet!aeFM@I?JduKj=!(+ zM7`37KYhd*^MrKID^Y1}*sZ#6akDBJyKna%xK%vLlBqzDxjQ3}jx8PBOmXkvf@B{@ zc#J;~wQ<6{B;``j+B!#7s$zONYdXunbuKvl@zvaWq;`v2&iCNF2=V9Kl|77-mpCp= z2$SxhcN=pZ?V{GW;t6s)?-cNPAyTi&8O0QMGo#DcdRl#+px!h3ayc*(VOGR95*Anj zL0YaiVN2mifzZ){X+fl`Z^P=_(W@=*cIe~BJd&n@HD@;lRmu8cx7K8}wPbIK)GjF> zQGQ2h#21o6b2FZI1sPl}9_(~R|2lE^h}UyM5A0bJQk2~Vj*O)l-4WC4$KZ>nVZS|d zZv?`~2{uPYkc?254B9**q6tS|>We?uJ&wK3KIww|zzSuj>ncI4D~K z1Y6irVFE{?D-|R{!rLhZxAhs+Ka9*-(ltIUgC;snNek4_5xhO}@+r9Sl*5=7ztnXO zAVZLm$Kdh&rqEtdxxrE9hw`aXW1&sTE%aJ%3VL3*<7oWyz|--A^qvV3!FHBu9B-Jj z4itF)3dufc&2%V_pZsjUnN=;s2B9<^Zc83>tzo)a_Q$!B9jTjS->%_h`ZtQPz@{@z z5xg~s*cz`Tj!ls3-hxgnX}LDGQp$t7#d3E}>HtLa12z&06$xEQfu#k=(4h{+p%aCg zzeudlLc$=MVT+|43#CXUtRR%h5nMchy}EJ;n7oHfTq6wN6PoalAy+S~2l}wK;qg9o zcf#dX>ke;z^13l%bwm4tZcU1RTXnDhf$K3q-cK576+TCwgHl&?9w>>_(1Gxt@jXln zt3-Qxo3ITr&sw1wP%}B>J$Jy>^-SpO#3e=7iZrXCa2!N69GDlD{97|S*og)3hG)Lk zuqxK|PkkhxV$FP45%z*1Z?(LVy+ruMkZx|(@1R(0CoS6`7FWfr4-diailmq&Q#ehn zc)b&*&Ub;7HRtFVjL%((d$)M=^6BV@Kiusmnr1_2&&aEGBpbK7OWs;+(`tRLF8x?n zfKJB3tB^F~N`_ak3^exe_3{=aP)3tuuK2a-IriHcWv&+u7p z_yXsd6kyLV@k=(QoSs=NRiKNYZ>%4wAF;2#iu1p^!6>MZUPd;=2LY~l2ydrx10b#OSAlltILY%OKTp{e{ zzNogSk~SJBqi<_wRa#JqBW8Ok=6vb%?#H(hG}Dv98{JST5^SSh>_GQ@UK-0J`6l#E za}X#ud0W?cp-NQE@jAx>NUv65U~%YYS%BC0Cr$5|2_A)0tW;(nqoGJUHG5R`!-{1M-4T{<^pOE!Dvyuu1x7?Wt#YIgq zA$Vwj`St+M#ZxJXXGkepIF6`xL&XPu^qiFlZcX+@fOAdQ9d(h{^xCiAWJ0Ixp~3&E z(WwdT$O$7ez?pw>Jf{`!T-205_zJv+y~$w@XmQ;CiL8d*-x_z~0@vo4|3xUermJ;Q z9KgxjkN8Vh)xZ2xhX0N@{~@^d@BLoYFW%Uys83=`15+YZ%KecmWXjVV2}YbjBonSh zVOwOfI7^gvlC~Pq$QDHMQ6_Pd10OV{q_Zai^Yg({5XysuT`3}~3K*8u>a2FLBQ%#_YT6$4&6(?ZGwDE*C-p8>bM?hj*XOIoj@C!L5) zH1y!~wZ^dX5N&xExrKV>rEJJjkJDq*$K>qMi`Lrq08l4bQW~!Fbxb>m4qMHu6weTiV6_9(a*mZ23kr9AM#gCGE zBXg8#m8{ad@214=#w0>ylE7qL$4`xm!**E@pw484-VddzN}DK2qg&W~?%hcv3lNHx zg(CE<2)N=p!7->aJ4=1*eB%fbAGJcY65f3=cKF4WOoCgVelH$qh0NpIka5J-6+sY* zBg<5!R=I*5hk*CR@$rY6a8M%yX%o@D%{q1Jn=8wAZ;;}ol>xFv5nXvjFggCQ_>N2} zXHiC~pCFG*oEy!h_sqF$^NJIpQzXhtRU`LR0yU;MqrYUG0#iFW4mbHe)zN&4*Wf)G zV6(WGOq~OpEoq##E{rC?!)8ygAaAaA0^`<8kXmf%uIFfNHAE|{AuZd!HW9C^4$xW; zmIcO#ti!~)YlIU4sH(h&s6}PH-wSGtDOZ+%H2gAO(%2Ppdec9IMViuwwWW)qnqblH9xe1cPQ@C zS4W|atjGDGKKQAQlPUVUi1OvGC*Gh2i&gkh0up%u-9ECa7(Iw}k~0>r*WciZyRC%l z7NX3)9WBXK{mS|=IK5mxc{M}IrjOxBMzFbK59VI9k8Yr$V4X_^wI#R^~RFcme2)l!%kvUa zJ{zpM;;=mz&>jLvON5j>*cOVt1$0LWiV>x)g)KKZnhn=%1|2E|TWNfRQ&n?vZxQh* zG+YEIf33h%!tyVBPj>|K!EB{JZU{+k`N9c@x_wxD7z~eFVw%AyU9htoH6hmo0`%kb z55c#c80D%0^*6y|9xdLG$n4Hn%62KIp`Md9Jhyp8)%wkB8<%RlPEwC&FL z;hrH(yRr(Ke$%TZ09J=gGMC3L?bR2F4ZU!}pu)*8@l(d9{v^^(j>y+GF*nGran5*M z{pl5ig0CVsG1etMB8qlF4MDFRkLAg4N=l{Sc*F>K_^AZQc{dSXkvonBI)qEN1*U&? zKqMr?Wu)q9c>U~CZUG+-ImNrU#c`bS?RpvVgWXqSsOJrCK#HNIJ+k_1Iq^QNr(j|~ z-rz67Lf?}jj^9Ik@VIMBU2tN{Ts>-O%5f?=T^LGl-?iC%vfx{}PaoP7#^EH{6HP!( zG%3S1oaiR;OmlKhLy@yLNns`9K?60Zg7~NyT0JF(!$jPrm^m_?rxt~|J2)*P6tdTU z25JT~k4RH9b_1H3-y?X4=;6mrBxu$6lsb@xddPGKA*6O`Cc^>Ul`f9c&$SHFhHN!* zjj=(Jb`P}R%5X@cC%+1ICCRh1^G&u548#+3NpYTVr54^SbFhjTuO-yf&s%r4VIU!lE!j(JzHSc9zRD_fw@CP0pkL(WX6 zn+}LarmQP9ZGF9So^+jr<(LGLlOxGiCsI^SnuC{xE$S;DA+|z+cUk=j^0ipB(WTZ} zR0osv{abBd)HOjc(SAV&pcP@37SLnsbtADj?bT#cPZq|?W1Ar;4Vg5m!l{@{TA~|g zXYOeU`#h-rT@(#msh%%kH>D=`aN}2Rysez?E@R6|@SB(_gS0}HC>83pE`obNA9vsH zSu^r>6W-FSxJA}?oTuH>-y9!pQg|*<7J$09tH=nq4GTx+5($$+IGlO^bptmxy#=)e zuz^beIPpUB_YK^?eb@gu(D%pJJwj3QUk6<3>S>RN^0iO|DbTZNheFX?-jskc5}Nho zf&1GCbE^maIL$?i=nXwi)^?NiK`Khb6A*kmen^*(BI%Kw&Uv4H;<3ib-2UwG{7M&* zn$qyi8wD9cKOuxWhRmFupwLuFn!G5Vj6PZ#GCNJLlTQuQ?bqAYd7Eva5YR~OBbIim zf(6yXS4pei1Bz4w4rrB6Ke~gKYErlC=l9sm*Zp_vwJe7<+N&PaZe|~kYVO%uChefr%G4-=0eSPS{HNf=vB;p~ z5b9O1R?WirAZqcdRn9wtct>$FU2T8p=fSp;E^P~zR!^C!)WHe=9N$5@DHk6(L|7s@ zcXQ6NM9Q~fan1q-u8{ez;RADoIqwkf4|6LfsMZK6h{ZUGYo>vD%JpY<@w;oIN-*sK zxp4@+d{zxe>Z-pH#_)%|d(AC`fa!@Jq)5K8hd71!;CEG|ZI{I2XI`X~n|ae;B!q{I zJDa#T+fRviR&wAN^Sl{z8Ar1LQOF&$rDs18h0{yMh^pZ#hG?c5OL8v07qRZ-Lj5(0 zjFY(S4La&`3IjOT%Jqx4z~08($iVS;M10d@q~*H=Py)xnKt(+G-*o33c7S3bJ8cmwgj45` zU|b7xCoozC!-7CPOR194J-m9N*g`30ToBo!Io?m>T)S{CusNZx0J^Hu6hOmvv;0~W zFHRYJgyRhP1sM_AQ%pkD!X-dPu_>)`8HunR4_v$4T78~R<})-@K2LBt03PBLnjHzuYY)AK?>0TJe9 zmmOjwSL%CTaLYvYlJ~|w?vc*R+$@vEAYghtgGhZ2LyF+UdOn+v^yvD9R%xbU$fUjK{{VQ4VL&&UqAFa>CZuX4kX zJ)njewLWfKXneB+r}Y$`ezzwDoRT3r{9(@=I3-z>8tT)n3whDyi(r*lAnxQJefj_x z-8lc=r!Vua{b}v;LT)oXW>~6Q03~RAp~R}TZq9sGbeUBMS)?ZrJqiu|E&ZE)uN1uL zXcAj3#aEz zzbcCF)+;Hia#OGBvOatkPQfE{*RtBlO1QFVhi+3q0HeuFa*p+Dj)#8Mq9yGtIx%0A znV5EmN(j!&b%kNz4`Vr-)mX_?$ng&M^a6loFO(G3SA!~eBUEY!{~>C|Ht1Q4cw)X5~dPiEYQJNg?B2&P>bU7N(#e5cr8qc7A{a7J9cdMcRx)N|?;$L~O|E)p~ zIC}oi3iLZKb>|@=ApsDAfa_<$0Nm<3nOPdr+8Y@dnb|u2S<7CUmTGKd{G57JR*JTo zb&?qrusnu}jb0oKHTzh42P00C{i^`v+g=n|Q6)iINjWk4mydBo zf0g=ikV*+~{rIUr%MXdz|9ebUP)<@zR8fgeR_rChk0<^^3^?rfr;-A=x3M?*8|RPz z@}DOF`aXXuZGih9PyAbp|DULSw8PJ`54io)ga6JG@Hgg@_Zo>OfJ)8+TIfgqu%877 z@aFykK*+|%@rSs-t*oAzH6Whyr=TpuQ}B0ptSsMg9p8@ZE5A6LfMk1qdsf8T^zkdC3rUhB$`s zBdanX%L3tF7*YZ4^A8MvOvhfr&B)QOWCLJ^02kw5;P%n~5e`sa6MG{E2N^*2ZX@ge zI2>ve##O?I}sWX)UqK^_bRz@;5HWp5{ziyg?QuEjXfMP!j zpr(McSAQz>ME?M-3NSoCn$91#_iNnULp6tD0NN7Z0s#G~-~xWZFWN-%KUVi^yz~-` zn;AeGvjLJ~{1p#^?$>zM4vu=3mjBI$(_tC~NC0o@6<{zS_*3nGfUsHr3Gdgn%XedF zQUP=j5Mb>9=#f7aPl;cm$=I0u*WP}aVE!lCYw2Ht{Z_j9mp1h>dHGKkEZP6f^6O@J zndJ2+rWjxp|3#<2oO=8v!oHMX{|Vb|^G~pU_A6=ckBQvt>o+dpgYy(D=VCj65GE&jJj{&-*iq?z)PHNee&-@Mie~#LD*={ex8h(-)<@|55 zUr(}L?mz#;d|mrD%zrh<-*=;5*7K$B`zPjJ%m2pwr*G6tf8tN%a

_x$+l{{cH8$W#CT literal 0 HcmV?d00001 From ddcb7bc6062617fabd656ab1fe567c927f2a87d0 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Thu, 14 May 2020 21:44:34 +0200 Subject: [PATCH 54/68] Fix sourceSet issues --- build.gradle | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 8097e69..557b261 100644 --- a/build.gradle +++ b/build.gradle @@ -36,9 +36,8 @@ sourceSets { api { java { srcDir('src/api/java') } } - impl { + main { java { - srcDir('src/main/java') compileClasspath += api.output runtimeClasspath += api.output } @@ -93,8 +92,7 @@ dependencies { // https://github.com/SpongePowered/Mixin compile "org.spongepowered:mixin:0.8.1-SNAPSHOT" - runtime configurations.apiRuntime - runtime configurations.implRuntime + implementation sourceSets.api.output } final def jarAttributes = [ From 3fecc7503ca09228c313fa65d4f5fef8b86bcaf3 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Thu, 14 May 2020 22:57:22 +0200 Subject: [PATCH 55/68] Define jar base names --- build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.gradle b/build.gradle index 557b261..20e58e4 100644 --- a/build.gradle +++ b/build.gradle @@ -117,6 +117,7 @@ jar.finalizedBy('reobfJar') // API jar for library consumers task apiJar(type: Jar, dependsOn: classes) { + baseName = project.modId classifier = 'api' from sourceSets.api.output } @@ -124,6 +125,7 @@ apiJar.finalizedBy('reobfJar') // Non-obfuscated jar for developers task devJar(type: Jar, dependsOn: classes) { + baseName = project.modId classifier = 'dev' from sourceSets.api.output from sourceSets.main.output From a8be1bc75dc31f4256d3c6aa9c7adad1f3939cc5 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Fri, 15 May 2020 19:39:07 +0200 Subject: [PATCH 56/68] Update mod name in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3428d5a..bee982f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Tickrate Changer Mod +# TimeLib This is a Forge mod for Mincraft version 1.15 that lets you slow down time making everything in your environment move slower. This includes all game animations (including the player), but does not affect the camera. From 5e4175ce047e685189bd0d49d727e6a0dbb87cc8 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Fri, 15 May 2020 19:39:23 +0200 Subject: [PATCH 57/68] Update README sections --- README.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index bee982f..9612f56 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,21 @@ # TimeLib -This is a Forge mod for Mincraft version 1.15 that lets you slow down time making everything in your environment move slower. This includes all game animations (including the player), but does not affect the camera. +TimeLib is a Minecraft Forge modding library that lets you control game time. -## Where do I download it? +## Motivation -- Check the [releases](https://github.com/yooksi/trcm/releases) section in project repository page to get the latest release. +Time is a very powerful game aspect that is often neglected. Changing how time behaves has the potential to dramatically alter game experience. For example, longer days and night could give players a greater sense of adventure by promoting immersion over fast-paced action, slow-motion effects applied in critical moments of battle could create a great feeling of excitement. -## How do I install it? +Through the use of Mixin and a simple to use API to configure various time related settings TimeLib gives developers the tools they need to create game changing mods. -- Make sure you have the appropriate Forge [version](https://github.com/yooksi/trcm/blob/master/gradle.properties#L9)-[build](https://github.com/yooksi/trcm/blob/master/gradle.properties#L10) installed. - Place the mod `jar` in game `mods` folder as per standard mod installation. -- Download the appropriate MixinBootstrap [version](https://github.com/yooksi/trcm/blob/master/gradle.properties#L13) from the [releases](https://github.com/LXGaming/MixinBootstrap/releases) section of the project repository page and place it in game `mods` folder alongside the mod `jar` as instructed by the previous step. +- Download a backward compatible [version](https://github.com/yooksi/trcm/blob/master/gradle.properties#L15) of MixinBootstrap from the [releases](https://github.com/LXGaming/MixinBootstrap/releases) section of the project repository page and place it in game `mods` folder alongside the mod `jar` as previously instructed. ### Why do I need an external mod? -Due to the nature of how Forge works Mixin needs a bit of help to work in production environment with Forge. MixinBootstrap does just that, it's only function is to enable Mixin to work with Forge, that's it. If you are interested in learning more about Mixin environment read [Introduction to Mixins: The Mixin Environment](https://github.com/SpongePowered/Mixin/wiki/Introduction-to-Mixins---The-Mixin-Environment). +Forge and [Mixin](https://github.com/SpongePowered/Mixin) are not compatible straight out of the box so they need a bit of help to work in production environment. MixinBootstrap does just that, it's only function is to enable Mixin to work with Forge, that's it. If you are interested in learning more about Mixin environment read [Introduction to Mixins: The Mixin Environment](https://github.com/SpongePowered/Mixin/wiki/Introduction-to-Mixins---The-Mixin-Environment). -## How do I use it? +## How to use it? Tick rate is changed through the use of the following game commands: @@ -25,7 +24,7 @@ Tick rate is changed through the use of the following game commands: ## Technical details -The process used to accomplish this is complex and involves bytecode manipulation using [Mixin](https://github.com/SpongePowered/Mixin). The technical side of things can be difficult to understand if you are not familiar with [ASM](https://asm.ow2.io/), however this is the simple version of what happens inside the mod that allows us to slow down time: +The following section is a brief technical explanation of how TimeLib is able to slow down game time. It is written in hopes that some developers might find it useful when learning to work with Mixin. Note that the process used to accomplish this involves bytecode manipulation and as such is not recommended as a starting point for beginners to learn about Java or Forge. - During runtime Mixin will redirect method flow at a particular point in `MinecraftServer.run()` method and inject a callback to itself. The point of injection is the `while` loop that handles the server time calculation and determines when each tick should happen. - We then do a series of calculations and determine how much milliseconds passed this tick based on the `mspt` (milliseconds per tick) rate calculated from tick rate set by the player via game command. From 2b4d85af198cf1116251d5f35dff9b64a7fe315f Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Fri, 15 May 2020 19:39:36 +0200 Subject: [PATCH 58/68] Add features README section --- README.md | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/README.md b/README.md index 9612f56..938f95a 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,72 @@ Time is a very powerful game aspect that is often neglected. Changing how time b Through the use of Mixin and a simple to use API to configure various time related settings TimeLib gives developers the tools they need to create game changing mods. +## Features + +- Allows you to set game tick rate resulting in slower or faster movements and animations + including all mobs and players, but does not affect the camera. + +- Allows you to set time cycle speed and control how fast days and nights last. + +## Where to get it? + +Each repository production and maven artifacts release contains three `jar` types that you can download: + +- `-dev.jar` is a non-obfuscated version of the jar used by developers. +- `-sources.jar` contains project source files used by developers. +- `-.jar` is an obfuscated production-ready jar mostly used by players. + +**Developers** will want either the dev or production jar (optionally) accompanied by sources jar to make reading and understanding the library code easier when working with their mods. + +**Players** will want only the production jar found in the repository release section on [Github](#github) which they should treat as a standard game mod (see [installation](#how-to-install-it) section for more information). + +### Maven + +TimeLib is hosted on [JitPack](https://jitpack.io/#yooksi/TimeLib) so head over there and get the latest release. + +Here is the **recommended** way of getting the library in your project: + +```groovy +// Definines where Gradle should look for declared dependencies +// Declare this AFTER the buildscript block (first script block) +// and BEFORE MinecraftForge Gradle plugin configuration +repositories { + ... + maven { url 'https://jitpack.io' } +} + +minecraft { + ... +} + +dependencies { + // Specify the version of Minecraft to use + minecraft "net.minecraftforge:forge:${minecraftVersion}-${forgeVersion}" + + // We need to compile with the api but don't need it during runtime + compileOnly "com.github.yooksi:TimeLib:${timeLibVersion}:api" + // We need the main jar during runtime but not when compiling + runtimeOnly "com.github.yooksi:TimeLib:${timeLibVersion}:dev" +} +``` + +*Note that the `timeLibVersion` property in this example was defined in `gradle.properties` to make accessing and reading version numbers easier. You should update the property (or just replace the variable) to a fully qualified version of the library you want to use.* + +The example above would attempt to resolve the following artifacts from Jitpack: + +- API library module for other mods to interact with. We need this jar when we are writing and compiling our mod so we use the `compileOnly` strategy. The API is also needed during runtime but in our case it is already included in the dev jar that is included on runtime classpath. + +- *Deobfuscated* version of our mod (indicated by the `dev` classifier). The dependency would be exposed only during runtime because we added it to `runtimeOnly` configuration. + +Another way to get the library would be to use `fg.deobf` right after declaring the configuration type to indicate that the production jar should be deobfuscated after being resolved. This is not necessary and just adds extra work during build phase, this is why the project provides the `dev` jar. Besides, this way you need to manually attach source files since the deobfuscated jar ends up in Forge cache folder. + +### Github + +Check the [releases](https://github.com/yooksi/TimeLib/releases) section in project repository page to get the latest release. This is the recommended way to obtain the production jar for players, developers should use this way only if JitPack is not working and they are not afraid to do things manually. + +## How to install it? + +- Make sure you have a backward compatible Forge [version](https://github.com/yooksi/trcm/blob/master/gradle.properties#L11) installed. - Place the mod `jar` in game `mods` folder as per standard mod installation. - Download a backward compatible [version](https://github.com/yooksi/trcm/blob/master/gradle.properties#L15) of MixinBootstrap from the [releases](https://github.com/LXGaming/MixinBootstrap/releases) section of the project repository page and place it in game `mods` folder alongside the mod `jar` as previously instructed. From 26168d6540be4b62f9d7a2be45c474b4d3c09923 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Fri, 15 May 2020 19:39:51 +0200 Subject: [PATCH 59/68] Credit Mixin community in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 938f95a..ca4161d 100644 --- a/README.md +++ b/README.md @@ -115,4 +115,4 @@ The steps above slow down server tick rate but unfortunately result in frame ski - [Unregkiller](https://github.com/Unregkiller) - for commissioning the creation of this mod. - [gnembon](https://github.com/gnembon) - for creating [Carpet](https://github.com/gnembon/fabric-carpet/blob/master/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java) on which this mod is based of. -- [MDC](https://www.moddevcafe.com/) and [MMD](https://discordapp.com/invite/EDbExcX) communities - for helping resolve technical issues. \ No newline at end of file +- [MDC](https://www.moddevcafe.com/), [MMD](https://discordapp.com/invite/EDbExcX) and [Mixin](https://discord.gg/sponge) community- for helping resolve technical issues. \ No newline at end of file From 407e583654f242b119d0d24c8bfe14184b6a50cb Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Fri, 15 May 2020 19:49:52 +0200 Subject: [PATCH 60/68] Add project badges to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ca4161d..1d95e31 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # TimeLib +[![JitPack](https://jitpack.io/v/yooksi/TimeLib.svg)](https://jitpack.io/#yooksi/TimeLib) [![License](https://img.shields.io/github/license/yooksi/TimeLib)](https://www.gnu.org/licenses/) [![Discord](https://img.shields.io/discord/710517912485494794)](https://discord.gg/dKY9xW) TimeLib is a Minecraft Forge modding library that lets you control game time. From f3857acfae6c7b8039fa5f3e2bd2cb76d2fce6c9 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Fri, 15 May 2020 21:36:45 +0200 Subject: [PATCH 61/68] Clarify third README section --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1d95e31..b56ffee 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,10 @@ Another way to get the library would be to use `fg.deobf` right after declaring ### Github -Check the [releases](https://github.com/yooksi/TimeLib/releases) section in project repository page to get the latest release. This is the recommended way to obtain the production jar for players, developers should use this way only if JitPack is not working and they are not afraid to do things manually. +This is the **recommended** way to obtain the production jar for library users. +*Developers should only use this way if JitPack is not working or they feel adventurous.* + +Check the [releases](https://github.com/yooksi/TimeLib/releases) section in project repository page to get the latest release. ## How to install it? From f0da89b13db3e07c26b1b3a04b37b1eb018566cb Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Fri, 15 May 2020 21:37:10 +0200 Subject: [PATCH 62/68] Update usage README section --- README.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b56ffee..f7b982f 100644 --- a/README.md +++ b/README.md @@ -87,10 +87,17 @@ Forge and [Mixin](https://github.com/SpongePowered/Mixin) are not compatible str ## How to use it? -Tick rate is changed through the use of the following game commands: - -- `\t ` - change tick rate to a desired value (min 0.1, max 20). -- `\t` - reset tick rate to game default value (20). +### Commands + +- `\tickrate set ` - change tick rate to a desired value (min 0.1, max 500). + - `slow` - 50% slower tick rate (10). + - `normal` - game default value (20). + - `fast` - 50% faster tick rate (30). +- `\tickrate reset` - resets tick rate to game default value (20). +- `\timecycle speed ` - change the speed for day/night time cycle (min -72, max 72) + - `slow` - skip 1 tick when updating day time (x2 longer cycle). + - `normal` - do not skip ticks when updating day time (game default). + - `fast` - add 1 additional tick when updating day time (x2 faster cycle). ## Technical details From 7a22956cf1119c9a0f2fb170f386e2b571654767 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Fri, 15 May 2020 21:53:22 +0200 Subject: [PATCH 63/68] Do minor changes to docs --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f7b982f..5b16314 100644 --- a/README.md +++ b/README.md @@ -62,15 +62,15 @@ dependencies { The example above would attempt to resolve the following artifacts from Jitpack: -- API library module for other mods to interact with. We need this jar when we are writing and compiling our mod so we use the `compileOnly` strategy. The API is also needed during runtime but in our case it is already included in the dev jar that is included on runtime classpath. +- API library module for other mods to interact with. We need this jar when we are writing and compiling our mod so we use the `compileOnly` strategy. It is also needed during runtime but it's already included in the dev jar which is on runtime classpath. -- *Deobfuscated* version of our mod (indicated by the `dev` classifier). The dependency would be exposed only during runtime because we added it to `runtimeOnly` configuration. +- *Deobfuscated* version of our mod built for use by developers (indicated by the `dev` classifier). The dependency will be exposed only during runtime because we added it to `runtimeOnly` configuration. -Another way to get the library would be to use `fg.deobf` right after declaring the configuration type to indicate that the production jar should be deobfuscated after being resolved. This is not necessary and just adds extra work during build phase, this is why the project provides the `dev` jar. Besides, this way you need to manually attach source files since the deobfuscated jar ends up in Forge cache folder. +Another way to get the library would be to use `fg.deobf` right after declaring the configuration type to indicate that the production jar should be deobfuscated after being resolved. This is not necessary and just adds extra work during build phase, this is why the project provides the `dev` jar. Besides, this way you need to manually attach source files since the created jar ends up in Forge cache folder. ### Github -This is the **recommended** way to obtain the production jar for library users. +This is the **recommended** way to obtain the production jar for library users. *Developers should only use this way if JitPack is not working or they feel adventurous.* Check the [releases](https://github.com/yooksi/TimeLib/releases) section in project repository page to get the latest release. From 84c4b978cbd7f5e40263ae936a6b056373a10d11 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Fri, 15 May 2020 22:09:42 +0200 Subject: [PATCH 64/68] Bump forge version number --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 20160ce..3b19444 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,6 +8,6 @@ modVersion=0.1.1 groupName=yooksi minecraftVersion=1.15.2 -forgeVersion=31.1.63 +forgeVersion=31.2.0 mappingMCVersion=1.15.1 mappingBuild=20200501 From 62895b5129d450769babb5dedc08f6289a17dac5 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Fri, 15 May 2020 22:10:04 +0200 Subject: [PATCH 65/68] Bump mapping build number --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 3b19444..057b1c2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,4 +10,4 @@ groupName=yooksi minecraftVersion=1.15.2 forgeVersion=31.2.0 mappingMCVersion=1.15.1 -mappingBuild=20200501 +mappingBuild=20200515 From 2182934a8f0b19313c30e50dad8bbf0b35b73390 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Fri, 15 May 2020 22:10:10 +0200 Subject: [PATCH 66/68] Bump mod version number --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 057b1c2..2483fcc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false modId=timelib -modVersion=0.1.1 +modVersion=0.2.0 groupName=yooksi minecraftVersion=1.15.2 From 99719f254833bac9aa152803a1a165d82f2b1b45 Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Sat, 16 May 2020 12:45:24 +0200 Subject: [PATCH 67/68] Lowercase project name This will help avoid confusion for consumers. --- .idea/.gitignore | 1 + settings.gradle | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.idea/.gitignore b/.idea/.gitignore index 04341f0..70e4ddf 100644 --- a/.idea/.gitignore +++ b/.idea/.gitignore @@ -37,3 +37,4 @@ # Other /**/compiler.xml /**/jarRepositories.xml +/**/.name \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index eb84a01..52f1204 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -rootProject.name = "TimeLib" +rootProject.name = "timelib" From c2b4b68b253138b2b2f8104d7eb51152c12d655f Mon Sep 17 00:00:00 2001 From: Matthew Cain Date: Tue, 26 May 2020 06:33:35 +0200 Subject: [PATCH 68/68] Improve readme sections --- README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5b16314..3a9309d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # TimeLib [![JitPack](https://jitpack.io/v/yooksi/TimeLib.svg)](https://jitpack.io/#yooksi/TimeLib) [![License](https://img.shields.io/github/license/yooksi/TimeLib)](https://www.gnu.org/licenses/) [![Discord](https://img.shields.io/discord/710517912485494794)](https://discord.gg/dKY9xW) -TimeLib is a Minecraft Forge modding library that lets you control game time. +TimeLib is a Minecraft modding library for Forge that lets you control game time. ## Motivation @@ -66,7 +66,9 @@ The example above would attempt to resolve the following artifacts from Jitpack: - *Deobfuscated* version of our mod built for use by developers (indicated by the `dev` classifier). The dependency will be exposed only during runtime because we added it to `runtimeOnly` configuration. -Another way to get the library would be to use `fg.deobf` right after declaring the configuration type to indicate that the production jar should be deobfuscated after being resolved. This is not necessary and just adds extra work during build phase, this is why the project provides the `dev` jar. Besides, this way you need to manually attach source files since the created jar ends up in Forge cache folder. +Another way to get the library would be to use `fg.deobf` right after declaring the configuration type to indicate that the production jar should be deobfuscated after being resolved. + +This is not necessary and just adds extra work during build phase and makes deal with manually attaching source files. This is why the project provides a compiled `dev` jar. ### Github @@ -83,7 +85,9 @@ Check the [releases](https://github.com/yooksi/TimeLib/releases) section in proj ### Why do I need an external mod? -Forge and [Mixin](https://github.com/SpongePowered/Mixin) are not compatible straight out of the box so they need a bit of help to work in production environment. MixinBootstrap does just that, it's only function is to enable Mixin to work with Forge, that's it. If you are interested in learning more about Mixin environment read [Introduction to Mixins: The Mixin Environment](https://github.com/SpongePowered/Mixin/wiki/Introduction-to-Mixins---The-Mixin-Environment). +Forge and [Mixin](https://github.com/SpongePowered/Mixin) are not compatible straight out of the box so they need a bit of help to work in production environment. MixinBootstrap does just that, it's only function is to enable Mixin to work with Forge, that's it. + +If you are interested in learning more about Mixin environment read [Introduction to Mixins: The Mixin Environment](https://github.com/SpongePowered/Mixin/wiki/Introduction-to-Mixins---The-Mixin-Environment). ## How to use it?