当前位置: 首页 > 知识库问答 >
问题:

Minecraft Forge实体返回错误的位置!错误

狄阳秋
2023-03-14

在本地开发环境中使用Eclipse(Mars.1发行版(4.5.1))中的Forge 1.8.9。

在环游世界一小段时间后,然后注销该世界并返回(同一个会话中,退出并关闭MC),世界将无法出现在控制台中。该位置与“一切正常”登录中的位置相同。另外还有一个错误的位置!错误

控制台的错误如下:

 [05:47:53] [Server thread/INFO]: Player992 joined the game
 [05:47:53] [Server thread/WARN]: Wrong location! (9, 9) should be (9, 6),  EntityPlayerMP['Player992'/2371, l='world', x=145.00, y=73.00, z=145.00]
 [05:48:18] [Server thread/INFO]: Saving and pausing game...
 [05:48:18] [Server thread/INFO]: Saving chunks for level 'world'/Overworld
 [05:48:18] [Server thread/INFO]: Saving chunks for level 'world'/Nether
 [05:48:18] [Server thread/INFO]: Saving chunks for level 'world'/The End

我已经尝试过一些变化,包括Minecraft Forge:使用正确的连接游戏侦听器进行设置位置和角度,但不使用骰子(不同的行为)。

忽略所有不相关的“导入”。它们是我多次尝试的产物。

import net.minecraft.util.ChatComponentText;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumChatFormatting;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent;
//import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.client.event.RenderWorldEvent;
import net.minecraftforge.event.world.WorldEvent;
public class JoinGameLocation {

    @SubscribeEvent
    public void onEntityJoinWorld(EntityJoinWorldEvent event) {
        if (event.entity != null && event.entity instanceof EntityPlayer && !event.entity.worldObj.isRemote) {
        event.entity.setLocationAndAngles(145, 73, 145, 0, 0);
        }
    }

}

我读了一些关于错误位置错误的文章,但有些地方似乎不正确,因为我可能第一次出现在那个位置,所以我不像是出现在一个街区内。我尝试过创建一个短延迟(1-3秒),但错误仍然发生。

共有1个答案

谷梁凌
2023-03-14

"错误的位置!"用于将实体添加到它不应该从其坐标进入的块中。

这里是事件触发的地方(在World.java中)(实际上,还有其他一些地方,但这是玩家在其他实体中使用的地方):

/**
 * Called when an entity is spawned in the world. This includes players.
 */
public boolean spawnEntityInWorld(Entity p_72838_1_)
{
    // do not drop any items while restoring blocksnapshots. Prevents dupes
    if (!this.isRemote && (p_72838_1_ == null || (p_72838_1_ instanceof net.minecraft.entity.item.EntityItem && this.restoringBlockSnapshots))) return false;

    int i = MathHelper.floor_double(p_72838_1_.posX / 16.0D);
    int j = MathHelper.floor_double(p_72838_1_.posZ / 16.0D);
    boolean flag = p_72838_1_.forceSpawn;

    if (p_72838_1_ instanceof EntityPlayer)
    {
        flag = true;
    }

    if (!flag && !this.isChunkLoaded(i, j, true))
    {
        return false;
    }
    else
    {
        if (p_72838_1_ instanceof EntityPlayer)
        {
            EntityPlayer entityplayer = (EntityPlayer)p_72838_1_;
            this.playerEntities.add(entityplayer);
            this.updateAllPlayersSleepingFlag();
        }

        if (net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.EntityJoinWorldEvent(p_72838_1_, this)) && !flag) return false;

        this.getChunkFromChunkCoords(i, j).addEntity(p_72838_1_);
        this.loadedEntityList.add(p_72838_1_);
        this.onEntityAdded(p_72838_1_);
        return true;
    }
}

请注意,更新玩家位置后,ij(区块坐标)不会改变。所以当Chunk时。addEntity(见下文)被称为,但不起作用:

/**
 * Adds an entity to the chunk. Args: entity
 */
public void addEntity(Entity entityIn)
{
    this.hasEntities = true;
    int i = MathHelper.floor_double(entityIn.posX / 16.0D);
    int j = MathHelper.floor_double(entityIn.posZ / 16.0D);

    if (i != this.xPosition || j != this.zPosition)
    {
        logger.warn("Wrong location! (" + i + ", " + j + ") should be (" + this.xPosition + ", " + this.zPosition + "), " + entityIn, new Object[] {entityIn});
        entityIn.setDead();
    }

    // ... rest of the method
}

这会杀死玩家。

我不完全确定它为什么第一次起作用。无论何时,只要你在远程传送到的同一块中登录,它都会起作用,因此,如果你在错误的位置后注销,下次你就会成功登录。

在解决问题之前,我还要注意以下几点:

  • 您不需要使用instanceof进行空值检查-null永远不会通过instanceof测试。
  • (至少根据命令传送),您需要以不同的方式传送EntityPlayerMPs,使用EntityPlayerMP. playerNetServerHandler.setPlayerplace

要解决这个问题,你需要将传送延迟1个滴答。我不太确定canonical forge的方法是什么,但类似的方法应该可以工作:

List<Entity> playersToTeleport = new ArrayList<Entity>();

@SubscribeEvent
public void onEntityJoinWorld(EntityJoinWorldEvent event) {
    if (event.entity instanceof EntityPlayer && !event.entity.worldObj.isRemote) {
        playersToTeleport.add(event.entity);
    }
}

