[1.7.10] Téléportation vers une autre dimension sans portail



  • Bonjour,

    Je travaille actuellement sur un mod côté serveur qui permet de téléporter un joueur à une position aléatoire dans une région définie d'une dimension. Par exemple, pour un serveur utilisant le mod Lord of the Rings v33.4, il s'agit de faire démarrer un joueur qui aurait choisi la faction Mordor à un emplacement aléatoire à l'intérieur de ce territoire.

    Pour la partie téléportation proprement dite, j'ai écrit le code suivant en m'inspirant de la méthode net.minecraft.entity.player.EntityPlayerMP.travelToDimension(int dimensionNumber)
    Teleports the entity to another dimension. Params: Dimension number to teleport to

    Pour player, dimension, x, y et z définis :

    player.playerNetServerHandler.setPlayerLocation(x, y, z, 0.0F, 0.0F);
    MinecraftServer.getServer().getConfigurationManager().transferPlayerToDimension(player, dimension);
    

    Cela fonctionne apparemment bien... mais seulement pendant une seconde !
    Après le joueur se retrouve retéléporté dans le Nether à côté d'un tout nouveau portail.

    En survolant le code de net.minecraft.server.management.ServerConfigurationManager.transferPlayerToDimension() j'ai l'impression que ça ne fonctionne justement qu'avec un portail.

    D'où mes questions :

    • Est-ce qu'il y a une autre façon de procéder dans le code de Minecraft ou Forge ?
    • Sinon, je pense continuer à reprendre les parties du code de transferPlayerToDimension() qui m'intéressent sans les trucs relatifs aux portails. Est-ce que cela pourrait marcher ?
    • Et si ça ne fonctionne toujours pas, me contenter d'appeler une commande externe (genre /mvtp dans le plugin Multiverse-core ou /mwtp dans le mod Forge Essentials)

    J'utilise Forge v10.13.4.1614.

    Bien cordialement,



  • Bon, ne perdez-pas votre temps, j'ai trouvé une solution beaucoup plus simple via une discussion où quelqu'un rencontrait le même problème :

    player.travelToDimension(dimension);
    player.setPositionAndUpdate(x, y, z);
    

    Quand on va dans la dimension, PUIS que l'on définit les coordonnées souhaitées, il n'y a plus de création de portail, ni d'envoi dans le Nether.

    Bonne soirée,



  • Finalement ce n'est pas aussi simple que cela !

    Il y a toujours un portail du Nether créé au point d'origine, sauf quand celui-ci est dans une zone de spawn protégée.

    Comme c'est mon cas d'usage, je ne l'avais pas remarqué et le fonctionnement m'a longtemps paru normal.
    Mais en faisant des allers et retours entre 2 points de la même dimension situés à quelques blocs l'un de l'autre, j'ai fini par remarquer cette création de portails.

    Du coup, je suis toujours à la recherche d'une solution permettant d'éviter cet effet de bord.

    Peut-être :

    • en protégeant à la volée le point de départ (ça m'étonnerait que ça marche),

    • ou en faisant une téléportation ordinaire soit sous la couche de bedrock, soit en haute altitude, puis ma téléportation interdimensionnelle

    • il y a peut être un événement que je pourrais intercepter ? (création de portail ?)

    D'autres idées ?



  • Bon, en réessayant pas-à-pas les solutions évoquées dans le lien cité précédemment j'ai fini par y arriver...

    J'ai commencé par :

    player.mcServer.getConfigurationManager().transferPlayerToDimension(player, dimension, ((WorldServer) world).getDefaultTeleporter());
    player.setPositionAndUpdate(x + 0.5, y, z + 0.5);
    

    Mais ça crée toujours un portail du Nether au point de départ...

    J'ai continué avec :

    WorldServer ws = player.mcServer.worldServerForDimension(dimension);
    Teleporter teleporter = ws.getDefaultTeleporter();
    player.mcServer.getConfigurationManager().transferPlayerToDimension(player, dimension, teleporter);
    player.setPositionAndUpdate(x + 0.5, y, z + 0.5);
    

    Mais malgré la correction consistant à prendre le téléporteur par défaut de la dimension cible, ça créait toujours un portail du Nether au point de départ 😞

    J'ai appliqué l'exemple donné jusqu'au bout :

    WorldServer ws = player.mcServer.worldServerForDimension(dimension);
    Teleporter teleporter = new MyTeleporter(ws);
    player.mcServer.getConfigurationManager().transferPlayerToDimension(player, dimension, teleporter);
    player.setPositionAndUpdate(x + 0.5, y, z + 0.5);
    

    Plus la classe :

    import net.minecraft.entity.Entity;
    import net.minecraft.util.MathHelper;
    import net.minecraft.world.Teleporter;
    import net.minecraft.world.WorldServer;
    
    public class MyTeleporter extends Teleporter
    {
    	private final WorldServer worldServerInstance;
    
    	public MyTeleporter(WorldServer par1WorldServer)
    	{
    		super(par1WorldServer);
    		this.worldServerInstance = par1WorldServer;
    	}
    
    	@Override
    	public void placeInPortal(Entity entity, double p2, double p3, double p4, float p5)
    	{
    	       int i = MathHelper.floor_double(entity.posX);
    	       int j = MathHelper.floor_double(entity.posY);
    	       int k = MathHelper.floor_double(entity.posZ);
    	       this.worldServerInstance.getBlock(i, j, k); //dummy load to maybe gen chunk
    	       int height = this.worldServerInstance.getHeightValue(i, k);
    	       entity.setPosition( i, height, k );
    	       return;
    	} // dont do ANY portal junk, just grab a dummy block then SHOVE the player setPosition() at height
    }
    

    El là, enfin, ça fonctionne sans créer de portail du Nether !
    IL y a quand même un effet de bord (les mobs du coin deviennent invisibles) mais rien de durable (tout revient à la normale quelques secondes après ou à la reconnexion suivante).

    Il fallait vraiment virer toutes ces saletés de création de portail dans placeInPortal pour en venir à bout !



  • Pour être complet, l'effet de bord avec les mobs invisibles semble ne se produire que quand on se téléporte depuis la même dimension.

    Du coup, j'utilise ce qui précède en inter-dimensionnel, et la voie classique en intra-dimensionnel:

    player.setPositionAndUpdate(targetX, targetY, targetZ);
    

Log in to reply