【崩溃解决新思路】运用AI来解决Blur与Somnia的崩溃问题!

查看数: 641 | 评论数: 3 | 收藏 0
关灯 | 提示:支持键盘翻页<-左 右->
    组图打开中,请稍候......
发布时间: 2025-2-1 18:20

正文摘要:

Blur与Somnia Awoken同时安装后。当玩家点击上床,进入睡觉状态后,屏幕上可出现正常的“经验进度条”界面。 但是,当进度条满后,也就是睡觉结束,该起床的时候,会发生一个问题。 对于Cleanroom+Fugue端(1.12.2) ...

回复

喵呜怪 发表于 2025-2-1 18:34:37
3.PacketHandler.java:
————————————
package com.kingrunes.somnia.common;

import com.kingrunes.somnia.Somnia;
import com.kingrunes.somnia.api.capability.CapabilityFatigue;
import com.kingrunes.somnia.api.capability.IFatigue;
import io.netty.buffer.ByteBufInputStream;
import io.netty.buffer.Unpooled;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.NetHandlerPlayServer;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientCustomPacketEvent;
import net.minecraftforge.fml.common.network.FMLNetworkEvent.ServerCustomPacketEvent;
import net.minecraftforge.fml.common.network.internal.FMLProxyPacket;

import javax.annotation.Nullable;
import java.io.DataInputStream;
import java.io.IOException;

public class PacketHandler
{
        /*
         * Handling
         */
        @SubscribeEvent
        public void onServerPacket(ServerCustomPacketEvent event)
        {
                if (event.getPacket().channel().equals(Somnia.MOD_ID))
                        onPacket(event.getPacket(), ((NetHandlerPlayServer)event.getHandler()).player);
        }
       
        @SubscribeEvent
        public void onClientPacket(ClientCustomPacketEvent event)
        {
                if (event.getPacket().channel().equals(Somnia.MOD_ID))
                        onPacket(event.getPacket(), null);
        }
       
        public void onPacket(FMLProxyPacket packet, EntityPlayerMP player)
        {
                DataInputStream in = new DataInputStream(new ByteBufInputStream(packet.payload()));
                try
                {
                        byte id = in.readByte();
                       
                        switch (id)
                        {
                        case 0x00:
                                handleGUIOpenPacket();
                                break;
                        case 0x01:
                                handleWakePacket(player, in);
                                break;
                        case 0x02:
                                handlePropUpdatePacket(in, player);
                                break;
                        case 0x03:
                                handleRightClickBlockPacket(player, in);
                                break;
                        case 0x04:
                                handleRideEntityPacket(player, in);
                                break;
                        }
                }
                catch (IOException e)
                {
                        Somnia.logger.error("Packet handling error", e);
                }
        }

        // CLIENT
        private void handleGUIOpenPacket() {
                Minecraft.getMinecraft().addScheduledTask(() ->
                        Somnia.proxy.handleGUIOpenPacket()
                );
        }
       
        private void handlePropUpdatePacket(DataInputStream in, @Nullable EntityPlayerMP player) throws IOException
        {
                if (player == null || player.world.isRemote) {
                        Minecraft.getMinecraft().addScheduledTask(() -> {
                                try {
                                        Somnia.proxy.handlePropUpdatePacket(in);
                                } catch (IOException e) {
                                        Somnia.logger.error("Prop update error", e);
                                }
                        });
                        return;
                }

                byte target = in.readByte();
                IFatigue props = player.getCapability(CapabilityFatigue.FATIGUE_CAPABILITY, null);

                if (target == 0x01 && props != null) {
                        int b = in.readInt();
                        for (int a=0; a<b; a++)
                        {
                                int val = in.readByte();
                                if (val == 0x00) {
                                        props.setFatigue(in.readDouble());
                                }
                                else if (val == 0x01) {
                                        props.setResetSpawn(in.readBoolean());
                                }
                                else if (val == 0x02) {
                                        props.setSleepNormally(in.readBoolean());
                                }
                        }
                }
        }
       
        private void handleWakePacket(EntityPlayerMP player, DataInputStream in)
        {
                Minecraft.getMinecraft().addScheduledTask(() ->
                        Somnia.proxy.handleWakePacket(player)
                );
        }

        private void handleRightClickBlockPacket(EntityPlayerMP player, DataInputStream in) throws IOException {
                BlockPos pos = new BlockPos(in.readInt(), in.readInt(), in.readInt());
                EnumFacing side = EnumFacing.values()[in.readByte()];
                float hitX = in.readFloat();
                float hitY = in.readFloat();
                float hitZ = in.readFloat();
                player.world.getBlockState(pos).getBlock().onBlockActivated(
                                player.world, pos, player.world.getBlockState(pos), player, EnumHand.MAIN_HAND,
                                side, hitX, hitY, hitZ
                );
        }

        private void handleRideEntityPacket(EntityPlayerMP player, DataInputStream in) throws IOException {
                int entityId = in.readInt();
                Entity entity = player.world.getEntityByID(entityId);
                if (entity != null) {
                        player.startRiding(entity);
                }
        }

