How do I go about injecting custom, non-mod related packets?

Discussion in 'Plugin Development' started by Cirno, May 2, 2015.

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

    Cirno

    Currently, the PacketPlayOutMap features this ugly loop:
    Code:java
    1.  
    2. for(int8 = 0;8 <6; ++8) {
    3. for(int9 = 0;9 <7; ++9) {
    4. this.h[8 +9 *6] =3[4 +8 + (5 +9) * 128];
    5. }
    6. }


    (The snowman's intentional; it's what IntelliJ shows me)

    I wanted to remove that loop, so I basically extended PacketPlayOutMap. However, trying to send the packet doesn't work and kicks the player for "Can't serialize unregistered packet". I've tried to inject the packet into EnumProtocol but no dice. Anyone got a form of "custom packet" injection working?
     
  2. Offline

    Totom3

    Why would you want to do that in the first place? Are you trying to find the meaning of this code?
     
  3. Offline

    xTrollxDudex

  4. Offline

    Cirno

    Been trying to work with that code; no cigar. I've found some code online elsewhere that looks promising though. Just trying to throw stuff at it to work.

    The first post explains why. PacketPlayOutMap has an ugly loop that becomes useless if the data you pass it is 128x128. On top of that, the rapid creation and discardation of PacketPlayOutMap's slightly annoys me.
     
  5. Offline

    megamichiel

    Well, what you can do (and what I have done some times), is put the map packet class inside your server jar in net/minecraft/server/<serverversion>/, make sure you have compiled it in that package too.
    Edit: Would you mind showing what your current class looks like?
     
  6. Offline

    xTrollxDudex

    Actually you should probably replace the instance of the encoder with your own version in the channel pipeline. Otherwise, you will need to do replace the actual class to make it work, or play with the NetworkManager's packet registry attribute.
     
  7. Offline

    Cirno

    I actually managed to get it to work; what I did was basically create a "proxy" class for BiMaps (ProxyBiMap). From there, I made get(key) check another BiMap's proxy list; if the proxy list had "key", it would return another "key" that worked with that class, otherwise, get the value from the original BiMap. That way, PacketPlayOutMapNoLoop was disguised as PacketPlayOutMap when it was requested. I also had to work around the inverse() logic to return a new ProxyBiMap that essentially had the same proxy list and original BiMap, all just inversered.

    I'm still slightly annoyed by the PacketPlayOutMap's constructor loop and how it doesn't check if the data is already max size and doesn't need "resizing" to a 128x128 array. I guess I can understand it since Mojang/Microsoft probably never intended maps to be rapidly updating lol

    Code for ProxyBiMap:
    Show Spoiler
    Code:java
    1.  
    2. package ga.nurupeaches.imgmap.nms;
    3.  
    4. import com.google.common.collect.BiMap;
    5. import com.google.common.collect.HashBiMap;
    6.  
    7. import javax.annotation.Nullable;
    8. import java.util.Map;
    9. import java.util.Set;
    10.  
    11. public class ProxyBiMap<K, V> implements BiMap<K, V> {
    12.  
    13. private BiMap<Object, Object> proxy;
    14. private BiMap<K, V> delegate;
    15. private ProxyBiMap<V, K> inverse;
    16.  
    17. public ProxyBiMap(BiMap<K, V> original){
    18. delegate = original;
    19. proxy = HashBiMap.create();
    20. }
    21.  
    22. public void addProxy(K target, K orig){
    23. proxy.put(target, orig);
    24. }
    25.  
    26. @Overridepublic V get(Object key) {
    27. Object key2 = proxy.get(key);
    28. return key2 != null ? delegate.get(key2) : delegate.get(key);
    29. }
    30.  
    31. @Overridepublic V put(@Nullable K k, @Nullable V v) {
    32. return delegate.put(k, v);
    33. }
    34.  
    35. @Overridepublic V forcePut(@Nullable K k, @Nullable V v) {
    36. return delegate.forcePut(k, v);
    37. }
    38.  
    39. @Overridepublic void putAll(Map<? extends K, ? extends V> map) {
    40. delegate.putAll(map);
    41. }
    42.  
    43. @Overridepublic Set<V> values() {
    44. return delegate.values();
    45. }
    46.  
    47. @Overridepublic BiMap<V, K> inverse() {
    48. if(inverse == null){
    49. inverse = new ProxyBiMap<V, K>(delegate.inverse());
    50. inverse.proxy = proxy.inverse();
    51. }
    52.  
    53. return inverse;
    54. }
    55.  
    56. @Overridepublic int size() {
    57. return delegate.size();
    58. }
    59.  
    60. @Overridepublic boolean isEmpty() {
    61. return delegate.isEmpty();
    62. }
    63.  
    64. @Overridepublic boolean containsKey(Object key) {
    65. return delegate.containsKey(key);
    66. }
    67.  
    68. @Overridepublic boolean containsValue(Object value) {
    69. return delegate.containsValue(value);
    70. }
    71.  
    72. @Overridepublic void clear() {
    73. delegate.clear();
    74. }
    75.  
    76. @Overridepublic V remove(Object key) {
    77. return delegate.remove(key);
    78. }
    79.  
    80. @Overridepublic Set<K> keySet() {
    81. return delegate.keySet();
    82. }
    83.  
    84. @Overridepublic Set<Entry<K, V>> entrySet() {
    85. return delegate.entrySet();
    86. }
    87.  
    88. @Overridepublic boolean equals(Object o) {
    89. return delegate.equals(o);
    90. }
    91.  
    92. @Overridepublic int hashCode() {
    93. return delegate.hashCode();
    94. }
    95.  
    96. }
     
  8. Offline

    xTrollxDudex

    @Cirno
    There's a Guava class for delegated collections classes, not sure what it's called but I'm sure it will shorten up your code :p
     
Thread Status:
Not open for further replies.

Share This Page