[Lib] [1.7.9] ProtocolLib 3.4.0 - Safely and easily modify sent and recieved packets

Discussion in 'Resources' started by Comphenix, Sep 15, 2012.

Thread Status:
Not open for further replies.
  1. Offline


    ProtocolLib 1.7.0

    Another update is out. This time I've mainly focused on asynchronous listeners, along with the usual bug fixes. I've also fixed a serious bug that would prevent client packets from being re-transmitted after being cancelled, and this time (hopefully) the update feature should be working properly. Upgrading is recommended.

    The most significant new feature is the ability to move processing of client packets to the main thread. This is important, as client packet are typically processed asynchronously in a client's
    reader thread, and as such cannot access the Bukkit API safely without manual synchronization. This is especially problematic if you need to cancel a packet as a response to the Bukkit API, such as the permission system.

    Currently, you will have to either cancel the packet - which I'd discourage - and sync with the main thread and then re-transmit it outside the filters. Or you could use an asynchronous thread with callSyncMethod and
    wait on the returned future, but that involves a lot of complicated logic. A better method is needed.

    Synchronous processing allows you to run light-weight packet listeners on the main thread without having to deal with synchronization, concurrency or the overhead of an additional thread. It can also process multiple packets per tick with a configurable timeout.

    This, along with 7b9d971, makes it easy to delay light-weight packets to be synchronously processed.

    Here's an example of how to use the new feature:
    1. final Thread mainThread = Thread.currentThread();
    3. manager.getAsynchronousManager().registerAsyncHandler(
    4. new PacketAdapter(this, ConnectionSide.CLIENT_SIDE, Packets.Client.CHAT) {
    5. @Override
    6. public void onPacketReceiving(final PacketEvent event) {
    7. try {
    8. // Proof that we're running on the main thread
    9. if (Thread.currentThread().getId() == mainThread.getId()) {
    10. if (!event.getPlayer().hasPermission("chat.offensive")) {
    11. String message = event.getPacket().getStrings().read(0);
    13. if (message.contains("shit") || message.contains("fuck")) {
    14. event.getPlayer().sendMessage("Bad manners!");
    15. event.setCancelled(true);
    16. }
    17. }
    19. // Add a delay of 2 seconds
    20. if (!event.isCancelled()) {
    21. event.getAsyncMarker().incrementProcessingDelay();
    23. getServer().getScheduler().scheduleSyncDelayedTask(ExampleMod.this, new Runnable() {
    24. @Override
    25. public void run() {
    26. manager.getAsynchronousManager().signalPacketTransmission(event);
    27. }
    28. }, TICKS_PER_SECOND * 2);
    29. }
    31. System.out.println("Processed on the main thread. Cancelled: " + event.isCancelled());
    32. } else {
    33. System.out.println("Something bad happened.");
    34. }
    36. } catch (FieldAccessException e) {
    37. // Error
    38. e.printStackTrace();
    39. }
    40. }
    42. // Remember this!
    43. }).syncStart();

    New features:
    Bug fixes:
    Small fixes:

    If anyone is running into problems modifying Packet5EntityEquipment - specifically, changes to the item stack is propagated to other players - I've found a solution.

    It turns out that Minecraft is rather inconsistent internally, and it will re-use the same equipment packet for single equipment changes, while creating a new equipment packet when a player has logged in or teleported.

    If the same packet is modified multiple times, only the last modification will take effect. The solution is to clone the packet before you modify it (download code):
    1. public class ColorChanger extends JavaPlugin implements Listener {
    2. private ProtocolManager manager;
    4. public void onLoad() {
    5. manager = ProtocolLibrary.getProtocolManager();
    6. }
    8. @Override
    9. public void onEnable() {
    10. manager.addPacketListener(new PacketAdapter(this, ConnectionSide.SERVER_SIDE, Packets.Server.ENTITY_EQUIPMENT) {
    11. @Override
    12. public void onPacketSending(PacketEvent event) {
    13. try {
    14. PacketContainer packet = event.getPacket();
    15. StructureModifier<ItemStack> items = packet.getItemModifier();
    17. ItemStack stack = items.read(0);
    19. // Only modify leather armor
    20. if (stack != null && stack.getType().name().contains("LEATHER")) {
    22. // The problem turned out to be that certain Minecraft functions update
    23. // every player with the same packet for an equipment, whereas other
    24. // methods update the equipment with a different packet per player.
    26. // To fix this, we'll simply clone the packet before we modify it
    27. packet = clonePacket(event.getPacket());
    28. items = packet.getItemModifier();
    29. event.setPacket(packet);
    31. // Color that depends on the player's name
    32. String recieverName = event.getPlayer().getName();
    33. int color = recieverName.hashCode() & 0xFFFFFF;
    35. // Write back the changed object
    36. items.write(0, setColor(stack.clone(), color));
    37. }
    39. } catch (FieldAccessException e) {
    40. getLogger().log(Level.WARNING, "Cannot read field.", e);
    41. }
    42. }
    43. });
    44. }
    46. // Should probably be included with ProtocolLib
    47. private PacketContainer clonePacket(PacketContainer packet) throws FieldAccessException {
    48. PacketContainer copy = manager.createPacket(packet.getID());
    49. StructureModifier<Object> source = packet.getModifier();
    50. StructureModifier<Object> destination = copy.getModifier();
    52. for (int i = 0; i < source.size(); i++) {
    53. destination.write(i, source.read(i));
    54. }
    55. return copy;
    56. }
    58. private static ItemStack setColor(ItemStack item, int color) {
    59. CraftItemStack craftStack = null;
    60. net.minecraft.server.ItemStack itemStack = null;
    62. if (item instanceof CraftItemStack) {
    63. craftStack = (CraftItemStack) item;
    64. itemStack = craftStack.getHandle();
    65. } else if (item instanceof ItemStack) {
    66. craftStack = new CraftItemStack(item);
    67. itemStack = craftStack.getHandle();
    68. }
    69. NBTTagCompound tag = itemStack.tag;
    71. if (tag == null) {
    72. tag = new NBTTagCompound();
    73. tag.setCompound("display", new NBTTagCompound());
    74. itemStack.tag = tag;
    75. }
    77. tag = itemStack.tag.getCompound("display");
    78. tag.setInt("color", color);
    79. itemStack.tag.setCompound("display", tag);
    80. return craftStack;
    81. }
    82. }

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
    Last edited by a moderator: May 28, 2016
    bobacadodl likes this.
  2. Offline


    Does TagApi conflict at all with hiding a player?

    Trying to hide players and yet they are still visible
  3. Offline


    Are you refering to TagAPI by mbaxter by any chance? If you do, you should probably pose that question in the TagAPI thread instead.

    As for TagHelper, I suppose it might show hidden players when you call "refreshPlayer". But that can be fixed by simply skipping that method call if the player is hidden.
  4. Offline


    Oh sorry. I looked at the name of the plugin in the main topic and assumed it was the name.

    I've fixed my problem thanks ^^ Changed your event to be cancellable to cancel the packet being sent.
  5. Offline


    Oh, okay.

    You probably could have used Player.canSee(Player), but I suppose that works as well. And, if you don't mind, I would love to incorporate your changes into my examples. Though, they're not released under the GPL (in fact, if a license isn't specified you may assume the example is under the Apache License), so it's not required. :)
  6. Offline


    Why would I mind..

    Oh and regarding the TagHelper. I notice in your 'refresh player' it gets the players it can refresh from a view distance calculation.

    I had problems with this and just set it to refresh everyone in the server. This is for a small world however where the players are forced to stay in a border.

    My issue was: Players were not being refreshed as they were outside the view distance. They were then teleported to the viewer.

    It meant they did not have a colored name.
  7. Offline


    Is there a way to listen for custom packages sent from a client to the server ? For mods that can interact with a bukkit plugin, at example.

    Now I know how :). Thanks for this really amazing lib!!! [diamond][redflower]

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
    Last edited by a moderator: May 28, 2016
  8. Offline


    ProtocolLib 1.7.1

    • GitHub
    • Jenkins (currently down)
    There's not a whole lot left to add to ProtocolLib, so this is just a small update that corrects a couple of bugs - a minor timing bug and a couple of mistakes in the DataWatcher wrapper. These may cause problems in some rare instances, though they're mostly just an annoying source of spam. Upgrading is not really required, but it will ensure that this will never be an issue.

    In addition, I've added a couple of convenience methods:
    • ProtocolManager.getEntityTrackers(Entity), which will return a list of every player that is tracking/observing the given entity. This is useful if you want to modify an entity locally, and only want to send packets to clients that are actually nearby.
    • PacketContainer.deepClone(), which clones the current packet by "sending it" to a byte buffer and reading it back again. This can be used in the workaround I posted about Packet5EntityEquipment.
    New features:
    Bug fixes:
    Small fixes:
  9. Offline


    How would you change metadata for Packet 40, Entity Metadata? What code should I use to make a player entity appear to always be sprinting or crouching/sneaking?
  10. Offline


    You have to modify the list of watchable objects and set or remove a "flag":
    1. protocolManager.addPacketListener(new PacketAdapter(
    2. this, ConnectionSide.SERVER_SIDE, Packets.Server.ENTITY_METADATA) {
    4. @Override
    5. public void onPacketSending(PacketEvent event) {
    6. // Clone the packet first
    7. event.setPacket(event.getPacket().deepClone());
    9. WrappedDataWatcher watcher = new WrappedDataWatcher(
    10. event.getPacket().getWatchableCollectionModifier().read(0)
    11. );
    12. Byte flags = watcher.getByte(0);
    14. if (flags != null) {
    15. // Add the "entity crouched" flag
    16. // Look in the Wiki for more flags
    17. watcher.setObject(0, (byte) (flags | 0x02), true);
    19. event.getPacket().getWatchableCollectionModifier().write(0, watcher.getWatchableObjects());
    20. }
    21. }
    22. });
    CeramicTitan likes this.
  11. Offline


    ProtocolLib 1.8.0

    • GitHub
    • Jenkins (currently down)
    This update addresses the looming CraftBukkit update (1.4.5-R0.3) that will break a number of plugins that rely on native/internal code (NMS and OBC). ProtocolLib is now compatible with the recent developer build, and as always, any previous releases. So even if you're not having any issues at moment, you should still consider upgrading as it will prevent future problems.

    Unfortunately, I did had to break certain parts of the API (getHandle() now returns Object), which may cause some plugins that depend on ProtocolLib to malfunction. You should downgrade ProtocolLib and wait for those plugins to update, if this problem presets itself.

    New features:
    Bug fixes:
    Small fixes:
  12. Offline


    Feel a bit like a fool but.. I can't seem to make this work. The player sees nothing from his viewpoint.
          p.setMetadata("InvisBlock", new FixedMetadataValue(sd, 99999));
          PacketContainer newPacket = new PacketContainer(24);
          StructureModifier<Object> newMods = newPacket.getModifier();
          newMods.write(0, p.getMetadata("InvisBlock").get(0).asInt());
          newMods.write(1, (byte) 56);
          newMods.write(2, (int) p.getLocation().getX());
          newMods.write(3, (int) p.getLocation().getY());
          newMods.write(4, (int) p.getLocation().getZ());
          DataWatcher data = new DataWatcher();
          data.a(0, (Object) (byte) 0);
          data.a(12, (Object) (byte) 0);
          data.a(16, (Object) (byte) 0);
          WrappedDataWatcher wData = new WrappedDataWatcher(data);
          newPacket.getDataWatcherModifier().write(0, wData);
          try {
            ProtocolLibrary.getProtocolManager().sendServerPacket(p, newPacket);
          } catch (InvocationTargetException e) {
    What should be happening is a ghast appears at the clients head.

    Edit: Nvrm. Just noticed when the chunks hadn't loaded that the ghast was sitting at 0,0,0
    Comphenix likes this.
  13. Offline


    Yeah, you need to multiply your coordinates by 32:
    1. public void sendPacket(Player p) {
    2. PacketContainer newPacket = new PacketContainer(24);
    3. WrappedDataWatcher dataWatcher = new WrappedDataWatcher();
    5. newPacket.getIntegers().
    6. write(0, 500).
    7. write(1, (int) EntityType.GHAST.getTypeId()).
    8. write(2, (int) (p.getLocation().getX() * 32)).
    9. write(3, (int) (p.getLocation().getY() * 32)).
    10. write(4, (int) (p.getLocation().getZ() * 32));
    12. dataWatcher.setObject(0, (byte) 0);
    13. dataWatcher.setObject(12, (byte) 0);
    14. dataWatcher.setObject(16, (byte) 0);
    15. newPacket.getDataWatcherModifier().
    16. write(0, ghastWatcher);
    18. try {
    19. ProtocolLibrary.getProtocolManager().sendServerPacket(p, newPacket);
    20. e.printStackTrace();
    21. }
    22. }

    In addition, you don't have to construct the data watcher yourself. You can get the default watcher object with a little hack (download):
    1. @Override
    2. public void onEnable() {
    3. ghastWatcher = getDefaultWatcher(getServer().getWorlds().get(0), EntityType.GHAST);
    5. for (WrappedWatchableObject object : ghastWatcher)
    6. System.out.println(object);
    7. }
    9. public void sendPacket(Player p) {
    10. PacketContainer newPacket = new PacketContainer(24);
    12. newPacket.getIntegers().
    13. write(0, 500).
    14. write(1, (int) EntityType.GHAST.getTypeId()).
    15. write(2, (int) (p.getLocation().getX() * 32)).
    16. write(3, (int) (p.getLocation().getY() * 32)).
    17. write(4, (int) (p.getLocation().getZ() * 32));
    19. newPacket.getDataWatcherModifier().
    20. write(0, ghastWatcher);
    22. try {
    23. ProtocolLibrary.getProtocolManager().sendServerPacket(p, newPacket);
    24. e.printStackTrace();
    25. }
    26. }
    28. public WrappedDataWatcher getDefaultWatcher(World world, EntityType type) {
    29. Entity entity = world.spawnEntity(new Location(world, 0, 256, 0), type);
    30. WrappedDataWatcher watcher = WrappedDataWatcher.getEntityWatcher(entity).deepClone();
    32. entity.remove();
    33. return watcher;
    34. }
  14. Offline


    Thanks, But it seems my 'fix' for preventing the players from viewing invisible people isn't that good a fix.
    I was spawning a invisible ghast inside the player.

    You are unable to click anything but the ghast you are sitting inside.
    Comphenix likes this.
  15. Offline


    Oh, that's what you were trying to do. Classic XY problem ...

    The best way to prevent a player from cheating, is to never send the information in the first place. So, use the hidePlayer() and showPlayer() API instead, and then simply allow invisible players to be attacked, if you still want them to take part in PVP.

    This is essentially how Spy does it.

    EDIT: Should probably mention that this will get fixed in 1.4.6.
  16. Offline


    Hi, I'm having a little issue getting this code to work. I am trying to send Packet40EntityMetadata..

    PacketContainer entitymeta = plugin.getProtocolManager().createPacket(40);
    entitymeta.getSpecificModifier(int.class).write(0, player.getEntityId());
    WrappedDataWatcher watcher = new WrappedDataWatcher();
    watcher.setObject(0, (byte)4);
    entitymeta.getDataWatcherModifier().write(0, watcher); //This line gives me an IOOBE (Index out of bounds exception)
    entitymeta.getSpecificModifier(boolean.class).write(0, false);
    Is this the correct way to send the packet?

  17. Offline


    Remember that you have to use JD-GUI and read the actual source code of Minecraft, as described in my tutorial.

    For packet 40, you'll notice that the data watcher is actually converted to a list:
    1. public class Packet40EntityMetadata extends Packet
    2. {
    3. public int a;
    4. private List b;
    6. public Packet40EntityMetadata()
    7. {
    8. }
    10. public Packet40EntityMetadata(int paramInt, DataWatcher paramDataWatcher, boolean paramBoolean)
    11. {
    12. this.a = paramInt;
    13. if (paramBoolean)
    14. this.b = paramDataWatcher.c();
    15. else
    16. this.b = paramDataWatcher.b();
    17. }
    18. //ect..

    Here, paramBoolean (if TRUE) instructs Minecraft to save bandwidth by only sending watchable objects that have changed (i.e. are dirty) since last time the client was updated. For simplicity, you can just assume that everything has changed. It's only an optimization.

    So - all you need to do, is convert the WrappedDataWatcher to a list and save that instead. You can do that like so:
    1. entityMeta.getWatchableCollectionModifier().write(0, watcher.getWatchableObjects());
  18. Offline


    Oh, thanks. I was doing it with packet parameters. Not the fields :p
  19. Offline


    Think you can update the OP and change the download link to the latest?
    Comphenix likes this.
  20. Offline


    Oops. :p

    I completely forgot.
  21. Offline


    1. PacketContainer packet = new PacketContainer(5);
    2. StructureModifier<Object> mods = packet.getModifier();
    3. mods.write(0, entityId);
    4. mods.write(1, 4); //Helmet
    5. mods.write(2, new CraftItemStack(new ItemStack(Material.STONE)).getHandle());
    6. ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet);

    This crashes the player.
    Any particular reason?

    It should be changing their helmet to a stone block.

    When looking at the player crash log. It says array out of bounds. And yet I can't see whats wrong with it..
  22. Offline


    I don't believe the player is supposed to receive these packets with itself as target the first place.

    If you need to know what packets to send, and when, you can always use the packet command in ProtocolLib. For instance, by calling "packet add server 5" in console, I don't get any packets containing a player ID when a single player logs in.

    But I do get the following after a second player has entered the server:
    2012-12-19 18:48:32 |INFO| aadnk|/| logged in with entity id 43 at (|world| 133.8209799629923, 64.0, 8.357548973310095)
    2012-12-19 18:50:53 |INFO| Acirium|/| logged in with entity id 28414 at (|world| 129.72922391367598, 64.0, 7.082568281302068)
    2012-12-19 18:50:53 |INFO| |ProtocolLib| Sent ENTITY_EQUIPMENT (5) to aadnk:
    { a = 28414, b = 4, c = { count = 1, b = 0, id = 306, tag = NULL, damage = 0, f = NULL } }
    2012-12-19 18:50:53 |INFO| |ProtocolLib| Sent ENTITY_EQUIPMENT (5) to Acirium:
    { a = 9849, b = 0, c = { count = 1, b = 0, id = 276, tag = NULL, damage = 0, f = NULL } }
    2012-12-19 18:50:53 |INFO| |ProtocolLib| Sent ENTITY_EQUIPMENT (5) to Acirium:
    { a = 9849, b = 4, c = { count = 1, b = 0, id = 310, tag = NULL, damage = 0, f = NULL } }
    2012-12-19 18:50:54 |INFO| |ProtocolLib| Sent ENTITY_EQUIPMENT (5) to aadnk:
    { a = 28414, b = 4, c = { count = 1, b = 0, id = 306, tag = NULL, damage = 0, f = NULL } }
    It's clear that ENTITY_EQUIPMENT is only sent for opposing players. But what is sent to the player, in that case?

    I made a small test plugin to determine exactly that:
    1. target.getInventory().setHelmet(new ItemStack(Material.IRON_HELMET));

    I then added the most likely suspect, SET_SLOT (103), and executed the code above on "aadnk":
    2012-12-19 18:55:52 |INFO| |ProtocolLib| Sent ENTITY_EQUIPMENT (5) to Acirium:
    { a = 9849, b = 4, c = { count = 1, b = 0, id = 306, tag = NULL, damage = 0, f = NULL } }
    2012-12-19 18:55:52 |INFO| |ProtocolLib| Sent SET_SLOT (103) to aadnk:
    { a = 0, b = 5, c = { count = 1, b = 0, id = 306, tag = NULL, damage = 0, f = NULL } }
    This is pretty definitive. So, send SET_SLOT to update the armor for the current player, and ENTITY_EQUIPMENT to update the armor of other players in the perspective of the current player.

    ProtocolLib 1.8.1

    This is a minor update that only contains only a few bug fixes. However, plugins that rely on ProtocolLib to convert between CraftItemStack and a Bukkit ItemStack may cause problems and crash. In addition, a issue with DisguiseCraft has been fixed.

    If you experience these problems in any way, please upgrade.

    New features
    Bug fixes
    Small fixes

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
    Last edited by a moderator: May 28, 2016
    bobacadodl likes this.
  23. Offline


    Oh silly me.

    And I didn't know about that command :D

    Makes it all a lot easier.

    With the new updates featuring renamed packages.
    Will ProtocolLib soar in size?
  24. Offline


    Not really. I use reflection to work around the change, and instead rely on my own version check. :p

    I've already used reflection extensively to handle changes in NMS due to Mojang's obfuscation, which could be trivially extended to cover the package versioning too. But with version check on startup, the end result ought to be the same.
  25. Offline


    Another question. I'm going to be building my own CB for the server. Taking out the '.v${minecraft_version}' in pom.xml.

    ProtocolLib still be compatible right.
  26. Offline


    Yes, but other plugins might not though.
  27. Offline


    Heh. Just looked back at my previous question. Sorry about making you answer such a stupid question.
    Pretty tired atm.

    Do you have a ETA on a protocol lib release. Or are you waiting for a beta build of cb?

    ProtocolLib is pretty awesome. Once you understand how, its dead easy to use.

    We use it in a minigames server which normally at peaktime has 150+ players.
  28. Offline


    A beta or release build would certainly make me expedite the next official release on BukkitDev, but until then I'll just keep on posting developer builds in the comment section and stick to my weekly release schedule.

    If people are 're running a developer build of CraftBukkit, they should be able find a developer build of each plugin too - so, I'm not too worried.
  29. Offline



    I just tried to use ProtocolLib for modifying SignUpdate packets, but I always get something like this:

    com.comphenix.protocol.reflect.FieldAccessException: Field index must be within 0 - count
        at com.comphenix.protocol.reflect.StructureModifier.read(StructureModifier.java:165)
        at me.blablubbabc.insigns.InSigns.change(InSigns.java:77)
        at me.blablubbabc.insigns.InSigns.access$0(InSigns.java:74)
        at me.blablubbabc.insigns.InSigns$2.onPacketSending(InSigns.java:58)
        at com.comphenix.protocol.injector.SortedPacketListenerList.invokePacketSending(SortedPacketListenerList.java:70)
        at com.comphenix.protocol.injector.PacketFilterManager.handlePacket(PacketFilterManager.java:402)
        at com.comphenix.protocol.injector.PacketFilterManager.invokePacketSending(PacketFilterManager.java:382)
        at com.comphenix.protocol.injector.player.PlayerInjector.handlePacketSending(PlayerInjector.java:533)
        at com.comphenix.protocol.injector.player.NetworkServerInjector.handlePacketSending(NetworkServerInjector.java:52)
        at com.comphenix.protocol.injector.player.NetworkServerInjector$1.intercept(NetworkServerInjector.java:158)
        at net.minecraft.server.v1_4_5.NetServerHandler$$EnhancerByCGLIB$$eb6ec45a.sendPacket(<generated>)
        at com.lishid.orebfuscator.internal.v1_4_5.ChunkQueue.updateTileEntity(ChunkQueue.java:204)
        at com.lishid.orebfuscator.internal.v1_4_5.ChunkQueue.processOutput(ChunkQueue.java:149)
        at com.lishid.orebfuscator.internal.v1_4_5.ChunkQueue.isEmpty(ChunkQueue.java:115)
        at net.minecraft.server.v1_4_5.EntityPlayer.j_(EntityPlayer.java:155)
        at net.minecraft.server.v1_4_5.World.entityJoinedWorld(World.java:1333)
        at net.minecraft.server.v1_4_5.WorldServer.entityJoinedWorld(WorldServer.java:546)
        at net.minecraft.server.v1_4_5.World.playerJoinedWorld(World.java:1315)
        at net.minecraft.server.v1_4_5.World.tickEntities(World.java:1193)
        at net.minecraft.server.v1_4_5.WorldServer.tickEntities(WorldServer.java:444)
        at net.minecraft.server.v1_4_5.MinecraftServer.r(MinecraftServer.java:579)
        at net.minecraft.server.v1_4_5.DedicatedServer.r(DedicatedServer.java:222)
        at net.minecraft.server.v1_4_5.MinecraftServer.q(MinecraftServer.java:493)
        at net.minecraft.server.v1_4_5.MinecraftServer.run(MinecraftServer.java:426)
        at net.minecraft.server.v1_4_5.ThreadServerApplication.run(SourceFile:856)
    Caused by: java.lang.IndexOutOfBoundsException: Out of bounds
        ... 25 more
    I tried using http://wiki.vg/Protocol#Update_Sign_.280x82.29 with something like this:

    PacketContainer result = protocolManager.createPacket(0x82);
            result.getSpecificModifier(int.class).write(0, psign.getSpecificModifier(int.class).read(0));
            result.getSpecificModifier(short.class).write(0, psign.getSpecificModifier(short.class).read(0));
            result.getSpecificModifier(int.class).write(1, psign.getSpecificModifier(int.class).read(1));
            String[] lin = {
    //...some stuff here .. and the the string part //of the signs (lin is a String[]) :
    result.getSpecificModifier(String.class).write(0, lin[0]);
            result.getSpecificModifier(String.class).write(1, lin[1]);
            result.getSpecificModifier(String.class).write(2, lin[2]);
            result.getSpecificModifier(String.class).write(3, lin[3]);
    I also tried using int instead of short for the y-coord. I guess it's something with the indexes ?

    Thanks for this awesome api and I hope you can help me with this :)

  30. Offline


    I would just like to say that I love you so much for making this library.
    I am not begging for an update but I would certainly appreciate if you updated this library to 1.4.6 R1.0 if possible ;)
Thread Status:
Not open for further replies.

Share This Page