        /*
         * Building
         */
        private static PacketBuffer unpooled() {
                return new PacketBuffer(Unpooled.buffer());
        }

        public static FMLProxyPacket buildGUIOpenPacket() {
                PacketBuffer buffer = unpooled();
                buffer.writeByte(0x00);
                return new FMLProxyPacket(buffer, Somnia.MOD_ID);
        }

        public static FMLProxyPacket buildWakePacket() {
                PacketBuffer buffer = unpooled();
                buffer.writeByte(0x01);
                return new FMLProxyPacket(buffer, Somnia.MOD_ID);
        }

        public static FMLProxyPacket buildPropUpdatePacket(int target, int prop, boolean value) {
                PacketBuffer buffer = unpooled();
                buffer.writeByte(0x02);
                buffer.writeByte(target);
                buffer.writeInt(1); // Number of properties
                buffer.writeByte(prop);
                buffer.writeBoolean(value);
                return new FMLProxyPacket(buffer, Somnia.MOD_ID);
        }

        public static FMLProxyPacket buildPropUpdatePacket(int target, int prop, double value) {
                PacketBuffer buffer = unpooled();
                buffer.writeByte(0x02);
                buffer.writeByte(target);
                buffer.writeInt(1);
                buffer.writeByte(prop);
                buffer.writeDouble(value);
                return new FMLProxyPacket(buffer, Somnia.MOD_ID);
        }

        public static FMLProxyPacket buildPropUpdatePacket(int target, int prop, double value, int prop2, String value2) {
                PacketBuffer buffer = unpooled();
                buffer.writeByte(0x02);
                buffer.writeByte(target);
                buffer.writeInt(2); // Number of properties
                buffer.writeByte(prop);
                buffer.writeDouble(value);
                buffer.writeByte(prop2);
                buffer.writeString(value2);
                return new FMLProxyPacket(buffer, Somnia.MOD_ID);
        }

        public static FMLProxyPacket buildRightClickBlockPacket(BlockPos pos, EnumFacing side, float hitX, float hitY, float hitZ) {
                PacketBuffer buffer = unpooled();
                buffer.writeByte(0x03);
                buffer.writeInt(pos.getX());
                buffer.writeInt(pos.getY());
                buffer.writeInt(pos.getZ());
                buffer.writeByte(side.ordinal());
                buffer.writeFloat(hitX);
                buffer.writeFloat(hitY);
                buffer.writeFloat(hitZ);
                return new FMLProxyPacket(buffer, Somnia.MOD_ID);
        }

        public static FMLProxyPacket buildRideEntityPacket(Entity entity) {
                PacketBuffer buffer = unpooled();
                buffer.writeByte(0x04);
                buffer.writeInt(entity.getEntityId());
                return new FMLProxyPacket(buffer, Somnia.MOD_ID);
        }
}
喵呜怪 发表于 2025-2-1 18:33:44
2.ServerTickHandler.java
————————————————————
package com.kingrunes.somnia.server;

import com.kingrunes.somnia.Somnia;
import com.kingrunes.somnia.common.PacketHandler;
import com.kingrunes.somnia.common.SomniaConfig;
import com.kingrunes.somnia.common.util.SomniaState;
import com.kingrunes.somnia.common.util.SomniaUtil;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.play.server.SPacketTimeUpdate;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.world.WorldServer;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent.Phase;
import net.minecraftforge.fml.common.network.internal.FMLProxyPacket;

import javax.annotation.Nullable;
import java.util.Iterator;

import static com.kingrunes.somnia.common.util.SomniaState.*;

public class ServerTickHandler
{
        public static final String TRANSLATION_FORMAT = "somnia.status.%s";
                       
        private static int activeTickHandlers = 0;
       
        public WorldServer worldServer;
        public SomniaState currentState;
       
        public long         lastSleepStart,
                                        currentSleepPeriod;                         // Incremented while mbCheck is true, reset when state is changed
        public long                checkTimer                         = 0,                 // Used to schedule GUI update packets and sleep state checks
                                        lastTpsMillis                = 0,
                                        liTps                                 = 0,                 // Counts ticks
                                        tps                                        = 0;                // Set per second to liTPS, used to work out actual multiplier to send to clients
       
        private double         multiplier                         = SomniaConfig.LOGIC.baseMultiplier;
        private double         worldTimeMultiplier = SomniaConfig.PERFORMANCE.fasterWorldTimeMultiplier;
       
        public ServerTickHandler(WorldServer worldServer)
        {
                this.worldServer = worldServer;
        }       
       
