diff --git a/sources/src/main/java/io/akarin/api/internal/mixin/IMixinRealTimeTicking.java b/sources/src/main/java/io/akarin/api/internal/mixin/IMixinRealTimeTicking.java new file mode 100644 index 000000000..24fcdd905 --- /dev/null +++ b/sources/src/main/java/io/akarin/api/internal/mixin/IMixinRealTimeTicking.java @@ -0,0 +1,30 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package io.akarin.api.internal.mixin; + +public interface IMixinRealTimeTicking { + + long getRealTimeTicks(); +} \ No newline at end of file diff --git a/sources/src/main/java/io/akarin/server/mixin/core/MixinMinecraftServer.java b/sources/src/main/java/io/akarin/server/mixin/core/MixinMinecraftServer.java index f03363103..c106c86ac 100644 --- a/sources/src/main/java/io/akarin/server/mixin/core/MixinMinecraftServer.java +++ b/sources/src/main/java/io/akarin/server/mixin/core/MixinMinecraftServer.java @@ -38,15 +38,6 @@ public abstract class MixinMinecraftServer { return "Akarin"; } - /* - * Forcely disable snooper - */ - @Overwrite - public void a(MojangStatisticsGenerator generator) {} - - @Overwrite - public void b(MojangStatisticsGenerator generator) {} - @Inject(method = "run()V", at = @At( value = "INVOKE", target = "net/minecraft/server/MinecraftServer.aw()J", @@ -60,6 +51,18 @@ public abstract class MixinMinecraftServer { AkarinSlackScheduler.boot(); } + /* + * Forcely disable snooper + */ + @Overwrite + public void a(MojangStatisticsGenerator generator) {} + + @Overwrite + public void b(MojangStatisticsGenerator generator) {} + + /* + * Parallel world ticking + */ @Shadow public CraftServer server; @Shadow @Mutable protected Queue> j; @Shadow public Queue processQueue; diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntity.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntity.java new file mode 100644 index 000000000..2cb7d7ba1 --- /dev/null +++ b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntity.java @@ -0,0 +1,56 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package io.akarin.server.mixin.realtime; + +import org.spongepowered.asm.lib.Opcodes; +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.Redirect; +import io.akarin.api.internal.mixin.IMixinRealTimeTicking; +import net.minecraft.server.Entity; +import net.minecraft.server.World; + +@Mixin(value = Entity.class, remap = false) +public abstract class MixinEntity { + private static final String ENTITY_RIDABLE_COOLDOWN_FIELD = "Lnet/minecraft/entity/Entity;j:I"; // PUTFIELD: rideCooldown + private static final String ENTITY_PORTAL_COUNTER_FIELD = "Lnet/minecraft/entity/Entity;al:I"; // PUTFIELD: portalCounter + @Shadow protected int j; + @Shadow protected int al; + @Shadow public World world; + + // PAIL: onEntityUpdate + @Redirect(method = "Y()V", at = @At(value = "FIELD", target = ENTITY_RIDABLE_COOLDOWN_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) + public void fixupEntityCooldown(Entity self, int modifier) { + int ticks = (int) ((IMixinRealTimeTicking) this.world).getRealTimeTicks(); + this.j = Math.max(0, this.j - ticks); // PAIL: rideCooldown + } + + @Redirect(method = "Y()V", at = @At(value = "FIELD", target = ENTITY_PORTAL_COUNTER_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) + public void fixupPortalCounter(Entity self, int modifier) { + int ticks = (int) ((IMixinRealTimeTicking) this.world).getRealTimeTicks(); + this.al += ticks; // PAIL: portalCounter + } +} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityAgeable.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityAgeable.java new file mode 100644 index 000000000..7265a38c6 --- /dev/null +++ b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityAgeable.java @@ -0,0 +1,51 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package io.akarin.server.mixin.realtime; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import io.akarin.api.internal.mixin.IMixinRealTimeTicking; +import net.minecraft.server.EntityAgeable; + +@Mixin(value = EntityAgeable.class, remap = false) +public abstract class MixinEntityAgeable { + private static final String ENTITY_AGEABLE_SET_GROWING_AGE_METHOD = "Lnet/minecraft/entity/EntityAgeable;setAgeRaw(I)V"; + + // PAIL: onLivingUpdate + @Redirect(method = "n()V", at = @At(value = "INVOKE", target = ENTITY_AGEABLE_SET_GROWING_AGE_METHOD, ordinal = 0)) + public void fixupGrowingUp(EntityAgeable self, int age) { + // Subtract the one the original update method added + int diff = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks() - 1; + self.setAgeRaw(Math.min(0, age + diff)); + } + + @Redirect(method = "n()V", at = @At(value = "INVOKE", target = ENTITY_AGEABLE_SET_GROWING_AGE_METHOD, ordinal = 1)) + public void fixupBreedingCooldown(EntityAgeable self, int age) { + // Subtract the one the original update method added + int diff = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks() - 1; + self.setAgeRaw(Math.max(0, age - diff)); + } +} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityExperienceOrb.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityExperienceOrb.java new file mode 100644 index 000000000..fc8da0e3f --- /dev/null +++ b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityExperienceOrb.java @@ -0,0 +1,55 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package io.akarin.server.mixin.realtime; + +import org.spongepowered.asm.lib.Opcodes; +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.Redirect; + +import io.akarin.api.internal.mixin.IMixinRealTimeTicking; +import net.minecraft.server.EntityExperienceOrb; + +@Mixin(value = EntityExperienceOrb.class, remap = false) +public abstract class MixinEntityExperienceOrb { + private static final String ENTITY_XP_DELAY_PICKUP_FIELD = "Lnet/minecraft/entity/item/EntityExperienceOrb;c:I"; // PUTFIELD: delayBeforeCanPickup + private static final String ENTITY_XP_AGE_FIELD = "Lnet/minecraft/entity/item/EntityExperienceOrb;b:I"; // PUTFIELD: xpOrbAge + @Shadow public int c; // PAIL: delayBeforeCanPickup + @Shadow public int b; // PAIL: xpOrbAge + + // PAIL: onUpdate + @Redirect(method = "B_()V", at = @At(value = "FIELD", target = ENTITY_XP_DELAY_PICKUP_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) + public void fixupPickupDelay(EntityExperienceOrb self, int modifier) { + int ticks = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks(); + this.c = Math.max(0, this.c - ticks); // PAIL: delayBeforeCanPickup + } + + @Redirect(method = "B_()V", at = @At(value = "FIELD", target = ENTITY_XP_AGE_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) + public void fixupAge(EntityExperienceOrb self, int modifier) { + int ticks = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks(); + this.b += ticks; // PAIL: xpOrbAge + } +} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityHuman.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityHuman.java new file mode 100644 index 000000000..d5318b6fc --- /dev/null +++ b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityHuman.java @@ -0,0 +1,61 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package io.akarin.server.mixin.realtime; + +import org.spongepowered.asm.lib.Opcodes; +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.Redirect; + +import io.akarin.api.internal.mixin.IMixinRealTimeTicking; +import net.minecraft.server.EntityHuman; + +@Mixin(value = EntityHuman.class, remap = false) +public abstract class MixinEntityHuman { + private static final String ENTITY_PLAYER_XP_COOLDOWN_FIELD = "Lnet/minecraft/entity/player/EntityHuman;bD:I"; // PUTFIELD: xpCooldown + private static final String ENTITY_PLAYER_SLEEP_TIMER_FIELD = "Lnet/minecraft/entity/player/EntityHuman;sleepTicks:I"; + @Shadow public int bD; + @Shadow private int sleepTicks; + + // PAIL: onUpdate + @Redirect(method = "B_()V", at = @At(value = "FIELD", target = ENTITY_PLAYER_XP_COOLDOWN_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) + public void fixupXpCooldown(EntityHuman self, int modifier) { + int ticks = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks(); + this.bD = Math.max(0, this.bD - ticks); // PAIL: xpCooldown + } + + @Redirect(method = "B_()V", at = @At(value = "FIELD", target = ENTITY_PLAYER_SLEEP_TIMER_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) + public void fixupSleepTimer(EntityHuman self, int modifier) { + int ticks = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks(); + this.sleepTicks += ticks; + } + + @Redirect(method = "B_()V", at = @At(value = "FIELD", target = ENTITY_PLAYER_SLEEP_TIMER_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 2)) + public void fixupWakeTimer(EntityHuman self, int modifier) { + int ticks = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks(); + this.sleepTicks += ticks; + } +} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityInsentient.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityInsentient.java new file mode 100644 index 000000000..f62489b8b --- /dev/null +++ b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityInsentient.java @@ -0,0 +1,50 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package io.akarin.server.mixin.realtime; + +import org.spongepowered.asm.lib.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import io.akarin.api.internal.mixin.IMixinRealTimeTicking; +import net.minecraft.server.EntityInsentient; +import net.minecraft.server.EntityLiving; +import net.minecraft.server.World; + +@Mixin(value = EntityInsentient.class, remap = false) +public abstract class MixinEntityInsentient extends EntityLiving { + private static final String ENTITY_LIVING_AGE_FIELD = "Lnet/minecraft/entity/EntityInsentient;ticksFarFromPlayer:I"; + + public MixinEntityInsentient(World world) { + super(world); + } + + @Redirect(method = "doTick", at = @At(value = "FIELD", target = ENTITY_LIVING_AGE_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) + public void fixupEntityDespawnAge(EntityInsentient self, int modifier) { + int ticks = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks(); + this.ticksFarFromPlayer += ticks; + } +} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityItem.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityItem.java new file mode 100644 index 000000000..fc580cc82 --- /dev/null +++ b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityItem.java @@ -0,0 +1,55 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package io.akarin.server.mixin.realtime; + +import org.spongepowered.asm.lib.Opcodes; +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.Redirect; + +import io.akarin.api.internal.mixin.IMixinRealTimeTicking; +import net.minecraft.server.EntityItem; + +@Mixin(value = EntityItem.class, remap = false) +public abstract class MixinEntityItem { + private static final String ENTITY_ITEM_DELAY_PICKUP_FIELD = "Lnet/minecraft/entity/item/EntityItem;pickupDelay:I"; + private static final String ENTITY_ITEM_AGE_FIELD = "Lnet/minecraft/entity/item/EntityItem;age:I"; + @Shadow public int age; + @Shadow private int pickupDelay; + + // PAIL: onUpdate + @Redirect(method = "B_()V", at = @At(value = "FIELD", target = ENTITY_ITEM_DELAY_PICKUP_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) + public void fixupPickupDelay(EntityItem self, int modifier) { + int ticks = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks(); + this.pickupDelay = Math.max(0, this.pickupDelay - ticks); + } + + @Redirect(method = "B_()V", at = @At(value = "FIELD", target = ENTITY_ITEM_AGE_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) + public void fixupAge(EntityItem self, int modifier) { + int ticks = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks(); + this.age += ticks; + } +} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityPlayer.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityPlayer.java new file mode 100644 index 000000000..81999a088 --- /dev/null +++ b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityPlayer.java @@ -0,0 +1,51 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package io.akarin.server.mixin.realtime; + +import org.spongepowered.asm.lib.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import io.akarin.api.internal.mixin.IMixinRealTimeTicking; +import net.minecraft.server.Entity; +import net.minecraft.server.EntityPlayer; +import net.minecraft.server.World; + +@Mixin(value = EntityPlayer.class, remap = false) +public abstract class MixinEntityPlayer extends Entity { + private static final String ENTITY_PLAYER_MP_PORTAL_COOLDOWN_FIELD = "Lnet/minecraft/entity/player/EntityPlayer;portalCooldown:I"; + + public MixinEntityPlayer(World worldIn) { + super(worldIn); + } + + // PAIL: decrementTimeUntilPortal + @Redirect(method = "I()V", at = @At(value = "FIELD", target = ENTITY_PLAYER_MP_PORTAL_COOLDOWN_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) + public void fixupPortalCooldown(EntityPlayer self, int modifier) { + int ticks = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks(); + this.portalCooldown = Math.max(0, this.portalCooldown - ticks); + } +} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityZombieVillager.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityZombieVillager.java new file mode 100644 index 000000000..d151aff6b --- /dev/null +++ b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinEntityZombieVillager.java @@ -0,0 +1,47 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package io.akarin.server.mixin.realtime; + +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.Redirect; + +import io.akarin.api.internal.mixin.IMixinRealTimeTicking; +import net.minecraft.server.EntityZombieVillager; + +@Mixin(value = EntityZombieVillager.class, remap = false) +public abstract class MixinEntityZombieVillager { + private static final String ENTITY_ZOMBIE_GET_CONVERSION_BOOST_METHOD = "Lnet/minecraft/entity/monster/EntityZombieVillager;du()I"; // INVOKE: getConversionProgress + + @Shadow(aliases = "du") protected abstract int getConversionProgress(); + + // PAIL: onUpdate + @Redirect(method = "B_()V", at = @At(value = "INVOKE", target = ENTITY_ZOMBIE_GET_CONVERSION_BOOST_METHOD, ordinal = 0)) + public int fixupConversionTimeBoost(EntityZombieVillager self) { + int ticks = (int) ((IMixinRealTimeTicking) self.getWorld()).getRealTimeTicks(); + return this.getConversionProgress() * ticks; + } +} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinMinecraftServer.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinMinecraftServer.java new file mode 100644 index 000000000..54aabc2a0 --- /dev/null +++ b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinMinecraftServer.java @@ -0,0 +1,30 @@ +package io.akarin.server.mixin.realtime; + +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.akarin.api.internal.mixin.IMixinRealTimeTicking; +import net.minecraft.server.MinecraftServer; + +@Mixin(value = MinecraftServer.class, remap = false, priority = 1001) +public abstract class MixinMinecraftServer implements IMixinRealTimeTicking { + private static long lastTickNanos = System.nanoTime(); + private static long realTimeTicks = 1; + + @Inject(method = "C()V", at = @At("HEAD")) // PAIL: fullTick + public void onTickUpdateRealTimeTicks(CallbackInfo ci) { + long currentNanos = System.nanoTime(); + realTimeTicks = (currentNanos - lastTickNanos) / 50000000; + if (realTimeTicks < 1) { + realTimeTicks = 1; + } + lastTickNanos = currentNanos; + } + + @Override + public long getRealTimeTicks() { + return realTimeTicks; + } +} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinPlayerConnection.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinPlayerConnection.java new file mode 100644 index 000000000..de9832de2 --- /dev/null +++ b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinPlayerConnection.java @@ -0,0 +1,58 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package io.akarin.server.mixin.realtime; + +import org.spongepowered.asm.lib.Opcodes; +import org.spongepowered.asm.mixin.Final; +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.Redirect; + +import io.akarin.api.internal.mixin.IMixinRealTimeTicking; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.PlayerConnection; + +@Mixin(value = PlayerConnection.class, remap = false) +public abstract class MixinPlayerConnection { + private static final String NET_HANDLER_PLAY_CHAT_SPAM_FIELD = "Lnet/minecraft/network/PlayerConnection;chatThrottle:I"; + private static final String NET_HANDLER_PLAY_DROP_SPAM_FIELD = "Lnet/minecraft/network/PlayerConnection;itemDropThreshold:I"; + @Shadow private volatile int chatThrottle; + @Shadow(aliases = "j") private int itemDropThreshold; + @Shadow @Final private MinecraftServer minecraftServer; + + // PAIL: update + @Redirect(method = "e()V", at = @At(value = "FIELD", target = NET_HANDLER_PLAY_CHAT_SPAM_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) + public void fixupChatSpamCheck(PlayerConnection self, int modifier) { + int ticks = (int) ((IMixinRealTimeTicking) this.minecraftServer).getRealTimeTicks(); + this.chatThrottle = Math.max(0, this.chatThrottle - ticks); + } + + @Redirect(method = "e()V", at = @At(value = "FIELD", target = NET_HANDLER_PLAY_DROP_SPAM_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) + public void fixupDropSpamCheck(PlayerConnection self, int modifier) { + int ticks = (int) ((IMixinRealTimeTicking) this.minecraftServer).getRealTimeTicks(); + this.itemDropThreshold = Math.max(0, this.itemDropThreshold - ticks); + } +} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinPlayerInteractManager.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinPlayerInteractManager.java new file mode 100644 index 000000000..a4d8e6a66 --- /dev/null +++ b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinPlayerInteractManager.java @@ -0,0 +1,49 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package io.akarin.server.mixin.realtime; + +import org.spongepowered.asm.lib.Opcodes; +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.Redirect; + +import io.akarin.api.internal.mixin.IMixinRealTimeTicking; +import net.minecraft.server.PlayerInteractManager; +import net.minecraft.server.World; + +@Mixin(value = PlayerInteractManager.class, remap = false) +public abstract class MixinPlayerInteractManager { + private static final String PLAYER_INTERACTION_BLOCK_DAMAGE_FIELD = "Lnet/minecraft/server/management/PlayerInteractManager;currentTick:I"; + @Shadow public World world; + @Shadow private int currentTick; + + // PAIL: updateBlockRemoving + @Redirect(method = "a()V", at = @At(value = "FIELD", target = PLAYER_INTERACTION_BLOCK_DAMAGE_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) + public void fixupDiggingTime(PlayerInteractManager self, int modifier) { + int ticks = (int) ((IMixinRealTimeTicking) this.world.getMinecraftServer()).getRealTimeTicks(); + this.currentTick += ticks; + } +} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinTileEntityBrewingStand.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinTileEntityBrewingStand.java new file mode 100644 index 000000000..f96da0345 --- /dev/null +++ b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinTileEntityBrewingStand.java @@ -0,0 +1,48 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package io.akarin.server.mixin.realtime; + +import org.spongepowered.asm.lib.Opcodes; +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.Redirect; + +import io.akarin.api.internal.mixin.IMixinRealTimeTicking; +import net.minecraft.server.TileEntity; +import net.minecraft.server.TileEntityBrewingStand; + +@Mixin(value = TileEntityBrewingStand.class, remap = false) +public abstract class MixinTileEntityBrewingStand extends TileEntity { + private static final String BREWING_STAND_BREW_TIME_FIELD = "Lnet/minecraft/tileentity/TileEntityBrewingStand;brewTime:I"; + @Shadow private int brewTime; + + // PAIL: update + @Redirect(method = "e()V", at = @At(value = "FIELD", target = BREWING_STAND_BREW_TIME_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) + public void fixupBrewTime(TileEntityBrewingStand self, int modifier) { + int ticks = (int) ((IMixinRealTimeTicking) this.getWorld()).getRealTimeTicks(); + this.brewTime = Math.max(0, this.brewTime - ticks); + } +} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinTileEntityFurnace.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinTileEntityFurnace.java new file mode 100644 index 000000000..29c1f8c45 --- /dev/null +++ b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinTileEntityFurnace.java @@ -0,0 +1,64 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package io.akarin.server.mixin.realtime; + +import org.spongepowered.asm.lib.Opcodes; +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.Redirect; + +import io.akarin.api.internal.mixin.IMixinRealTimeTicking; +import net.minecraft.server.MathHelper; +import net.minecraft.server.TileEntity; +import net.minecraft.server.TileEntityFurnace; + +@Mixin(value = TileEntityFurnace.class, remap = false) +public abstract class MixinTileEntityFurnace extends TileEntity { + private static final String FURNACE_BURN_TIME_FIELD = "Lnet/minecraft/tileentity/TileEntityFurnace;burnTime:I"; + private static final String FURNACE_COOK_TIME_FIELD = "Lnet/minecraft/tileentity/TileEntityFurnace;cookTime:I"; + @Shadow private int burnTime; + @Shadow private int cookTime; + @Shadow private int cookTimeTotal; + + // PAIL: update + @Redirect(method = "e()V", at = @At(value = "FIELD", target = FURNACE_BURN_TIME_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) + public void fixupBurnTime(TileEntityFurnace self, int modifier) { + int ticks = (int) ((IMixinRealTimeTicking) this.getWorld()).getRealTimeTicks(); + this.burnTime = Math.max(0, this.burnTime - ticks); + } + + @Redirect(method = "e()V", at = @At(value = "FIELD", target = FURNACE_COOK_TIME_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 0)) + public void fixupCookTime(TileEntityFurnace self, int modifier) { + int ticks = (int) ((IMixinRealTimeTicking) this.getWorld()).getRealTimeTicks(); + this.cookTime = Math.min(this.cookTimeTotal, this.cookTime + ticks); + } + + @Redirect(method = "e()V", at = @At(value = "FIELD", target = FURNACE_COOK_TIME_FIELD, opcode = Opcodes.PUTFIELD, ordinal = 3)) + public void fixupCookTimeCooldown(TileEntityFurnace self, int modifier) { + int ticks = (int) ((IMixinRealTimeTicking) this.getWorld()).getRealTimeTicks(); + this.cookTime = MathHelper.clamp(this.cookTime - (2 * ticks), 0, this.cookTimeTotal); + } +} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinWorld.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinWorld.java new file mode 100644 index 000000000..bfec6c590 --- /dev/null +++ b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinWorld.java @@ -0,0 +1,22 @@ +package io.akarin.server.mixin.realtime; + +import javax.annotation.Nullable; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import io.akarin.api.internal.mixin.IMixinRealTimeTicking; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.World; + +@Mixin(value = World.class, remap = false, priority = 1002) +public abstract class MixinWorld implements IMixinRealTimeTicking { + @Shadow @Nullable public abstract MinecraftServer getMinecraftServer(); + + @Override + public long getRealTimeTicks() { + if (this.getMinecraftServer() != null) { + return ((IMixinRealTimeTicking) this.getMinecraftServer()).getRealTimeTicks(); + } + return 1; + } +} diff --git a/sources/src/main/java/io/akarin/server/mixin/realtime/MixinWorldServer.java b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinWorldServer.java new file mode 100644 index 000000000..88d4da4c0 --- /dev/null +++ b/sources/src/main/java/io/akarin/server/mixin/realtime/MixinWorldServer.java @@ -0,0 +1,61 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package io.akarin.server.mixin.realtime; + +import org.bukkit.World.Environment; +import org.bukkit.generator.ChunkGenerator; +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.akarin.api.internal.mixin.IMixinRealTimeTicking; +import net.minecraft.server.IDataManager; +import net.minecraft.server.MethodProfiler; +import net.minecraft.server.World; +import net.minecraft.server.WorldData; +import net.minecraft.server.WorldProvider; +import net.minecraft.server.WorldServer; + +@Mixin(value = WorldServer.class, remap = false, priority = 1001) +public abstract class MixinWorldServer extends World implements IMixinRealTimeTicking { + + protected MixinWorldServer(IDataManager idatamanager, WorldData worlddata, WorldProvider worldprovider, MethodProfiler methodprofiler, boolean flag, ChunkGenerator gen, Environment env) { + super(idatamanager, worlddata, worldprovider, methodprofiler, flag, gen, env); + } + + @Inject(method = "doTick()V", at = @At("HEAD")) + public void fixTimeOfDay(CallbackInfo ci) { + if (this.getGameRules().getBoolean("doDaylightCycle")) { + // Subtract the one the original tick method is going to add + long diff = this.getRealTimeTicks() - 1; + // Don't set if we're not changing it as other mods might be listening for changes + if (diff > 0) { + this.worldData.setDayTime(this.worldData.getDayTime() + diff); + } + } + } + +} diff --git a/sources/src/main/java/net/minecraft/server/WorldServer.java b/sources/src/main/java/net/minecraft/server/WorldServer.java index f42a74c99..6bdf03579 100644 --- a/sources/src/main/java/net/minecraft/server/WorldServer.java +++ b/sources/src/main/java/net/minecraft/server/WorldServer.java @@ -285,7 +285,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { if (this.everyoneDeeplySleeping()) { if (this.getGameRules().getBoolean("doDaylightCycle")) { long i = this.worldData.getDayTime() + 24000L; - + this.worldData.setDayTime(i - i % 24000L); } diff --git a/sources/src/main/resources/mixins.akarin.core.json b/sources/src/main/resources/mixins.akarin.core.json index c83382892..f30e2ce50 100644 --- a/sources/src/main/resources/mixins.akarin.core.json +++ b/sources/src/main/resources/mixins.akarin.core.json @@ -37,6 +37,22 @@ "lighting.MixinWorldServer", "lighting.MixinChunkProviderServer", + "realtime.MixinWorld", + "realtime.MixinEntity", + "realtime.MixinEntityItem", + "realtime.MixinWorldServer", + "realtime.MixinEntityHuman", + "realtime.MixinEntityPlayer", + "realtime.MixinEntityAgeable", + "realtime.MixinMinecraftServer", + "realtime.MixinEntityInsentient", + "realtime.MixinPlayerConnection", + "realtime.MixinTileEntityFurnace", + "realtime.MixinEntityExperienceOrb", + "realtime.MixinEntityZombieVillager", + "realtime.MixinPlayerInteractManager", + "realtime.MixinTileEntityBrewingStand", + "optimization.WeakBigTree", "optimization.MixinPlayerChunk", "optimization.PandaRedstoneWire",