2016-02-19 4 views
5

EclipseのForge 1.8.9(Mars.1リリース(4.5.1))をローカル開発環境で使用する。Minecraft Forge EntityJoinWorldEventが間違った場所を返します!エラー

私は、参加するか、世界に再参加するたびにプレーヤーの場所を設定しようとしています。それは常に最初に動作します(たとえば、世界を走ったり、世界に参加します。最初のスクリーンショットを参照)。 First appearance in World - works as expected

世界を少し動かしてから、その世界からログアウトして戻ってきて(同じセッションでMCを終了して)、世界は表示されず、コンソールにも表示されません。場所は「すべてOK」ログインと同じ場所です。プラスに間違った場所があります!エラー。

Location OK, but World does not appear

コンソールからのエラーはここにある:

[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: 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-3s)を作成しようとしましたが、エラーはまだ発生します。

+0

エンティティの位置に応じて使用するチャンクと一致しないチャンクにエンティティを追加すると、「間違った場所」が発生します。私は生の鍛造源をチェックしなければならないでしょうが、エンティティが追加されている間に位置を変更するのが適切に処理されないようです...私はチャンスが得られたらそれをさらに調べます。偽造バグかもしれない。 – Pokechu22

答えて

0

「場所が間違っています!エンティティがチャンクに追加されるときに使用されます。

はここでどこ(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チェックをする必要はありません - nullはinstanceofは試験に合格することはありません。
  • (少なくともCommandTeleportによると)EntityPlayerMP.playerNetServerHandler.setPlayerLocationを使用してEntityPlayerMPを異なる方法でテレポートする必要があります。

修正するには、テレポートを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(); 
      } 
     } 
    } 
} 

、あなたは完全にここで使用したイベントを登録するので、EntityJoinWorldEventで使用したいよりも、あなたは別のバスに登録する必要があり、TickEventを使用することに注意し、あなたはこれを行うでしょう:

MinecraftForge.EVENT_BUS.register(this); 
FMLCommonHandler.instance().bus().register(this); 
+0

ありがとう、私はおそらく最初のバージョンで実行されますが、私はEODをチェックします。 –

+0

私は単純な答えを試して、それは間違った場所を返しました!たぶん半分の時間。それがどうなっているのか分かりません。私はこれを投稿して以来、私が働いていた以上のものであるため、これを "行く"と言います。あなたのお手伝いをありがとう。 –

+0

@joseph_pindi実際には、私のコードをもう一度見て、私はその半分で間違いを犯しているかもしれません - それは私がチックの間に世界をチェックする別のものと私が作ったリビジョンはありません...私はそれを編集しました。 – Pokechu22

関連する問題