@SubscribeEvent
public void teleportEntiesOnWorldTick(TickEvent.WorldTickEvent event) {
// Make sure that this is the type of tick we want.
if (event.phase == TickEvent.Phase.START && event.type == TickEvent.Type.WORLD) {
        for (Entity entity : playersToTeleport) {
            if (entity.worldObj == event.world) {
                if (entity instanceof EntityPlayerMP) {
                    ((EntityPlayerMP) entity).playerNetServerHandler.setPlayerLocation(145, 73, 145, 0, 0);
                } else {
                    entity.setLocationAndAngles(145, 73, 145, 0, 0);
                }
            }
        }
        playersToTeleport.clear();
    }
}

如果你需要改变玩家的位置,而不是总是去那些特定的坐标,这里有一种方法:

@SubscribeEvent
public void onEntityJoinWorld(EntityJoinWorldEvent event) {
    if (event.entity instanceof EntityPlayer && !event.entity.worldObj.isRemote) {
        queueTeleportNextTick(event.entity, Math.random() * 200 - 100, 73,
                Math.random() * 200 - 100, 0, 0);
    }
}

/**
 * List of teleports to perform next tick.
 */
private List<TeleportInfo> queuedTeleports = new ArrayList<TeleportInfo>();

/**
 * Stores information about a future teleport.
 */
private static class TeleportInfo {
    public TeleportInfo(Entity entity, double x, double y, double z,
            float yaw, float pitch) {
        this.entity = entity;
        this.x = x;
        this.y = y;
        this.z = z;
        this.yaw = yaw;
        this.pitch = pitch;
    }

    public final Entity entity;
    public final double x;
    public final double y;
    public final double z;
    public final float yaw;
    public final float pitch;
}

/**
 * Teleport the given entity to the given coordinates on the next game tick.
 */
public void queueTeleportNextTick(Entity entity, double x, double y,
        double z, float yaw, float pitch) {
    System.out.printf("Preparing to teleport %s to %f, %f, %f%n", entity, x, y, z);
    queuedTeleports.add(new TeleportInfo(entity, x, y, z, yaw, pitch));
}

@SubscribeEvent
public void teleportEntiesOnWorldTick(TickEvent.WorldTickEvent event) {
    // Make sure that this is the type of tick we want.
    if (event.phase == TickEvent.Phase.START && event.type == TickEvent.Type.WORLD) {
        // Perform each teleport
        Iterator<TeleportInfo> itr = queuedTeleports.iterator();
        while (itr.hasNext()) {
            TeleportInfo info = itr.next();
            if (info.entity.worldObj == event.world) {
                System.out.printf("Teleporting %s to %f, %f, %f%n", info.entity, info.x, info.y, info.z);
                if (info.entity instanceof EntityPlayerMP) {
                    // EntityPlayerMPs are handled somewhat differently.
                    ((EntityPlayerMP) info.entity).playerNetServerHandler
                            .setPlayerLocation(info.x, info.y, info.z,
                                    info.pitch, info.yaw);
                } else {
                    info.entity.setLocationAndAngles(info.x, info.y, info.z,
                            info.pitch, info.yaw);
                }
                itr.remove();
            }
        }
    }
}

另外,请注意,要使用ticketvent,您需要注册到一个单独的总线,而不是使用EntityJoinWorldEvent,因此要完全注册此处使用的事件,您需要执行以下操作:

MinecraftForge.EVENT_BUS.register(this);
FMLCommonHandler.instance().bus().register(this);
 类似资料:
  • 问题内容: 我的android应用程序drawable文件夹中有一个jpg图像,分辨率为1000x600。我像这样将图像加载到位图 之后,我打电话返回1500。怎么回事?以及如何获得正确的图像宽度和高度? 问题答案: 这可能是因为密度不同。您的资源可能存储在中等密度的文件夹中,但设备为hdpi。中密度为160dpi,高密度为240dpi。因此,您的位图将缩放为原始大小的1.5倍。有关更多信息,请参

  • 我写了一个二分搜索的递归程序,正如你所看到的,我试图在给定的数组中找到目标=21的位置,然后返回位置为2。但是,我的输出是1。当我调试它匹配att arr[start]=target时,它直接跳到findTheNumber(arr,mid+1,end,target)行;然后下一行,然后返回mid..只是想知道为什么我的返回在“返回开始”时中断了 }

  • 基类控制器里有error方法,用于api的错误消息返回输出 /** * 操作错误跳转的快捷方法 * @access protected * @param mixed $msg 提示信息,若要指定错误码,可以传数组,格式为['code'=>您的错误码,'msg'=>'您的错误消息'] * @param mixed $data 返回的数据 * @par

  • 我有一个配置,我想从指定位置返回自定义错误。然而,我收到的却是标准的nginx错误页面。不过,我可以从未命名的位置获取自定义错误。 为了重现这个问题,我创建了这个简单的基于docker的设置: Dockerfile: 违约形态: 50x错误在这里并不有趣,我已经从nginx docker映像中调整了配置。 使用404以外的东西重定向到指定位置并没有什么区别。 404.html: 然后启动docke

  • 下面的代码旨在用给定的分区键和ROWKEY从表中删除一行。但我在Fiddler中得到以下请求/响应。我怎样才能纠正错误? DELETE https://hireazureStorageAcct.table.core.windows.net/mytable(PartitionKey='sample1',%20rowkey='0001')?timeout=20 http/1.1接受:Applicati

  • 我是JS的学生。我有一段代码返回了一个错误。 这是返回的语法错误。你们能解释一下我做错了什么吗?