CCr4ft3r / DimensionalThreading-Reforged

Unofficial Forge port of Dimensional Threading
GNU Lesser General Public License v3.0
2 stars 2 forks source link

TickEvent.LevelTickEvent not fired #6

Closed lab3 closed 1 year ago

lab3 commented 1 year ago

I could use a little assistance. I'm looking into a bug report in our mod where some features stop working when DimensionalThreading-Reforged is installed.

https://github.com/iron431/Irons-Spells-n-Spellbooks/issues/10

The problem I'm seeing is that TickEvent.LevelTickEvent event is not fired when "gamerule dimthread_active" is set to true. Soon as you set it to false the event starts firing again. I'm not familiar enough with DimensionalThreading-Reforged to know what is going on but I'm hoping you might be able to point us in the right direction.

lab3 commented 1 year ago

I think I found the issue. In this method in your mixin

    @Inject(method = "tickChildren", at = @At(value = "INVOKE",
        target = "Lnet/minecraft/server/MinecraftServer;getWorldArray()[Lnet/minecraft/server/level/ServerLevel;"))
    public void tickWorlds(BooleanSupplier shouldKeepTicking, CallbackInfo ci) {

There is a loop where each levels tick gets called

            DimThread.swapThreadsAndRun(() -> {
                try {
                    serverWorld.tick(shouldKeepTicking);
                } catch (Throwable throwable) {
                    crash.set(new CrashInfo(serverWorld, throwable));
                }
            }, serverWorld, serverWorld.getChunkSource());

But in the Forge Implementation of tickChildren there is a similar loop where the Forge tick events are being fired in addition to the level's tick method being called.

         net.minecraftforge.event.ForgeEventFactory.onPreLevelTick(serverlevel, p_129954_);
         try {
            serverlevel.tick(p_129954_);
         } catch (Throwable throwable) {
            CrashReport crashreport = CrashReport.forThrowable(throwable, "Exception ticking world");
            serverlevel.fillReportDetails(crashreport);
            throw new ReportedException(crashreport);
         }
         net.minecraftforge.event.ForgeEventFactory.onPostLevelTick(serverlevel, p_129954_);

Here is the full Forge implementation of tickChildren for reference. Unless I'm missing something, I think the forge specific items would need to be implemented in your mixin for full Forge compatibility.

   public void tickChildren(BooleanSupplier p_129954_) {
      this.profiler.push("commandFunctions");
      this.getFunctions().tick();
      this.profiler.popPush("levels");

      for(ServerLevel serverlevel : this.getWorldArray()) {
         long tickStart = Util.getNanos();
         this.profiler.push(() -> {
            return serverlevel + " " + serverlevel.dimension().location();
         });
         if (this.tickCount % 20 == 0) {
            this.profiler.push("timeSync");
            this.playerList.broadcastAll(new ClientboundSetTimePacket(serverlevel.getGameTime(), serverlevel.getDayTime(), serverlevel.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)), serverlevel.dimension());
            this.profiler.pop();
         }

         this.profiler.push("tick");
         net.minecraftforge.event.ForgeEventFactory.onPreLevelTick(serverlevel, p_129954_);

         try {
            serverlevel.tick(p_129954_);
         } catch (Throwable throwable) {
            CrashReport crashreport = CrashReport.forThrowable(throwable, "Exception ticking world");
            serverlevel.fillReportDetails(crashreport);
            throw new ReportedException(crashreport);
         }
         net.minecraftforge.event.ForgeEventFactory.onPostLevelTick(serverlevel, p_129954_);

         this.profiler.pop();
         this.profiler.pop();
         perWorldTickTimes.computeIfAbsent(serverlevel.dimension(), k -> new long[100])[this.tickCount % 100] = Util.getNanos() - tickStart;
      }

      this.profiler.popPush("connection");
      this.getConnection().tick();
      this.profiler.popPush("players");
      this.playerList.tick();
      if (net.minecraftforge.gametest.ForgeGameTestHooks.isGametestEnabled()) {
         GameTestTicker.SINGLETON.tick();
      }

      this.profiler.popPush("server gui refresh");

      for(int i = 0; i < this.tickables.size(); ++i) {
         this.tickables.get(i).run();
      }

      this.profiler.pop();
   }
CCr4ft3r commented 1 year ago

Hi, thx for reporting and the assistance to find the cause of this issue. I will fix it asap. This could probably fix some of other incompatibilities too.

CCr4ft3r commented 1 year ago

Fixed in v1.2.8

lab3 commented 1 year ago

Glad to help