net.labymod.serverapi.LabyModAPI   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 123
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 14
eloc 50
dl 0
loc 123
c 1
b 0
f 0
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A writeString(ByteBuf,String) 0 8 2
A getBytesToSend(Map) 0 11 2
A writeVarIntToBuffer(ByteBuf,int) 0 7 2
A readString(ByteBuf,int) 0 16 4
A getBytesToSend(String,String) 0 16 1
A readVarIntFromBuffer(ByteBuf) 0 14 3
1
package net.labymod.serverapi;
2
3
import com.google.gson.JsonObject;
4
import io.netty.buffer.ByteBuf;
5
import io.netty.buffer.Unpooled;
6
import io.netty.handler.codec.DecoderException;
7
import io.netty.handler.codec.EncoderException;
8
9
import java.nio.charset.Charset;
10
import java.util.Map;
11
12
/**
13
 * Class created by qlow | Jan
14
 */
15
public class LabyModAPI {
16
17
    /**
18
     * Gets the bytes we should send to a player to update the permissions
19
     *
20
     * @param permissions a map containing the permissions
21
     * @return the byte array that should be the payload
22
     */
23
    public byte[] getBytesToSend( Map<Permission, Boolean> permissions ) {
24
        // Creating a json object we will put the permissions in
25
        JsonObject object = new JsonObject();
26
27
        // Adding the permissions to the json object
28
        for ( Map.Entry<Permission, Boolean> permissionEntry : permissions.entrySet() ) {
29
            object.addProperty( permissionEntry.getKey().name(), permissionEntry.getValue() );
30
        }
31
32
        // Returning the byte array
33
        return getBytesToSend( "PERMISSIONS", object.toString() );
34
    }
35
36
    /**
37
     * Gets the bytes that are required to send the given message
38
     *
39
     * @param messageKey      the message's key
40
     * @param messageContents the message's contents
41
     * @return the byte array that should be the payload
42
     */
43
    public byte[] getBytesToSend( String messageKey, String messageContents ) {
44
        // Getting an empty buffer
45
        ByteBuf byteBuf = Unpooled.buffer();
46
47
        // Writing the message-key to the buffer
48
        writeString( byteBuf, messageKey );
49
50
        // Writing the contents to the buffer
51
        writeString( byteBuf, messageContents );
52
53
        // Copying the buffer's bytes to the byte array
54
        byte[] bytes = new byte[byteBuf.readableBytes()];
55
        byteBuf.readBytes( bytes );
56
57
        // Returning the byte array
58
        return bytes;
59
    }
60
61
    /**
62
     * Writes a varint to the given byte buffer
63
     *
64
     * @param buf   the byte buffer the int should be written to
65
     * @param input the int that should be written to the buffer
66
     */
67
    private void writeVarIntToBuffer( ByteBuf buf, int input ) {
68
        while ( (input & -128) != 0 ) {
69
            buf.writeByte( input & 127 | 128 );
70
            input >>>= 7;
71
        }
72
73
        buf.writeByte( input );
74
    }
75
76
    /**
77
     * Writes a string to the given byte buffer
78
     *
79
     * @param buf    the byte buffer the string should be written to
80
     * @param string the string that should be written to the buffer
81
     */
82
    private void writeString( ByteBuf buf, String string ) {
83
        byte[] abyte = string.getBytes( Charset.forName( "UTF-8" ) );
84
85
        if ( abyte.length > Short.MAX_VALUE ) {
86
            throw new EncoderException( "String too big (was " + string.length() + " bytes encoded, max " + Short.MAX_VALUE + ")" );
87
        } else {
88
            writeVarIntToBuffer( buf, abyte.length );
89
            buf.writeBytes( abyte );
90
        }
91
    }
92
93
    /**
94
     * Reads a varint from the given byte buffer
95
     *
96
     * @param buf the byte buffer the varint should be read from
97
     * @return the int read
98
     */
99
    public int readVarIntFromBuffer( ByteBuf buf ) {
100
        int i = 0;
101
        int j = 0;
102
103
        byte b0;
104
        do {
105
            b0 = buf.readByte();
106
            i |= (b0 & 127) << j++ * 7;
107
            if ( j > 5 ) {
108
                throw new RuntimeException( "VarInt too big" );
0 ignored issues
show
Best Practice introduced by
Dedicated exceptions should be preferred over throwing the generic Exception.
Loading history...
109
            }
110
        } while ( (b0 & 128) == 128 );
111
112
        return i;
113
    }
114
115
    /**
116
     * Reads a string from the given byte buffer
117
     *
118
     * @param buf       the byte buffer the string should be read from
119
     * @param maxLength the string's max-length
120
     * @return the string read
121
     */
122
    public String readString( ByteBuf buf, int maxLength ) {
123
        int i = this.readVarIntFromBuffer( buf );
124
125
        if ( i > maxLength * 4 ) {
126
            throw new DecoderException( "The received encoded string buffer length is longer than maximum allowed (" + i + " > " + maxLength * 4 + ")" );
127
        } else if ( i < 0 ) {
128
            throw new DecoderException( "The received encoded string buffer length is less than zero! Weird string!" );
129
        } else {
130
            byte[] bytes = new byte[i];
131
            buf.readBytes( bytes );
132
133
            String s = new String( bytes, Charset.forName( "UTF-8" ) );
134
            if ( s.length() > maxLength ) {
135
                throw new DecoderException( "The received string length is longer than maximum allowed (" + i + " > " + maxLength + ")" );
136
            } else {
137
                return s;
138
            }
139
        }
140
    }
141
142
}
143