Jump to content

Recommended Posts

Posted

Hi

 

I used Reflection to do this, perhaps you can implement something similar - it's a bit of a hack but it worked ok.  The code below might help you understand the key ideas behind it.

 

public class ReplacePlayerControllerMPHandler
{
  @SubscribeEvent
  public void worldLoadEvent(WorldEvent.Load event) {
    if (event.world instanceof WorldClient) {
      Minecraft mc = Minecraft.getMinecraft();
      PlayerControllerMP playerControllerMP = mc.playerController;
      if (!(playerControllerMP instanceof PlayerControllerMPHijack)) {
        mc.playerController = PlayerControllerMPHijack.createFromVanilla(playerControllerMP);
      }
    }
  }
}

/**
* Hijack various parts of PlayerControllerMP to extend the block reach distance
*/
@SideOnly(Side.CLIENT)
public class PlayerControllerMPHijack extends PlayerControllerMP {
  private static Method syncCurrentPlayItemMethod;

  public static PlayerControllerMPHijack createFromVanilla(PlayerControllerMP playerControllerMP)
  {
    NetHandlerPlayClient netHandlerPlayClient = ReflectionHelper.getPrivateValue
            (PlayerControllerMP.class, playerControllerMP, "netClientHandler", "field_78774_b");

    PlayerControllerMPHijack retObj = new PlayerControllerMPHijack(Minecraft.getMinecraft(), netHandlerPlayClient);

    WorldSettings.GameType gameType = ReflectionHelper.getPrivateValue(PlayerControllerMP.class, playerControllerMP,
                                                                       "currentGameType", "field_78779_k");

    ReflectionHelper.setPrivateValue(PlayerControllerMP.class, retObj, gameType, "currentGameType", "field_78779_k");
    syncCurrentPlayItemMethod = UsefulFunctions.findMethod(PlayerControllerMP.class,
                                                           new String [] {"syncCurrentPlayItem", "func_78750_j"},
                                                           new Class [] {});
    return retObj;
  }

  private PlayerControllerMPHijack(Minecraft mcIn, NetHandlerPlayClient netHandlerPlayClient)
  {
    super(mcIn, netHandlerPlayClient);
  }

  @Override
  public float getBlockReachDistance()
  {
    EntityPlayerSP player = Minecraft.getMinecraft().thePlayer;
    if (player == null) return super.getBlockReachDistance();
    ItemStack heldItem = player.getHeldItem();
    if (heldItem != null && heldItem.getItem() instanceof ItemStick) {
      ItemStick itemStick = (ItemStick)heldItem.getItem();
      return itemStick.getReachDistance(heldItem, super.getBlockReachDistance());
    } else {
      return super.getBlockReachDistance();
    }
  }

  // copied from base class
  @Override
  public void attackEntity(EntityPlayer playerIn, Entity targetEntity)
  {
    try {
      syncCurrentPlayItemMethod.invoke(this);
    } catch (Exception e) {
      throw new RuntimeException("Could not invoke syncCurrentPlayItem()", e);
    }
//    this.syncCurrentPlayItem();
    AttackMessageToServer attackMessageToServer = new AttackMessageToServer(targetEntity);
    StartupCommon.simpleNetworkWrapper.sendToServer(attackMessageToServer);
    if (getCurrentGameType() != WorldSettings.GameType.SPECTATOR)
    {
      playerIn.attackTargetEntityWithCurrentItem(targetEntity);
    }
  }
}


public class StartupClientOnly
{
  public static void preInitClientOnly()
  {
    MinecraftForge.EVENT_BUS.register(new ReplacePlayerControllerMPHandler());
  }

  public static void initClientOnly()
  {
  }

  public static void postInitClientOnly()
  {
  }
}

 

-TGG

 

 

 

Posted

Do you want to extend reach in matter of attacking, block-harvesting or totally in terms of reach in everything?

There are ways of doing some stuff smooth and nice, but in case of "total-override" - yes, this (not counting ASM) is the only good way.

1.7.10 is no longer supported by forge, you are on your own.

Posted

WorldEvent.Load is responsible for replacing, on client side (since it is client thread that "controls" player), player controller with hijacked one.

 

PlayerControllerMPHijack extends PlayerControllerMP

Is the hijacked version of normal controller that allows you to manipulate reach.

It is possible by overriding methods:

 

getBlockReachDistance()

attackEntity(...)

 

Inside those - you can see that everything is client sided, so you can use you own player from Minecraft.class to e.g get held item.

 

As to reflection magic inside - google "java reflection" - LEARN IT - then, when you do - have look at class ObfuscationReflectionHelper.

Logic behind - dev names are deobfuscated, when you release mod, you need SRGs - that is what those "func_78750_j" are.

 

General questions get general answers - be more precise, or if you don't understand anything - learn more about Java (please).

1.7.10 is no longer supported by forge, you are on your own.

Posted

what does ItemStick, StartupCommon, AttackMessageToServer  and UsefulFunctions refer to?

Hi

 

Most of those you don't need to worry about, they are just other parts of the mod I took the code from. 

 

I forgot to include the UsefulFunctions method, which you will need.

 

  public static Method findMethod(Class clazz, String[] methodNames, Class<?>... methodTypes)
  {
    Exception failed = null;
    for (String methodName : methodNames)
    {
      try
      {
        Method m = clazz.getDeclaredMethod(methodName, methodTypes);
        m.setAccessible(true);
        return m;
      }
      catch (Exception e)
      {
        failed = e;
      }
    }
    throw new ReflectionHelper.UnableToFindMethodException(methodNames, failed);
  }

 

Unfortunately since the server side also checks the reach distance, you will need to do a similar trick on ItemInWorldManager as well.  I don't have sample code for that because I used the extended reach client side only to send an AttackMessageToServer (to drop pigs from the sky onto the player's head) instead of using the vanilla block damaging code, which is in NetHandlerPlayServer.processPlayerDigging().

 

It will be tricky to get right without a fair bit of work to understand the vanilla code, plus trial and error.  If there's an easier way, I don't know what it is.

 

-TGG

 

 

 

 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.