Minecraft Forge EntityJoinWorldEvent 返回错误位置!错误

2024-03-17

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

I'm trying to set a player's location every time they join or re-join a world. It always works the first time (e.g. run and join the world. See first screen shot).First appearance in World - works as expected

在世界各地移动了一会儿,然后退出该世界并返回(同一会话,没有关闭 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:为 setLocationAndAngles 使用正确的加入游戏侦听器 https://stackoverflow.com/questions/35460996/minecraft-forge-using-correct-join-game-listener-for-setlocationandangles但没有骰子(不同的行为)。

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

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秒),但错误仍然发生。


“位置不对!”当实体被添加到从其坐标来看不应该位于其中的块时使用。

这是哪里(在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;
    }
}

注意i and j(块坐标)在更新玩家位置后不会改变。所以当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测试。
  • (至少根据命令传送),你需要传送EntityPlayerMP不同的是,使用EntityPlayerMP.playerNetServerHandler.setPlayerLocation.

要解决这个问题,您需要将传送延迟 1 个刻度。我不太确定规范的锻造方法是什么,但这样的方法应该有效:

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();
            }
        }
    }
}

另请注意,要使用TickEvent,您需要注册到与您使用的不同的总线EntityJoinWorldEvent,因此要完全注册此处使用的事件,您可以这样做:

MinecraftForge.EVENT_BUS.register(this);
FMLCommonHandler.instance().bus().register(this);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Minecraft Forge EntityJoinWorldEvent 返回错误位置!错误 的相关文章

  • 在 Java 中连接和使用 Cassandra

    我已经阅读了一些关于 Cassandra 是什么以及它可以做什么的教程 但我的问题是如何在 Java 中与 Cassandra 交互 教程会很好 如果可能的话 有人可以告诉我是否应该使用 Thrift 还是 Hector 哪一个更好以及为什
  • Java new Date() 打印

    刚刚学习 Java 我知道这可能听起来很愚蠢 但我不得不问 System out print new Date 我知道参数中的任何内容都会转换为字符串 最终值是 new Date 返回对 Date 对象的引用 那么它是如何打印这个的呢 Mo
  • 为什么 i++ 不是原子的?

    Why is i Java 中不是原子的 为了更深入地了解 Java 我尝试计算线程中循环的执行频率 所以我用了一个 private static int total 0 在主课中 我有两个线程 主题 1 打印System out prin
  • Play框架运行应用程序问题

    每当我尝试运行使用以下命令创建的新 Web 应用程序时 我都会收到以下错误Play http www playframework org Error occurred during initialization of VM Could no
  • Java JDBC:更改表

    我希望对此表进行以下修改 添加 状态列 varchar 20 日期列 时间戳 我不确定该怎么做 String createTable Create table aircraft aircraftNumber int airLineCompa
  • 如何找到给定字符串的最长重复子串

    我是java新手 我被分配寻找字符串的最长子字符串 我在网上研究 似乎解决这个问题的好方法是实现后缀树 请告诉我如何做到这一点或者您是否有任何其他解决方案 请记住 这应该是在 Java 知识水平较低的情况下完成的 提前致谢 附 测试仪字符串
  • 给定两个 SSH2 密钥,我如何检查它们是否属于 Java 中的同一密钥对?

    我正在尝试找到一种方法来验证两个 SSH2 密钥 一个私有密钥和一个公共密钥 是否属于同一密钥对 我用过JSch http www jcraft com jsch 用于加载和解析私钥 更新 可以显示如何从私钥 SSH2 RSA 重新生成公钥
  • Liferay ClassNotFoundException:DLFileEntryImpl

    在我的 6 1 0 Portal 实例上 带有使用 ServiceBuilder 和 DL Api 的 6 1 0 SDK Portlet 这一行 DynamicQuery query DynamicQueryFactoryUtil for
  • Spring Data JPA 应用排序、分页以及 where 子句

    我目前正在使用 Spring JPA 并利用此处所述的排序和分页 如何通过Spring data JPA通过排序和可分页查询数据 https stackoverflow com questions 10527124 how to query
  • 磁模拟

    假设我在 n m 像素的 2D 表面上有 p 个节点 我希望这些节点相互吸引 使得它们相距越远吸引力就越强 但是 如果两个节点之间的距离 比如 d A B 小于某个阈值 比如 k 那么它们就会开始排斥 谁能让我开始编写一些关于如何随时间更新
  • 无法解析插件 Java Spring

    我正在使用 IntelliJ IDEA 并且我尝试通过 maven 安装依赖项 但它给了我这些错误 Cannot resolve plugin org apache maven plugins maven clean plugin 3 0
  • JRE 系统库 [WebSphere v6.1 JRE](未绑定)

    将项目导入 Eclipse 后 我的构建路径中出现以下错误 JRE System Library WebSphere v6 1 JRE unbound 谁知道怎么修它 右键单击项目 特性 gt Java 构建路径 gt 图书馆 gt JRE
  • 总是使用 Final?

    我读过 将某些东西做成最终的 然后在循环中使用它会带来更好的性能 但这对一切都有好处吗 我有很多地方没有循环 但我将 Final 添加到局部变量中 它会使速度变慢还是仍然很好 还有一些地方我有一个全局变量final 例如android Pa
  • 如何在控制器、服务和存储库模式中使用 DTO

    我正在遵循控制器 服务和存储库模式 我只是想知道 DTO 在哪里出现 控制器应该只接收 DTO 吗 我的理解是您不希望外界了解底层域模型 从领域模型到 DTO 的转换应该发生在控制器层还是服务层 在今天使用 Spring MVC 和交互式
  • 如何从泛型类调用静态方法?

    我有一个包含静态创建方法的类 public class TestClass public static
  • 玩!框架:运行“h2-browser”可以运行,但网页不可用

    当我运行命令时activator h2 browser它会使用以下 url 打开浏览器 192 168 1 17 8082 但我得到 使用 Chrome 此网页无法使用 奇怪的是它以前确实有效 从那时起我唯一改变的是JAVA OPTS以启用
  • 捕获的图像分辨率太大

    我在做什么 我允许用户捕获图像 将其存储到 SD 卡中并上传到服务器 但捕获图像的分辨率为宽度 4608 像素和高度 2592 像素 现在我想要什么 如何在不影响质量的情况下获得小分辨率图像 例如我可以获取或设置捕获的图像分辨率为原始图像分
  • 将 List 转换为 JSON

    Hi guys 有人可以帮助我 如何将我的 HQL 查询结果转换为带有对象列表的 JSON 并通过休息服务获取它 这是我的服务方法 它返回查询结果列表 Override public List
  • 如何实现仅当可用内存较低时才将数据交换到磁盘的写缓存

    我想将应用程序生成的数据缓存在内存中 但如果内存变得稀缺 我想将数据交换到磁盘 理想情况下 我希望虚拟机通知它需要内存并将我的数据写入磁盘并以这种方式释放一些内存 但我没有看到任何方法以通知我的方式将自己挂接到虚拟机中before an O
  • 节拍匹配算法

    我最近开始尝试创建一个移动应用程序 iOS Android 它将自动击败比赛 http en wikipedia org wiki Beatmatching http en wikipedia org wiki Beatmatching 两

随机推荐