        public void tickStart()
        {
                if (++checkTimer == 10)
                {
                        checkTimer = 0;
                       
                        SomniaState prevState = currentState;
                        currentState = SomniaState.getState(this);
                       
                        if (prevState != currentState)
                        {
                                currentSleepPeriod = 0;
                                if (currentState == ACTIVE) // acceleration started
                                {
                                        lastSleepStart = worldServer.getWorldTime();
                                        activeTickHandlers++;
                                }
                                else if (prevState == ACTIVE) // acceleration stopped
                                {
                                        activeTickHandlers--;
                                       
                                        if (currentState == EXPIRED || currentState == NOT_NOW)
                                                closeGuiWithMessage(currentState.toString());
                                }
                        }
                       
                        if (currentState == ACTIVE || currentState == WAITING_PLAYERS || currentState == COOLDOWN)
                        {
                                FMLProxyPacket packet = PacketHandler.buildPropUpdatePacket(
                                        0x00,
                                        0x00, currentState == ACTIVE ? (double)tps/20d : .0d,
                                        0x01, currentState == ACTIVE ? SomniaUtil.timeStringForWorldTime(worldServer.getWorldTime()) : "f:"+currentState.toString()
                                );
                               
                                Somnia.eventChannel.sendToDimension(packet, worldServer.provider.getDimension());
                        }
                }
               
                if (currentState == ACTIVE)
                        doMultipliedTicking();
        }
       
        private void closeGuiWithMessage(@Nullable String key)
        {
                FMLProxyPacket packet = PacketHandler.buildWakePacket();

                Iterator<EntityPlayer> iter = worldServer.playerEntities.iterator();
                EntityPlayer ep;
                while (iter.hasNext())
                {
                        ep = iter.next();
                        if (ep.isPlayerSleeping())
                        {
                                Somnia.eventChannel.sendTo(packet, (EntityPlayerMP) ep);
                                if (ep.isPlayerSleeping()) // this if might stop random teleporting when players have already woken
                                {
                                        ep.wakeUpPlayer(false, true, true); // Stop clients ignoring GUI close packets (major hax)
                                }
                                if (key != null)
                                        ep.sendMessage(new TextComponentTranslation(String.format(TRANSLATION_FORMAT, key.toLowerCase())));
                        }
                }
        }
       
        private void incrementCounters()
        {
                liTps++;
                currentSleepPeriod++;
        }
       
        private double overflow = .0d;
        private double worldTimeOverflow = .0d;
        private void doMultipliedTicking()
        {
                /*
                 * We can't run 0.5 of a tick,
                 * so we floor the multiplier and store the difference as overflow to be ran on the next tick
                 */
                double target = multiplier + overflow;
                int liTarget = (int) Math.floor(target);
                overflow = target - liTarget;
               
                long delta = System.currentTimeMillis();
                for (int i=0; i<liTarget; i++)
                        doMultipliedServerTicking();
                delta = System.currentTimeMillis() - delta;

                MinecraftServer server = worldServer.getMinecraftServer();
                if (server == null) return;
                server.getPlayerList().sendPacketToAllPlayersInDimension(new SPacketTimeUpdate(worldServer.getTotalWorldTime(), worldServer.getWorldTime(), worldServer.getGameRules().getBoolean("doDaylightCycle")), worldServer.provider.getDimension());
               
                if (delta > (SomniaConfig.LOGIC.delta/activeTickHandlers))
                        multiplier -= .1d;
                else
                        multiplier += .1d;
               
                if (multiplier > SomniaConfig.LOGIC.multiplierCap)
                        multiplier = SomniaConfig.LOGIC.multiplierCap;
               
                if (multiplier < SomniaConfig.LOGIC.baseMultiplier)
                        multiplier = SomniaConfig.LOGIC.baseMultiplier;
               
                long currentTimeMillis = System.currentTimeMillis();
                if (currentTimeMillis-lastTpsMillis > 1000)
                {
                        tps = liTps;
                        liTps = 0;
                        lastTpsMillis = currentTimeMillis;
                }
        }
       
        private void doMultipliedServerTicking()
        {
                FMLCommonHandler.instance().onPreWorldTick(worldServer);
                worldServer.tick();
                worldServer.updateEntities();
                worldServer.getEntityTracker().tick();
                FMLCommonHandler.instance().onPostWorldTick(worldServer);
               
                /*
                 * Work around for making sure fatigue is updated with every tick (including Somnia ticks)
                 */
                for (Object obj : worldServer.playerEntities)
                        Somnia.forgeEventHandler.onPlayerTick(new TickEvent.PlayerTickEvent(Phase.START, (EntityPlayer) obj));
               
                if (SomniaConfig.PERFORMANCE.fasterWorldTime)
                {
                        double target = worldTimeMultiplier + worldTimeOverflow;
                        int liTarget = (int) Math.floor(target);
                        worldTimeOverflow = target - liTarget;
                       
                        worldServer.setWorldTime(worldServer.getWorldTime() + liTarget);
                }
               
                incrementCounters();
        }
}

[ MC百科(mcmod.cn) 除另有声明,所有开放公共编辑的内容均使用 BY-NC-SA 3.0 协议 ]

Minecraft百科CC协议
快速回复 返回顶部 返回列表