md-5 / SpecialSource

Automatic generator and renamer of jar obfuscation mappings.
Other
202 stars 51 forks source link

`FluidState` gets remapped by mistake when running maven `build` #77

Open LoneDev6 opened 2 years ago

LoneDev6 commented 2 years ago

Hello! Seems somehow this Level#getFluidState function calls are not getting remapped correctly, its return type has a wrong remapped name. java.lang.NoSuchMethodError: 'net.minecraft.world.level.material.FluidType net.minecraft.world.level.World.b_(net.minecraft.core.BlockPosition)'

It should be Fluid instead of FluidType, as I can see by decompiling the Spigot jar. public Fluid b_(BlockPosition pos).

Is this normal? Am I missing something? Fluid and FluidType are two different classes in the remapped Spigot jar, this is weird.

Thanks a lot for the help.

LoneDev6 commented 2 years ago

This is the code I use:

FluidState fluid = handle.level.getFluidState(blockposition_mutableblockposition);

It gets converted to

FluidType fluid = handle.t.b_((BlockPosition)blockposition_mutableblockposition);

instead of

Fluid fluid = handle.t.b_((BlockPosition)blockposition_mutableblockposition);

EDIT: The issue was solved with these steps:

md-5 commented 2 years ago

How come you reopened it? The steps you used to solve suggest user error

LoneDev6 commented 2 years ago

Yes totally, I forgot to reclose it. Thanks for your time

LoneDev6 commented 1 year ago

I actually found the real cause of this issue. What I stated above was not the cause.

Steps to reproduce

1

Compile this code:

import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;

public class Test1
{
    public void test(Block block)
    {
        ServerLevel level = ((CraftWorld) block.getWorld()).getHandle();
        BlockPos blockPos = new BlockPos(block.getX(), block.getY(), block.getZ());
        FluidState fluidState = level.getFluidState(blockPos);
        if (!fluidState.isEmpty())
        {
            Fluid fluidType = fluidState.getType();
            level.scheduleTick(blockPos, fluidType, fluidType.getTickDelay(level));
        }
    }
}

2

Run the maven command clean build. See the output remapped code is this working and correct code.

import net.minecraft.core.BlockPosition;
import net.minecraft.server.level.WorldServer;
import net.minecraft.world.level.IWorldReader;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidType;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;

public class Test1 {
  public void test(Block block) {
    WorldServer level = ((CraftWorld)block.getWorld()).getHandle();
    BlockPosition blockPos = new BlockPosition(block.getX(), block.getY(), block.getZ());
    Fluid fluidState = level.b_(blockPos);
    if (!fluidState.c()) {
      FluidType fluidType = fluidState.a();
      level.a(blockPos, fluidType, fluidType.a((IWorldReader)level));
    } 
  }
}

3

Run the maven command build instead of clean build

See the remapper mistakenly remapping FluidState to FluidType.

import net.minecraft.core.BlockPosition;
import net.minecraft.server.level.WorldServer;
import net.minecraft.world.level.IWorldReader;
import net.minecraft.world.level.material.FluidType;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;

public class Test1 {
  public void test(Block block) {
    WorldServer level = ((CraftWorld)block.getWorld()).getHandle();
    BlockPosition blockPos = new BlockPosition(block.getX(), block.getY(), block.getZ());
    FluidType fluidState = level.b_(blockPos);
    if (!fluidState.c()) {
      FluidType fluidType = fluidState.a();
      level.a(blockPos, fluidType, fluidType.a((IWorldReader)level));
    } 
  }
}

4

Now add some random code to the class which SHOULD make maven remove the cached class from the target dir, to regenerate it (which seems not to happen)

import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;

public class Test1
{
    public void test(Block block)
    {
        ServerLevel level = ((CraftWorld) block.getWorld()).getHandle();
        BlockPos blockPos = new BlockPos(block.getX(), block.getY(), block.getZ());
        FluidState fluidState = level.getFluidState(blockPos);
        if (!fluidState.isEmpty())
        {
            Fluid fluidType = fluidState.getType();
            level.scheduleTick(blockPos, fluidType, fluidType.getTickDelay(level));
            int test = 0;
            if(test == 0)
            {
                System.out.println("test");
            }
        }
    }
}

And see again how the Fluid class is mistakenly renamed.


import net.minecraft.core.BlockPosition;
import net.minecraft.server.level.WorldServer;
import net.minecraft.world.level.IWorldReader;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidType;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;

public class Test1 {
  public void test(Block block) {
    WorldServer level = ((CraftWorld)block.getWorld()).getHandle();
    BlockPosition blockPos = new BlockPosition(block.getX(), block.getY(), block.getZ());
    Fluid fluidState = level.b_(blockPos);
    if (!fluidState.c()) {
      FluidType fluidType = fluidState.a();
      level.a(blockPos, fluidType, fluidType.a((IWorldReader)level));
      int test = 0;
      if (test == 0)
        System.out.println("test"); 
    } 
  }
}

This happens because the maven plugin is remapping the code a second time and remaps Fluid by mistake because of the remapping map:

c   net/minecraft/world/level/material/FluidState   net/minecraft/world/level/material/Fluid

c   net/minecraft/world/level/material/Fluid    net/minecraft/world/level/material/FluidType

Temporary solution 1

My solution is to basically run clean build to avoid this from happening but it makes my build time longer.

Temporary solution 2

Separate your plugin into modules and add this plugin into the maven module containing the NMS code. It will force clean up the previous built code even if you run the package command without the clean argument.

 <plugin>
   <artifactId>maven-clean-plugin</artifactId>
   <version>3.2.0</version>
   <executions>
       <execution>
           <id>auto-clean</id>
           <phase>initialize</phase>
           <goals>
               <goal>clean</goal>
           </goals>
       </execution>
   </executions>
</plugin>

Final notes

I'd like to know if you think there is a solution for this. Thanks a lot for your hard work.