diff --git a/Client/src/main/java/org/runite/client/AudioHandler.java b/Client/src/main/java/org/runite/client/AudioHandler.java index fb7cf39a1..6ac7860d2 100644 --- a/Client/src/main/java/org/runite/client/AudioHandler.java +++ b/Client/src/main/java/org/runite/client/AudioHandler.java @@ -20,7 +20,7 @@ public final class AudioHandler { try { if (-1 == var1 && !musicEffectPlaying) { GameObject.method1870(); - } else if (var1 != -1 && (currentTrack != var1 || Class79.method1391(-1)) && musicVolume != 0 && !musicEffectPlaying) { + } else if (var1 != -1 && (currentTrack != var1 || CSConfigCachefile.method1391(-1)) && musicVolume != 0 && !musicEffectPlaying) { method2099(var1, CacheIndex.musicIndex, musicVolume); } currentTrack = var1; @@ -117,13 +117,13 @@ public final class AudioHandler { } } - if (musicEffectPlaying && Class79.method1391(-1)) { + if (musicEffectPlaying && CSConfigCachefile.method1391(-1)) { if (0 != musicVolume && currentTrack != -1) { Class70.method1285(CacheIndex.musicIndex, currentTrack, musicVolume); } musicEffectPlaying = false; - } else if (musicVolume != 0 && currentTrack != -1 && Class79.method1391((byte) -92 + 91)) { + } else if (musicVolume != 0 && currentTrack != -1 && CSConfigCachefile.method1391((byte) -92 + 91)) { TextureOperation12.outgoingBuffer.putOpcode(137); TextureOperation12.outgoingBuffer.writeInt(currentTrack); currentTrack = -1; diff --git a/Client/src/main/java/org/runite/client/CS2Script.java b/Client/src/main/java/org/runite/client/CS2Script.java index 7645d30d2..5544b1896 100644 --- a/Client/src/main/java/org/runite/client/CS2Script.java +++ b/Client/src/main/java/org/runite/client/CS2Script.java @@ -27,7 +27,6 @@ public final class CS2Script extends Linkable { static int anInt3775 = 0; static int anInt2440 = 0; static ReferenceCache aReferenceCache_2442 = new ReferenceCache(50); - static ReferenceCache aReferenceCache_2450 = new ReferenceCache(64); static byte[][][] aByteArrayArrayArray2452; RSInterface aClass11_2438; RSString aClass94_2439; @@ -58,30 +57,6 @@ public final class CS2Script extends Linkable { } } - static Class79 method378(int var0, byte var1) { - try { - Class79 var2 = (Class79) aReferenceCache_2450.get(var0); - if (var2 == null) { - if (var1 < 126) { - return null; - } else { - byte[] var3 = Class101.aClass153_1420.getFile(Class140_Sub7.method2032(var0), var0 & 1023); - var2 = new Class79(); - if (var3 != null) { - var2.method1387(new DataBuffer(var3)); - } - - aReferenceCache_2450.put(var2, var0); - return var2; - } - } else { - return var2; - } - } catch (RuntimeException var4) { - throw ClientErrorException.clientError(var4, "jl.A(" + var0 + ',' + var1 + ')'); - } - } - static void method379() { try { int var2 = Class146.anInt1904 * 128 - -64; diff --git a/Client/src/main/java/org/runite/client/Class79.java b/Client/src/main/java/org/runite/client/CSConfigCachefile.java similarity index 83% rename from Client/src/main/java/org/runite/client/Class79.java rename to Client/src/main/java/org/runite/client/CSConfigCachefile.java index 043e62add..b07173151 100644 --- a/Client/src/main/java/org/runite/client/Class79.java +++ b/Client/src/main/java/org/runite/client/CSConfigCachefile.java @@ -1,14 +1,16 @@ package org.runite.client; +import org.rs09.SystemLogger; + import java.awt.event.KeyEvent; -final class Class79 { +final class CSConfigCachefile { static int anInt1124 = -1; static int anInt1127 = 0; - int anInt1123; - int anInt1125; - int anInt1128; + int lowerBound; + int upperBound; + int parentVarpIndex; static void method1385(int var0, int var1) { @@ -182,31 +184,44 @@ final class Class79 { } } - final void method1387(DataBuffer var1) { + static CSConfigCachefile getCSConfigFileFromVarbitID(int varbitID) { try { - while (true) { - int var3 = var1.readUnsignedByte(); - if (var3 == 0) { - return; + CSConfigCachefile cacheFile = (CSConfigCachefile) VarpHelpers.varbitLookup.get(varbitID); + if (cacheFile == null) { + byte[] fileData = Class101.csConfigFileRAM.getFile(varbitID >>> 10, varbitID & 1023); + cacheFile = new CSConfigCachefile(); + if (fileData != null) { + cacheFile.tryParseConfigFile(new DataBuffer(fileData)); } - this.method1389(var1, var3); + VarpHelpers.varbitLookup.put(cacheFile, varbitID); } + return cacheFile; } catch (RuntimeException var4) { - throw ClientErrorException.clientError(var4, "kk.G(" + (var1 != null ? "{...}" : "null") + ',' + -111 + ')'); + throw ClientErrorException.clientError(var4, "jl.A(" + varbitID + ',' + (byte) 127 + ')'); } } - private void method1389(DataBuffer var1, int var3) { + final void tryParseConfigFile(DataBuffer fileData) { try { - if (1 == var3) { - this.anInt1128 = var1.readUnsignedShort(); - this.anInt1123 = var1.readUnsignedByte(); - this.anInt1125 = var1.readUnsignedByte(); + boolean end = fileData.readUnsignedByte() == 0; + while (!end) { + this.parseConfigFile(fileData); + end = fileData.readUnsignedByte() == 0; } + } catch (RuntimeException var4) { + throw ClientErrorException.clientError(var4, "kk.G(" + (fileData != null ? "{...}" : "null") + ',' + -111 + ')'); + } + } + + private void parseConfigFile(DataBuffer fileData) { + try { + this.parentVarpIndex = fileData.readUnsignedShort(); + this.lowerBound = fileData.readUnsignedByte(); + this.upperBound = fileData.readUnsignedByte(); } catch (RuntimeException var5) { - throw ClientErrorException.clientError(var5, "kk.B(" + (var1 != null ? "{...}" : "null") + ',' + 1 + ',' + var3 + ')'); + throw ClientErrorException.clientError(var5, "kk.B(" + (fileData != null ? "{...}" : "null") + ',' + 1 + ')'); } } diff --git a/Client/src/main/java/org/runite/client/Class101.java b/Client/src/main/java/org/runite/client/Class101.java index 4b1c1272c..bb1cad4d8 100644 --- a/Client/src/main/java/org/runite/client/Class101.java +++ b/Client/src/main/java/org/runite/client/Class101.java @@ -2,7 +2,7 @@ package org.runite.client; final class Class101 { - static CacheIndex aClass153_1420; + static CacheIndex csConfigFileRAM; static Class3_Sub24_Sub4 aClass3_Sub24_Sub4_1421; static Class30 aClass30_1422; static CacheIndex aClass153_1423; @@ -65,7 +65,7 @@ final class Class101 { method1607(46, 78, true, null, null); } - aClass153_1420 = null; + csConfigFileRAM = null; } catch (RuntimeException var2) { throw ClientErrorException.clientError(var2, "nj.A(" + var0 + ')'); } diff --git a/Client/src/main/java/org/runite/client/Class107.java b/Client/src/main/java/org/runite/client/Class107.java index 9723ccd87..8ca5995aa 100644 --- a/Client/src/main/java/org/runite/client/Class107.java +++ b/Client/src/main/java/org/runite/client/Class107.java @@ -34,7 +34,7 @@ final class Class107 { static void method1648(CacheIndex var0) { try { - Class101.aClass153_1420 = var0; + Class101.csConfigFileRAM = var0; } catch (RuntimeException var3) { throw ClientErrorException.clientError(var3, "og.B(" + (var0 != null ? "{...}" : "null") + ',' + 255 + ')'); diff --git a/Client/src/main/java/org/runite/client/Class108.java b/Client/src/main/java/org/runite/client/Class108.java index 58dc2a50f..639db0458 100644 --- a/Client/src/main/java/org/runite/client/Class108.java +++ b/Client/src/main/java/org/runite/client/Class108.java @@ -51,7 +51,7 @@ final class Class108 { int var2 = Class140_Sub7.canvasHeight; int var3 = var2 * 956 / 503; Objects.requireNonNull(Class40.aAbstractSprite_680).method639((Class23.canvasWidth + -var3) / 2, 0, var3, var2); - SequenceDefinition.aClass109_1856 = InterfaceWidget.a(Class79.anInt1124, var0); + SequenceDefinition.aClass109_1856 = InterfaceWidget.a(CSConfigCachefile.anInt1124, var0); Objects.requireNonNull(SequenceDefinition.aClass109_1856).method1667(Class23.canvasWidth / 2 + -(SequenceDefinition.aClass109_1856.width / 2), 18); Class140_Sub2.aBoolean2713 = true; if (var1 > -50) { diff --git a/Client/src/main/java/org/runite/client/Class140_Sub7.java b/Client/src/main/java/org/runite/client/Class140_Sub7.java index 8dd7f8e2c..2e05ab0a2 100644 --- a/Client/src/main/java/org/runite/client/Class140_Sub7.java +++ b/Client/src/main/java/org/runite/client/Class140_Sub7.java @@ -32,7 +32,7 @@ public final class Class140_Sub7 extends GameObject { static boolean method2031(byte var0, boolean var1, int var2, int var3, Class3_Sub2[][][] var4, int var5) { try { - byte var6 = !var1?(byte)(255 & Class79.anInt1127):1; + byte var6 = !var1?(byte)(255 & CSConfigCachefile.anInt1127):1; if(Class158.aByteArrayArrayArray2008[WorldListCountry.localPlane][var2][var3] == var6) { return false; } else if((Unsorted.aByteArrayArrayArray113[WorldListCountry.localPlane][var2][var3] & 4) == 0) { diff --git a/Client/src/main/java/org/runite/client/Class163.java b/Client/src/main/java/org/runite/client/Class163.java index d3774b46f..3d9a32fe3 100644 --- a/Client/src/main/java/org/runite/client/Class163.java +++ b/Client/src/main/java/org/runite/client/Class163.java @@ -1,5 +1,6 @@ package org.runite.client; +import org.rs09.SystemLogger; import org.rs09.client.data.NodeCache; import java.util.Objects; @@ -11,26 +12,4 @@ public class Class163 { public static int localNPCCount = 0; - static void method2209(byte var0, int var1, int var2) { - try { - if (var0 >= -99) { - method2209((byte) 57, -14, 120); - } - - Class79 var3 = CS2Script.method378(var2, (byte) 127); - int var4 = Objects.requireNonNull(var3).anInt1128; - int var6 = var3.anInt1125; - int var5 = var3.anInt1123; - int var7 = Class3_Sub6.anIntArray2288[var6 - var5]; - if (var1 < 0 || var7 < var1) { - var1 = 0; - } - - var7 <<= var5; - TextureOperation39.method281(var1 << var5 & var7 | ~var7 & Class57.varpArray[var4], var4); - } catch (RuntimeException var8) { - throw ClientErrorException.clientError(var8, "wd.K(" + var0 + ',' + var1 + ',' + var2 + ')'); - } - } - } diff --git a/Client/src/main/java/org/runite/client/Class25.java b/Client/src/main/java/org/runite/client/Class25.java index dacd09986..ed231bd4f 100644 --- a/Client/src/main/java/org/runite/client/Class25.java +++ b/Client/src/main/java/org/runite/client/Class25.java @@ -115,7 +115,7 @@ final class Class25 { static void method959() { try { - CS2Script.aReferenceCache_2450.clear(); + VarpHelpers.varbitLookup.clear(); } catch (RuntimeException var2) { throw ClientErrorException.clientError(var2, "ec.B(" + 0 + ')'); diff --git a/Client/src/main/java/org/runite/client/Class3_Sub28_Sub20.java b/Client/src/main/java/org/runite/client/Class3_Sub28_Sub20.java index 89fa25610..05de01b0b 100644 --- a/Client/src/main/java/org/runite/client/Class3_Sub28_Sub20.java +++ b/Client/src/main/java/org/runite/client/Class3_Sub28_Sub20.java @@ -289,8 +289,8 @@ final class Class3_Sub28_Sub20 extends Node { static void method725() { try { if(Class137.method1817() == 2) { - byte var2 = (byte)(255 & Class79.anInt1127 + -4); - int var3 = Class79.anInt1127 % 104; + byte var2 = (byte)(255 & CSConfigCachefile.anInt1127 + -4); + int var3 = CSConfigCachefile.anInt1127 % 104; int var4; int var5; diff --git a/Client/src/main/java/org/runite/client/Class3_Sub6.java b/Client/src/main/java/org/runite/client/Class3_Sub6.java index d03ccd93d..da647c14f 100644 --- a/Client/src/main/java/org/runite/client/Class3_Sub6.java +++ b/Client/src/main/java/org/runite/client/Class3_Sub6.java @@ -6,15 +6,15 @@ final class Class3_Sub6 extends Linkable { static byte[][] softReferenceTestArray; - static int[] anIntArray2288 = new int[32]; + static int[] expectedMinimumValues = new int[32]; static int anInt2291; static { - int var0 = 2; + int accumulator = 2; - for (int var1 = 0; var1 < 32; ++var1) { - anIntArray2288[var1] = -1 + var0; - var0 += var0; + for (int i = 0; i < 32; ++i) { + expectedMinimumValues[i] = -1 + accumulator; + accumulator += accumulator; } anInt2291 = 1; diff --git a/Client/src/main/java/org/runite/client/Class75_Sub3.java b/Client/src/main/java/org/runite/client/Class75_Sub3.java index a9ed520cd..a0164ca0b 100644 --- a/Client/src/main/java/org/runite/client/Class75_Sub3.java +++ b/Client/src/main/java/org/runite/client/Class75_Sub3.java @@ -46,7 +46,7 @@ final class Class75_Sub3 extends Class75 { Class67.aReferenceCache_1013.sweep(5); Texture.aReferenceCache_1146.sweep(5); Class159.aReferenceCache_2016.sweep(5); - CS2Script.aReferenceCache_2450.sweep(5); + VarpHelpers.varbitLookup.sweep(5); Class136.aReferenceCache_1772.sweep(5); RenderAnimationDefinition.aReferenceCache_1955.sweep(5); TextureOperation25.aReferenceCache_3412.sweep(5); diff --git a/Client/src/main/java/org/runite/client/Class97.java b/Client/src/main/java/org/runite/client/Class97.java index cfcb1f1cd..6469e23f3 100644 --- a/Client/src/main/java/org/runite/client/Class97.java +++ b/Client/src/main/java/org/runite/client/Class97.java @@ -67,7 +67,7 @@ public final class Class97 { static void method1593(int var0, CacheIndex var1) { try { Class154.anInt1966 = var1.getArchiveForName(TextCore.aClass94_3574); - Class79.anInt1124 = var1.getArchiveForName(TextCore.aClass94_1341); + CSConfigCachefile.anInt1124 = var1.getArchiveForName(TextCore.aClass94_1341); if (var0 <= 108) { method1593(14, null); } diff --git a/Client/src/main/java/org/runite/client/Client.java b/Client/src/main/java/org/runite/client/Client.java index 3630de869..477138b8e 100644 --- a/Client/src/main/java/org/runite/client/Client.java +++ b/Client/src/main/java/org/runite/client/Client.java @@ -1349,8 +1349,8 @@ public final class Client extends GameShell { } else { try { if (PacketParser.anInt80 == 0) { - System.out.println("Trying " + GameConfig.Companion.getJS5_SERVER_PORT()); - Class17.aClass64_413 = Class38.gameSignlink.method1441((byte) 8, Class38_Sub1.accRegistryIp, GameConfig.Companion.getJS5_SERVER_PORT()); + System.out.println("Trying " + GameConfig.JS5_SERVER_PORT); + Class17.aClass64_413 = Class38.gameSignlink.method1441((byte) 8, Class38_Sub1.accRegistryIp, GameConfig.JS5_SERVER_PORT); ++PacketParser.anInt80; } @@ -1358,7 +1358,7 @@ public final class Client extends GameShell { /* If the connection is null we reset the JS5 port to the backup server JS5 for compatibility reasons */ if (2 == Objects.requireNonNull(Class17.aClass64_413).anInt978) { - GameConfig.Companion.setJS5_SERVER_PORT(GameConfig.SERVER_PORT + ObjectDefinition.paramWorldID); + GameConfig.JS5_SERVER_PORT = GameConfig.SERVER_PORT + ObjectDefinition.paramWorldID; this.method46(1000); return; } diff --git a/Client/src/main/java/org/runite/client/ClientCommands.java b/Client/src/main/java/org/runite/client/ClientCommands.java index ede2c12af..61ef6273c 100644 --- a/Client/src/main/java/org/runite/client/ClientCommands.java +++ b/Client/src/main/java/org/runite/client/ClientCommands.java @@ -1,7 +1,11 @@ package org.runite.client; +import org.rs09.SystemLogger; + import java.awt.*; +import java.io.File; +import java.io.FileWriter; import java.net.URI; public class ClientCommands { @@ -192,6 +196,29 @@ public class ClientCommands { if (command.equalsStringIgnoreCase(TextCore.COMMAND_SHIFT_DROP_CLICK)) { shiftClickEnabled = !shiftClickEnabled; } + + if (command.startsWith(TextCore.COMMAND_GETBITS)) { + System.out.println("Trying to write file..."); + try { + int index = command.substring(10).parseInt(); + File file = new File("FILE_BITS.txt"); + FileWriter writer = new FileWriter(file); + for(int i = 0; i < 200000; i++){ + CSConfigCachefile cachefile = CSConfigCachefile.getCSConfigFileFromVarbitID(i); + if(cachefile.parentVarpIndex == index){ + writer.write("ID: " + i + " lowerBound = " + cachefile.lowerBound + " upperBound = " + cachefile.upperBound + " size = " + ((cachefile.upperBound - cachefile.lowerBound) + 1)); + writer.write("\n"); + } + } + writer.flush(); + writer.close(); + BufferedDataStream.addChatMessage(null, 0, RSString.parse("Wrote bits to " + file.getAbsolutePath()), -1); + } catch (Exception e){ + SystemLogger.logInfo("Whoopsie"); + e.printStackTrace(); + } + } + TextureOperation12.outgoingBuffer.putOpcode(44); TextureOperation12.outgoingBuffer.writeByte(command.length() + -1); TextureOperation12.outgoingBuffer.writeString(command.substring(2)); @@ -220,7 +247,7 @@ public class ClientCommands { Class159.aReferenceCache_2016.clearSoftReferences();//Originally Class133.method1803(); Class3_Sub31.aReferenceCache_2604.clearSoftReferences();//Class38.method1025(); Class27.aReferenceCache_511.clearSoftReferences();//Class38.method1025(); - CS2Script.aReferenceCache_2450.clearSoftReferences();//Class40.method1044(); + VarpHelpers.varbitLookup.clearSoftReferences();//Class40.method1044(); Class136.aReferenceCache_1772.clearSoftReferences(); RenderAnimationDefinition.aReferenceCache_1955.clearSoftReferences();//Originally: Class158_Sub1.method2192(); TextureOperation25.aReferenceCache_3412.clearSoftReferences();//Originally: Class159.method2196(); diff --git a/Client/src/main/java/org/runite/client/KeyboardListener.java b/Client/src/main/java/org/runite/client/KeyboardListener.java index afa10ca95..7d63daad9 100644 --- a/Client/src/main/java/org/runite/client/KeyboardListener.java +++ b/Client/src/main/java/org/runite/client/KeyboardListener.java @@ -188,7 +188,7 @@ final class KeyboardListener implements KeyListener, FocusListener { try { if(TextureOperation33.aClass148_3049 != null) { - int var2 = Class79.method1386(var1); + int var2 = CSConfigCachefile.method1386(var1); if(var2 >= 0) { int var3 = 1 + Class25.anInt491 & 127; if(var3 != Class3_Sub28_Sub9.anInt3620) { diff --git a/Client/src/main/java/org/runite/client/NPCDefinition.java b/Client/src/main/java/org/runite/client/NPCDefinition.java index 8e04e2b09..7f043ada4 100644 --- a/Client/src/main/java/org/runite/client/NPCDefinition.java +++ b/Client/src/main/java/org/runite/client/NPCDefinition.java @@ -902,11 +902,11 @@ public final class NPCDefinition { static int method1484(int var1) { try { - Class79 var2 = CS2Script.method378(var1, (byte)127); - int var3 = Objects.requireNonNull(var2).anInt1128; - int var5 = var2.anInt1125; - int var4 = var2.anInt1123; - int var6 = Class3_Sub6.anIntArray2288[var5 + -var4]; + CSConfigCachefile var2 = CSConfigCachefile.getCSConfigFileFromVarbitID(var1); + int var3 = Objects.requireNonNull(var2).parentVarpIndex; + int var5 = var2.upperBound; + int var4 = var2.lowerBound; + int var6 = Class3_Sub6.expectedMinimumValues[var5 + -var4]; return ItemDefinition.ram[var3] >> var4 & var6; } catch (RuntimeException var7) { throw ClientErrorException.clientError(var7, "me.B(" + 64835055 + ',' + var1 + ')'); diff --git a/Client/src/main/java/org/runite/client/PacketParser.java b/Client/src/main/java/org/runite/client/PacketParser.java index 5c1ae1418..4b929db00 100644 --- a/Client/src/main/java/org/runite/client/PacketParser.java +++ b/Client/src/main/java/org/runite/client/PacketParser.java @@ -77,7 +77,7 @@ public final class PacketParser { if (60 == Unsorted.incomingOpcode) { nodeModelId = BufferedDataStream.incomingBuffer.readUnsignedShort128(); byte var69 = BufferedDataStream.incomingBuffer.readSignedNegativeByte(); - TextureOperation39.method281(var69, nodeModelId); + VarpHelpers.setVarp(var69, nodeModelId); Unsorted.incomingOpcode = -1; return true; } else { @@ -442,7 +442,7 @@ public final class PacketParser { } else if (Unsorted.incomingOpcode == 226) { nodeModelId = BufferedDataStream.incomingBuffer.readInt(); var19 = BufferedDataStream.incomingBuffer.readUnsignedShort128(); - TextureOperation39.method281(nodeModelId, var19); + VarpHelpers.setVarp(nodeModelId, var19); Unsorted.incomingOpcode = -1; return true; } else if (Unsorted.incomingOpcode == 21) { @@ -1027,7 +1027,7 @@ public final class PacketParser { var19 = BufferedDataStream.incomingBuffer.readUnsignedShort128(); modelId = BufferedDataStream.incomingBuffer.readUnsignedShortLE128(); Class146.updateInterfacePacketCounter(var19); - Class79.method1385(modelId, nodeModelId); + CSConfigCachefile.method1385(modelId, nodeModelId); Unsorted.incomingOpcode = -1; return true; @@ -1123,7 +1123,7 @@ public final class PacketParser { } else if (37 == Unsorted.incomingOpcode) { nodeModelId = BufferedDataStream.incomingBuffer.readUnsignedByte128(); var19 = BufferedDataStream.incomingBuffer.readUnsignedShortLE(); - Class163.method2209((byte) -122, nodeModelId, var19); + VarpHelpers.setVarbit((byte) -122, nodeModelId, var19); Unsorted.incomingOpcode = -1; return true; } else if (Unsorted.incomingOpcode == 155) { @@ -1400,7 +1400,7 @@ public final class PacketParser { } else if (Unsorted.incomingOpcode == 84) { nodeModelId = BufferedDataStream.incomingBuffer.readIntLE(); var19 = BufferedDataStream.incomingBuffer.readUnsignedShortLE128(); - Class163.method2209((byte) -106, nodeModelId, var19); + VarpHelpers.setVarbit((byte) -106, nodeModelId, var19); Unsorted.incomingOpcode = -1; return true; } else { diff --git a/Client/src/main/java/org/runite/client/TextCore.java b/Client/src/main/java/org/runite/client/TextCore.java index 338c84eb9..622de97cf 100644 --- a/Client/src/main/java/org/runite/client/TextCore.java +++ b/Client/src/main/java/org/runite/client/TextCore.java @@ -196,6 +196,7 @@ public class TextCore { */ static RSString COMMAND_HIGHRES_GRAPHICS_RESIZE = RSString.parse("::wm2"); static RSString COMMAND_SHIFT_DROP_CLICK = RSString.parse("::shiftclick"); + static RSString COMMAND_GETBITS = RSString.parse("::getbits"); static RSString COMMAND_REPLACE_CANVAS = RSString.parse("::replacecanvas"); static RSString COMMAND_HIGHRES_GRAPHICS_WINDOW = RSString.parse("::wm1"); static RSString COMMAND_QA_OP_TEST = RSString.parse("::qa_op_test"); diff --git a/Client/src/main/java/org/runite/client/Texture.java b/Client/src/main/java/org/runite/client/Texture.java index b73291c51..e3c8c3674 100644 --- a/Client/src/main/java/org/runite/client/Texture.java +++ b/Client/src/main/java/org/runite/client/Texture.java @@ -346,15 +346,15 @@ public final class Texture { } if (6 == anIntArray3331[var7]) { - var32 = 10 <= Class79.anInt1127 % 20 ? 16776960 : 16711680; + var32 = 10 <= CSConfigCachefile.anInt1127 % 20 ? 16776960 : 16711680; } if (anIntArray3331[var7] == 7) { - var32 = Class79.anInt1127 % 20 < 10 ? 255 : 65535; + var32 = CSConfigCachefile.anInt1127 % 20 < 10 ? 255 : 65535; } if (8 == anIntArray3331[var7]) { - var32 = Class79.anInt1127 % 20 >= 10 ? 8454016 : '\ub000'; + var32 = CSConfigCachefile.anInt1127 % 20 >= 10 ? 8454016 : '\ub000'; } if (9 == anIntArray3331[var7]) { @@ -405,15 +405,15 @@ public final class Texture { } if (1 == anIntArray3336[var7]) { - FontType.bold.method696(var33, var2 - -Class32.anInt590, anInt2208 + var0, var32, Class79.anInt1127); + FontType.bold.method696(var33, var2 - -Class32.anInt590, anInt2208 + var0, var32, CSConfigCachefile.anInt1127); } if (anIntArray3336[var7] == 2) { - FontType.bold.method695(var33, var2 - -Class32.anInt590, var0 - -anInt2208, var32, Class79.anInt1127); + FontType.bold.method695(var33, var2 - -Class32.anInt590, var0 - -anInt2208, var32, CSConfigCachefile.anInt1127); } if (anIntArray3336[var7] == 3) { - FontType.bold.method692(var33, var2 + Class32.anInt590, anInt2208 + var0, var32, Class79.anInt1127, 150 - anIntArray3318[var7]); + FontType.bold.method692(var33, var2 + Class32.anInt590, anInt2208 + var0, var32, CSConfigCachefile.anInt1127, 150 - anIntArray3318[var7]); } if (4 == anIntArray3336[var7]) { diff --git a/Client/src/main/java/org/runite/client/TextureOperation3.java b/Client/src/main/java/org/runite/client/TextureOperation3.java index 292db387b..ecf12d88d 100644 --- a/Client/src/main/java/org/runite/client/TextureOperation3.java +++ b/Client/src/main/java/org/runite/client/TextureOperation3.java @@ -1,5 +1,6 @@ package org.runite.client; +import org.rs09.SystemLogger; import org.rs09.client.util.ArrayUtils; import org.rs09.client.filestore.resources.configs.cursors.CursorDefinition; @@ -114,12 +115,13 @@ final class TextureOperation3 extends TextureOperation { static void method306(int var0, int var2) { try { - Class79 var3 = CS2Script.method378(var0, (byte)127); - int var6 = Objects.requireNonNull(var3).anInt1125; - int var5 = var3.anInt1123; - int var4 = var3.anInt1128; - int var7 = Class3_Sub6.anIntArray2288[var6 - var5]; + CSConfigCachefile var3 = CSConfigCachefile.getCSConfigFileFromVarbitID(var0); + int var6 = Objects.requireNonNull(var3).upperBound; + int var5 = var3.lowerBound; + int var4 = var3.parentVarpIndex; + int var7 = Class3_Sub6.expectedMinimumValues[var6 - var5]; if(var2 < 0 || var7 < var2) { + SystemLogger.logInfo(var7 + " < " + var2); var2 = 0; } diff --git a/Client/src/main/java/org/runite/client/TextureOperation39.java b/Client/src/main/java/org/runite/client/TextureOperation39.java index 0998afd5f..1eedc6e60 100644 --- a/Client/src/main/java/org/runite/client/TextureOperation39.java +++ b/Client/src/main/java/org/runite/client/TextureOperation39.java @@ -166,25 +166,6 @@ class TextureOperation39 extends TextureOperation { } } - static void method281(int var1, int var2) { - try { - Class57.varpArray[var2] = var1; - if(CustomVars.parse(var2,var1)){ - return; - } - Class3_Sub7 var3 = (Class3_Sub7) AtmosphereParser.aHashTable_3679.get(var2); - if(null == var3) { - var3 = new Class3_Sub7(4611686018427387905L); - AtmosphereParser.aHashTable_3679.put(var2, var3); - } else if (var3.aLong2295 != 4611686018427387905L) { - var3.aLong2295 = TimeUtils.time() + 500L | 4611686018427387904L; - } - - } catch (RuntimeException var4) { - throw ClientErrorException.clientError(var4, "nh.W(" + (byte) 99 + ',' + var1 + ',' + var2 + ')'); - } - } - final void method161(byte var1) { try { super.method161(var1); diff --git a/Client/src/main/java/org/runite/client/Unsorted.java b/Client/src/main/java/org/runite/client/Unsorted.java index 81f90befc..747b5fbb2 100644 --- a/Client/src/main/java/org/runite/client/Unsorted.java +++ b/Client/src/main/java/org/runite/client/Unsorted.java @@ -12,8 +12,6 @@ import org.rs09.client.util.ArrayUtils; import org.runite.client.drawcalls.*; import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Objects; @@ -1964,7 +1962,7 @@ public class Unsorted { Class136.method1816(512, -7); TextureOperation19.method257(); } else { - Class3_Sub5.method112((byte) (-4 + Class79.anInt1127 & 0xFF)); + Class3_Sub5.method112((byte) (-4 + CSConfigCachefile.anInt1127 & 0xFF)); Class136.method1816(2, -7); } @@ -2646,7 +2644,7 @@ public class Unsorted { ++var2; } - if (var1.retrieveSpriteFile(Class79.anInt1124)) { + if (var1.retrieveSpriteFile(CSConfigCachefile.anInt1124)) { ++var2; } @@ -4720,7 +4718,7 @@ public class Unsorted { } } - Class79.method1390(new DataBuffer(var4)); + CSConfigCachefile.method1390(new DataBuffer(var4)); } } catch (Exception var8) { } @@ -4913,7 +4911,7 @@ public class Unsorted { static void method338(int var1, boolean var2, int var3, int var4, int var5) { try { - ++Class79.anInt1127; + ++CSConfigCachefile.anInt1127; Class124.method1745(); if(!var2) { Class3_Sub5.method116(true); @@ -5022,7 +5020,7 @@ public class Unsorted { } Class58.method1194(); - byte var19 = Class137.method1817() != 2 ?1:(byte)Class79.anInt1127; + byte var19 = Class137.method1817() != 2 ?1:(byte) CSConfigCachefile.anInt1127; if(HDToolKit.highDetail) { HDToolKit.method1846(); HDToolKit.method1831(true); diff --git a/Client/src/main/java/org/runite/client/VarpHelpers.java b/Client/src/main/java/org/runite/client/VarpHelpers.java new file mode 100644 index 000000000..6fdfa25e1 --- /dev/null +++ b/Client/src/main/java/org/runite/client/VarpHelpers.java @@ -0,0 +1,58 @@ +package org.runite.client; + +import org.rs09.CustomVars; +import org.rs09.SystemLogger; +import org.rs09.client.data.ReferenceCache; + +import java.util.Objects; + +public class VarpHelpers { + + static ReferenceCache varbitLookup = new ReferenceCache(64); + + static void setVarbit(byte var0, int valueToSet, int varbitID) { + try { + if (var0 >= -99) { + setVarbit((byte) 57, -14, 120); + } + + CSConfigCachefile cacheFile = CSConfigCachefile.getCSConfigFileFromVarbitID(varbitID); + int parentVarp = Objects.requireNonNull(cacheFile).parentVarpIndex; + int upperBound = cacheFile.upperBound; + int lowerBound = cacheFile.lowerBound; + int varbitSize = upperBound - lowerBound; + SystemLogger.logInfo(parentVarp + " - bitStart: " + lowerBound + " bitEnd: " + upperBound + " bitSize = " + (varbitSize + 1)); + int expectedMinimumValue = Class3_Sub6.expectedMinimumValues[varbitSize]; + SystemLogger.logInfo("emv: " + expectedMinimumValue + " || vs: " + (127 + valueToSet)); + if (valueToSet < 0|| expectedMinimumValue < valueToSet) { + SystemLogger.logInfo(expectedMinimumValue + " < " + valueToSet); + valueToSet = 0; + } + + expectedMinimumValue <<= lowerBound; + int modifiedVarpValue = valueToSet << lowerBound & expectedMinimumValue | ~expectedMinimumValue & Class57.varpArray[parentVarp]; + setVarp(modifiedVarpValue, parentVarp); + } catch (RuntimeException var8) { + throw ClientErrorException.clientError(var8, "wd.K(" + var0 + ',' + valueToSet + ',' + varbitID + ')'); + } + } + + static void setVarp(int valueToSet, int varpIndex) { + try { + Class57.varpArray[varpIndex] = valueToSet; + if(CustomVars.parse(varpIndex,valueToSet)){ + return; + } + Class3_Sub7 var3 = (Class3_Sub7) AtmosphereParser.aHashTable_3679.get(varpIndex); + if(null == var3) { + var3 = new Class3_Sub7(4611686018427387905L); + AtmosphereParser.aHashTable_3679.put(varpIndex, var3); + } else if (var3.aLong2295 != 4611686018427387905L) { + var3.aLong2295 = TimeUtils.time() + 500L | 4611686018427387904L; + } + + } catch (RuntimeException var4) { + throw ClientErrorException.clientError(var4, "nh.W(" + (byte) 99 + ',' + valueToSet + ',' + varpIndex + ')'); + } + } +} diff --git a/Client/src/main/java/org/runite/client/drawcalls/ContextMenu.java b/Client/src/main/java/org/runite/client/drawcalls/ContextMenu.java index cb99d8a62..64ef0deb0 100644 --- a/Client/src/main/java/org/runite/client/drawcalls/ContextMenu.java +++ b/Client/src/main/java/org/runite/client/drawcalls/ContextMenu.java @@ -12,13 +12,13 @@ public final class ContextMenu { int width = Class21.anInt3552; int height = Class21.anInt3537; int contextMenuColor = 6116423; //Context Menu RGB || 6116423 Classic || Old var5 || ColorCore.getHexColors() - Toolkit.getActiveToolkit().fillRect(1 + x, y + 18, width + -2, -19 + height, GameConfig.RCM_BG_COLOR, GameConfig.RCM_BG_OPACITY); + Toolkit.getActiveToolkit().fillRect(1 + x, y + 18, width + -2, -19 + height, GameConfig.RCM_BG_COLOR, GameConfig.getRCM_BG_OPACITY()); if (GameConfig.RS3_CONTEXT_STYLE) { - Toolkit.getActiveToolkit().fillRect(1 + x, 2 + y, width + -2, 16, GameConfig.RCM_TITLE_COLOR, GameConfig.RCM_TITLE_OPACITY); - Toolkit.getActiveToolkit().drawRect(1 + x, 1 + y, width + -2, height, GameConfig.RCM_BORDER_COLOR, GameConfig.RCM_BORDER_OPACITY); + Toolkit.getActiveToolkit().fillRect(1 + x, 2 + y, width + -2, 16, GameConfig.RCM_TITLE_COLOR, GameConfig.getRCM_TITLE_OPACITY()); + Toolkit.getActiveToolkit().drawRect(1 + x, 1 + y, width + -2, height, GameConfig.RCM_BORDER_COLOR, GameConfig.getRCM_BORDER_OPACITY()); } else { - Toolkit.getActiveToolkit().fillRect(1 + x, 2 + y, width + -2, 16, GameConfig.RCM_TITLE_COLOR, GameConfig.RCM_TITLE_OPACITY); - Toolkit.getActiveToolkit().drawRect(1 + x, y + 18, width + -2, -19 + height, GameConfig.RCM_BORDER_COLOR, GameConfig.RCM_BORDER_OPACITY); + Toolkit.getActiveToolkit().fillRect(1 + x, 2 + y, width + -2, 16, GameConfig.RCM_TITLE_COLOR, GameConfig.getRCM_TITLE_OPACITY()); + Toolkit.getActiveToolkit().drawRect(1 + x, y + 18, width + -2, -19 + height, GameConfig.RCM_BORDER_COLOR, GameConfig.getRCM_BORDER_OPACITY()); } FontType.bold.method681(RSString.parse(GameConfig.RCM_TITLE), x - -3, y + 14, contextMenuColor, -1); diff --git a/Client/src/main/kotlin/org/rs09/client/config/GameConfig.kt b/Client/src/main/kotlin/org/rs09/client/config/GameConfig.kt index 971a87e32..3979edb6e 100644 --- a/Client/src/main/kotlin/org/rs09/client/config/GameConfig.kt +++ b/Client/src/main/kotlin/org/rs09/client/config/GameConfig.kt @@ -11,384 +11,382 @@ import java.util.* * Handles the client's config loading * @author Ceikry */ -class GameConfig { - companion object { +object GameConfig { + /** + * Debug Booleans + */ + @JvmField + var ITEM_DEBUG_ENABLED = false - /** - * Debug Booleans - */ - @JvmField - var ITEM_DEBUG_ENABLED = false + @JvmField + var OBJECT_DEBUG_ENABLED = false - @JvmField - var OBJECT_DEBUG_ENABLED = false + @JvmField + var NPC_DEBUG_ENABLED = false - @JvmField - var NPC_DEBUG_ENABLED = false + @JvmField + var HD_LOGIN_DEBUG = false - @JvmField - var HD_LOGIN_DEBUG = false + @JvmField + var HD_LOGIN_VERBOSE = false - @JvmField - var HD_LOGIN_VERBOSE = false + @JvmField + var CACHE_DEBUG = false - @JvmField - var CACHE_DEBUG = false + @JvmField + var WORLD_MAP_DEBUG = false - @JvmField - var WORLD_MAP_DEBUG = false + /** + * Context Menu Presets + */ + @JvmField + var RCM_STYLE_PRESET = "classic" - /** - * Context Menu Presets - */ - @JvmField - var RCM_STYLE_PRESET = "classic" + /** + * Context Menu Customization + */ + @JvmField + var RCM_BG_COLOR = 6116423 - /** - * Context Menu Customization - */ - @JvmField - var RCM_BG_COLOR = 6116423 - - @JvmStatic - var RCM_BG_OPACITY = 255 - set(value) { - if(value > 255 || value < 0) field = 255 - else field = value - } - - @JvmField - var RCM_TITLE_COLOR = 0 - - @JvmStatic - var RCM_TITLE_OPACITY = 255 - set(value) { - if(value > 255 || value < 0) field = 255 - else field = value - } - - @JvmField - var RCM_BORDER_COLOR = 0 - - @JvmStatic - var RCM_BORDER_OPACITY = 255 - set(value) { - if(value > 255 || value < 0) field = 255 - else field = value - } - - @JvmField - var RCM_TITLE = "Choose Option" - - @JvmField - var RS3_CONTEXT_STYLE = false - - /** - * Render distance - */ - @JvmField - var RENDER_DISTANCE_INCREASE = false - - @JvmField - var RENDER_DISTANCE_VALUE = 3584f - - @JvmField - var RENDER_DISTANCE_TILE_VALUE = 28 - - @JvmField - var RENDER_DISTANCE_FOG_FIX = 3328.0f - - @JvmField - var SKYBOX_COLOR = "float" - - /** - * Client Info - * Editable - */ - @JvmField - var IP_ADDRESS = "localhost" - - @JvmField - var IP_MANAGEMENT = "localhost" - - var JS5_SERVER_PORT = 43593 - - @JvmField - var SERVER_PORT = 43594 - - @JvmField - var WL_PORT = 5555 - - @JvmField - var WORLD = 1 - - @JvmField - var WORLD_OVERRIDE = -1 - - @JvmField - var LOGIN_THEME = "scape main" - - @JvmField - var xpDropsEnabled = true - - @JvmField - var xpDropMode = 0 - - @JvmField - var xpTrackMode = 0 - - @JvmField - var slayerCountEnabled = true - - @JvmField - var slayerTrackerColor = "#635a38" - - @JvmStatic - var slayerTrackerOpacity = 180 + @JvmStatic + var RCM_BG_OPACITY = 255 set(value) { if(value > 255 || value < 0) field = 255 else field = value } - @JvmField - var slayerTaskID = 0 + @JvmField + var RCM_TITLE_COLOR = 0 - @JvmField - var slayerTaskAmount = 0 - - @JvmField - var VERBOSE_LOGGING = false - - @JvmStatic - fun setSlayerAmount(amount : Int){ - slayerTaskAmount = amount - if(slayerTaskAmount < 0) slayerTaskAmount = 0 - SlayerTracker.lastUpdate = System.currentTimeMillis() + @JvmStatic + var RCM_TITLE_OPACITY = 255 + set(value) { + if(value > 255 || value < 0) field = 255 + else field = value } + @JvmField + var RCM_BORDER_COLOR = 0 + + @JvmStatic + var RCM_BORDER_OPACITY = 255 + set(value) { + if(value > 255 || value < 0) field = 255 + else field = value + } + + @JvmField + var RCM_TITLE = "Choose Option" + + @JvmField + var RS3_CONTEXT_STYLE = false + + /** + * Render distance + */ + @JvmField + var RENDER_DISTANCE_INCREASE = false + + @JvmField + var RENDER_DISTANCE_VALUE = 3584f + + @JvmField + var RENDER_DISTANCE_TILE_VALUE = 28 + + @JvmField + var RENDER_DISTANCE_FOG_FIX = 3328.0f + + @JvmField + var SKYBOX_COLOR = "float" + + /** + * Client Info + * Editable + */ + @JvmField + var IP_ADDRESS = "localhost" + + @JvmField + var IP_MANAGEMENT = "localhost" + + @JvmField + var JS5_SERVER_PORT = 43593 + + @JvmField + var SERVER_PORT = 43594 + + @JvmField + var WL_PORT = 5555 + + @JvmField + var WORLD = 1 + + @JvmField + var WORLD_OVERRIDE = -1 + + @JvmField + var LOGIN_THEME = "scape main" + + @JvmField + var xpDropsEnabled = true + + @JvmField + var xpDropMode = 0 + + @JvmField + var xpTrackMode = 0 + + @JvmField + var slayerCountEnabled = true + + @JvmField + var slayerTrackerColor = "#635a38" + + @JvmStatic + var slayerTrackerOpacity = 180 + set(value) { + if(value > 255 || value < 0) field = 255 + else field = value + } + + @JvmField + var slayerTaskID = 0 + + @JvmField + var slayerTaskAmount = 0 + + @JvmField + var VERBOSE_LOGGING = false + + @JvmStatic + fun setSlayerAmount(amount : Int){ + slayerTaskAmount = amount + if(slayerTaskAmount < 0) slayerTaskAmount = 0 + SlayerTracker.lastUpdate = System.currentTimeMillis() + } + + /** + * Json config Parser + */ + @JvmStatic + fun parse(path: String){ + val reader = FileReader(path) + val parser = JSONParser() + val data = parser.parse(reader) as JSONObject + + //Networking + if(data.containsKey("ip_address")) IP_ADDRESS = data["ip_address"].toString() else IP_ADDRESS = "play.2009scape.org" + if(data.containsKey("ip_management")) IP_MANAGEMENT = data["ip_management"].toString() else IP_MANAGEMENT = IP_ADDRESS + if(data.containsKey("wl_port")) WL_PORT = data["wl_port"].toString().toInt() + if(data.containsKey("server_port")) SERVER_PORT = data["server_port"].toString().toInt() + if(data.containsKey("js5_port")) JS5_SERVER_PORT = data["js5_port"].toString().toInt() + if(data.containsKey("world")) WORLD = data["world"].toString().toInt() + + //Parse customization options + if(data.containsKey("customization")){ + val custom = data["customization"] as JSONObject + if(custom.containsKey("login_theme")) LOGIN_THEME = custom["login_theme"].toString() + + //Right-click menu customizations + if(custom.containsKey("right_click_menu")){ + val rcm = custom["right_click_menu"] as JSONObject + + //background + if(rcm.containsKey("background")){ + val bg = rcm["background"] as JSONObject + if(bg.containsKey("color")) RCM_BG_COLOR = bg["color"].toString().replace("#", "").toIntOrNull(16) ?: 6116423//convert hex -> deci + if(bg.containsKey("opacity")) RCM_BG_OPACITY = bg["opacity"].toString().toInt() + } + + //title bar + if(rcm.containsKey("title_bar")){ + val tb = rcm["title_bar"] as JSONObject + if(tb.containsKey("font_color")) RCM_TITLE = RCM_TITLE.replace("0", tb["font_color"].toString().replace("#", "")) + if(tb.containsKey("color")) RCM_TITLE_COLOR = tb["color"].toString().replace("#", "").toIntOrNull(16) ?: 6116423//convert hex -> deci + if(tb.containsKey("opacity")) RCM_TITLE_OPACITY = tb["opacity"].toString().toInt() + } + + //border + if(rcm.containsKey("border")){ + val border = rcm["border"] as JSONObject + if(border.containsKey("color")) RCM_BORDER_COLOR = border["color"].toString().replace("#", "").toIntOrNull(16) ?: 6116423 //convert hex -> deci + if(border.containsKey("opacity")) RCM_BORDER_OPACITY = border["opacity"].toString().toInt() + } + + //styles (changes how things are drawn) + if(rcm.containsKey("styles")){ + val style = rcm["styles"] as JSONObject + if(style.containsKey("presets")) RCM_STYLE_PRESET = style["presets"].toString() + if(style.containsKey("rs3border")) RS3_CONTEXT_STYLE = style["rs3border"] as Boolean + } + } + + if(custom.containsKey("xpdrops")){ + val xpd = custom["xpdrops"] as JSONObject + if(xpd.containsKey("enabled")) xpDropsEnabled = xpd["enabled"] as Boolean + if(xpd.containsKey("drop_mode")) xpDropMode = xpd["drop_mode"].toString().toInt() + if(xpd.containsKey("track_mode")) xpTrackMode = xpd["track_mode"].toString().toInt() + } + + if(custom.containsKey("slayer")){ + val slayer = custom["slayer"] as JSONObject + if(slayer.containsKey("enabled")) slayerCountEnabled = slayer["enabled"] as Boolean + if(slayer.containsKey("color")) slayerTrackerColor = slayer["color"].toString().replace("#", "") + if(slayer.containsKey("opacity")) slayerTrackerOpacity = slayer["opacity"].toString().toInt() + } + + if(custom.containsKey("rendering_options")) { + val hdoptions = custom["rendering_options"] as JSONObject + + if(hdoptions.containsKey("technical")) { + val renderIncrease = hdoptions["technical"] as JSONObject + if(renderIncrease.containsKey("render_distance_increase")) RENDER_DISTANCE_INCREASE = renderIncrease["render_distance_increase"] as Boolean + } + if(hdoptions.containsKey("skybox")) { + val skyboxColor = hdoptions["skybox"] as JSONObject + if(skyboxColor.containsKey("skybox_color")) SKYBOX_COLOR + } + } + } + + //Parse debug options + if(data.containsKey("debug")){ + val debug = data["debug"] as JSONObject + if(debug.containsKey("item_debug")) ITEM_DEBUG_ENABLED = debug["item_debug"] as Boolean + if(debug.containsKey("npc_debug")) NPC_DEBUG_ENABLED = debug["npc_debug"] as Boolean + if(debug.containsKey("object_debug")) OBJECT_DEBUG_ENABLED = debug["object_debug"] as Boolean + if(debug.containsKey("hd_login_region_debug")) HD_LOGIN_DEBUG = debug["hd_login_region_debug"] as Boolean + if(debug.containsKey("hd_login_region_debug_verbose")) HD_LOGIN_VERBOSE = debug["hd_login_region_debug_verbose"] as Boolean + if(debug.containsKey("cache_debug")) CACHE_DEBUG = debug["cache_debug"] as Boolean + if(debug.containsKey("world_map_debug")) WORLD_MAP_DEBUG = debug["world_map_debug"] as Boolean + } + + /** - * Json config Parser + * Style Overrides (Still working on this system. We should allow for maximum creativity + * The way that it will be setup is a style type 1st + * ie, classicbox, rs3, rounded, rounded2 + * Then we introduce color schemes that a user could select + * ie, classic, rs3, alternate, alternate2, custom + * @author Woah */ - @JvmStatic - fun parse(path: String){ - val reader = FileReader(path) - val parser = JSONParser() - val data = parser.parse(reader) as JSONObject - - //Networking - if(data.containsKey("ip_address")) IP_ADDRESS = data["ip_address"].toString() else IP_ADDRESS = "play.2009scape.org" - if(data.containsKey("ip_management")) IP_MANAGEMENT = data["ip_management"].toString() else IP_MANAGEMENT = IP_ADDRESS - if(data.containsKey("wl_port")) WL_PORT = data["wl_port"].toString().toInt() - if(data.containsKey("server_port")) SERVER_PORT = data["server_port"].toString().toInt() - if(data.containsKey("js5_port")) JS5_SERVER_PORT = data["js5_port"].toString().toInt() - if(data.containsKey("world")) WORLD = data["world"].toString().toInt() - - //Parse customization options - if(data.containsKey("customization")){ - val custom = data["customization"] as JSONObject - if(custom.containsKey("login_theme")) LOGIN_THEME = custom["login_theme"].toString() - - //Right-click menu customizations - if(custom.containsKey("right_click_menu")){ - val rcm = custom["right_click_menu"] as JSONObject - - //background - if(rcm.containsKey("background")){ - val bg = rcm["background"] as JSONObject - if(bg.containsKey("color")) RCM_BG_COLOR = bg["color"].toString().replace("#", "").toIntOrNull(16) ?: 6116423//convert hex -> deci - if(bg.containsKey("opacity")) RCM_BG_OPACITY = bg["opacity"].toString().toInt() - } - - //title bar - if(rcm.containsKey("title_bar")){ - val tb = rcm["title_bar"] as JSONObject - if(tb.containsKey("font_color")) RCM_TITLE = RCM_TITLE.replace("0", tb["font_color"].toString().replace("#", "")) - if(tb.containsKey("color")) RCM_TITLE_COLOR = tb["color"].toString().replace("#", "").toIntOrNull(16) ?: 6116423//convert hex -> deci - if(tb.containsKey("opacity")) RCM_TITLE_OPACITY = tb["opacity"].toString().toInt() - } - - //border - if(rcm.containsKey("border")){ - val border = rcm["border"] as JSONObject - if(border.containsKey("color")) RCM_BORDER_COLOR = border["color"].toString().replace("#", "").toIntOrNull(16) ?: 6116423 //convert hex -> deci - if(border.containsKey("opacity")) RCM_BORDER_OPACITY = border["opacity"].toString().toInt() - } - - //styles (changes how things are drawn) - if(rcm.containsKey("styles")){ - val style = rcm["styles"] as JSONObject - if(style.containsKey("presets")) RCM_STYLE_PRESET = style["presets"].toString() - if(style.containsKey("rs3border")) RS3_CONTEXT_STYLE = style["rs3border"] as Boolean - } - } - - if(custom.containsKey("xpdrops")){ - val xpd = custom["xpdrops"] as JSONObject - if(xpd.containsKey("enabled")) xpDropsEnabled = xpd["enabled"] as Boolean - if(xpd.containsKey("drop_mode")) xpDropMode = xpd["drop_mode"].toString().toInt() - if(xpd.containsKey("track_mode")) xpTrackMode = xpd["track_mode"].toString().toInt() - } - - if(custom.containsKey("slayer")){ - val slayer = custom["slayer"] as JSONObject - if(slayer.containsKey("enabled")) slayerCountEnabled = slayer["enabled"] as Boolean - if(slayer.containsKey("color")) slayerTrackerColor = slayer["color"].toString().replace("#", "") - if(slayer.containsKey("opacity")) slayerTrackerOpacity = slayer["opacity"].toString().toInt() - } - - if(custom.containsKey("rendering_options")) { - val hdoptions = custom["rendering_options"] as JSONObject - - if(hdoptions.containsKey("technical")) { - val renderIncrease = hdoptions["technical"] as JSONObject - if(renderIncrease.containsKey("render_distance_increase")) RENDER_DISTANCE_INCREASE = renderIncrease["render_distance_increase"] as Boolean - } - if(hdoptions.containsKey("skybox")) { - val skyboxColor = hdoptions["skybox"] as JSONObject - if(skyboxColor.containsKey("skybox_color")) SKYBOX_COLOR - } - } + when (RCM_STYLE_PRESET) { + "classic" -> { + RS3_CONTEXT_STYLE = false + RCM_BG_COLOR = 6116423 + RCM_BG_OPACITY = 255 + RCM_TITLE = "Choose Option" + RCM_TITLE_COLOR = 0 + RCM_TITLE_OPACITY = 255 + RCM_BORDER_COLOR = 0 + RCM_BORDER_OPACITY = 255 } - - //Parse debug options - if(data.containsKey("debug")){ - val debug = data["debug"] as JSONObject - if(debug.containsKey("item_debug")) ITEM_DEBUG_ENABLED = debug["item_debug"] as Boolean - if(debug.containsKey("npc_debug")) NPC_DEBUG_ENABLED = debug["npc_debug"] as Boolean - if(debug.containsKey("object_debug")) OBJECT_DEBUG_ENABLED = debug["object_debug"] as Boolean - if(debug.containsKey("hd_login_region_debug")) HD_LOGIN_DEBUG = debug["hd_login_region_debug"] as Boolean - if(debug.containsKey("hd_login_region_debug_verbose")) HD_LOGIN_VERBOSE = debug["hd_login_region_debug_verbose"] as Boolean - if(debug.containsKey("cache_debug")) CACHE_DEBUG = debug["cache_debug"] as Boolean - if(debug.containsKey("world_map_debug")) WORLD_MAP_DEBUG = debug["world_map_debug"] as Boolean + "rs3" -> { + RS3_CONTEXT_STYLE = true + RCM_BG_COLOR = 662822 + RCM_BG_OPACITY = 255 + RCM_TITLE = "Choose Option" + RCM_TITLE_COLOR = 1512718 + RCM_TITLE_OPACITY = 165 + RCM_BORDER_COLOR = 16777215 + RCM_BORDER_OPACITY = 255 } + } - /** - * Style Overrides (Still working on this system. We should allow for maximum creativity - * The way that it will be setup is a style type 1st - * ie, classicbox, rs3, rounded, rounded2 - * Then we introduce color schemes that a user could select - * ie, classic, rs3, alternate, alternate2, custom - * @author Woah + } + + fun extendRenderDistance() { + if (RENDER_DISTANCE_INCREASE) { + /** **DO NOT CHANGE THESE NUMBERS UNLESS YOU KNOW WHAT YOU ARE DOING** + * Render Distance Overrides + * + * (Simple formula) Tile amount * 512 + * Default: 7 * 512 = 3584 + * Extended(max): 56 * 512 = 28672 + * + * Files + methods effected by these values: + * HDToolKit METHOD viewport + * Class140_Sub1_Sub1 METHOD animate + * Class3_Sub22 METHOD method398 * value as short + * Class40 METHOD method1046 * using RENDER_DISTANCE_TILE_VALUE */ - when (RCM_STYLE_PRESET) { - "classic" -> { - RS3_CONTEXT_STYLE = false - RCM_BG_COLOR = 6116423 - RCM_BG_OPACITY = 255 - RCM_TITLE = "Choose Option" - RCM_TITLE_COLOR = 0 - RCM_TITLE_OPACITY = 255 - RCM_BORDER_COLOR = 0 - RCM_BORDER_OPACITY = 255 - } - "rs3" -> { - RS3_CONTEXT_STYLE = true - RCM_BG_COLOR = 662822 - RCM_BG_OPACITY = 255 - RCM_TITLE = "Choose Option" - RCM_TITLE_COLOR = 1512718 - RCM_TITLE_OPACITY = 165 - RCM_BORDER_COLOR = 16777215 - RCM_BORDER_OPACITY = 255 - } - } - - + RENDER_DISTANCE_VALUE = if (RENDER_DISTANCE_INCREASE) 28672F else 3584.0f + RENDER_DISTANCE_TILE_VALUE = if (RENDER_DISTANCE_INCREASE) 56 else 28 + RENDER_DISTANCE_FOG_FIX = if (RENDER_DISTANCE_INCREASE) 28672F else 3328.0f } + } - fun extendRenderDistance() { - if (RENDER_DISTANCE_INCREASE) { - /** **DO NOT CHANGE THESE NUMBERS UNLESS YOU KNOW WHAT YOU ARE DOING** - * Render Distance Overrides - * - * (Simple formula) Tile amount * 512 - * Default: 7 * 512 = 3584 - * Extended(max): 56 * 512 = 28672 - * - * Files + methods effected by these values: - * HDToolKit METHOD viewport - * Class140_Sub1_Sub1 METHOD animate - * Class3_Sub22 METHOD method398 * value as short - * Class40 METHOD method1046 * using RENDER_DISTANCE_TILE_VALUE - */ - RENDER_DISTANCE_VALUE = if (RENDER_DISTANCE_INCREASE) 28672F else 3584.0f - RENDER_DISTANCE_TILE_VALUE = if (RENDER_DISTANCE_INCREASE) 56 else 28 - RENDER_DISTANCE_FOG_FIX = if (RENDER_DISTANCE_INCREASE) 28672F else 3328.0f - } - } + /** + * Client Info + * Not Editable + */ + @JvmField + var CLIENT_BUILD = 530 - /** - * Client Info - * Not Editable - */ - @JvmField - var CLIENT_BUILD = 530 + @JvmField + var CLIENT_VERSION = 1 - @JvmField - var CLIENT_VERSION = 1 + @JvmField + var PACKAGE_NAME = "org.runite.client" - @JvmField - var PACKAGE_NAME = "org.runite.client" + @JvmField + var RSA = true - @JvmField - var RSA = true + @JvmField + var ISAAC = false - @JvmField - var ISAAC = false + @JvmField + var EXPONENT = BigInteger("65537") - @JvmField - var EXPONENT = BigInteger("65537") + @JvmField + var MODULUS = BigInteger("96982303379631821170939875058071478695026608406924780574168393250855797534862289546229721580153879336741968220328805101128831071152160922518190059946555203865621183480223212969502122536662721687753974815205744569357388338433981424032996046420057284324856368815997832596174397728134370577184183004453899764051") - @JvmField - var MODULUS = BigInteger("96982303379631821170939875058071478695026608406924780574168393250855797534862289546229721580153879336741968220328805101128831071152160922518190059946555203865621183480223212969502122536662721687753974815205744569357388338433981424032996046420057284324856368815997832596174397728134370577184183004453899764051") + @JvmField + var SERVER_NAME = "2009scape" - @JvmField - var SERVER_NAME = "2009scape" + /** + * Path to config + */ + @JvmField + var configLocation = "config.json" - /** - * Path to config - */ - @JvmField - var configLocation = "config.json" + /** + * Holiday Event Toggles + */ + @JvmField + var HOLIDAYS_ENABLED = true - /** - * Holiday Event Toggles - */ - @JvmField - var HOLIDAYS_ENABLED = true + @JvmField + var EASTER_EVENT_ENABLED = false + /** + * Halloween event NPC Definitions are handled inside of NPCDefinition.java + */ + @JvmField + var HALLOWEEN_EVENT_ENABLED = false - @JvmField - var EASTER_EVENT_ENABLED = false - /** - * Halloween event NPC Definitions are handled inside of NPCDefinition.java - */ - @JvmField - var HALLOWEEN_EVENT_ENABLED = false + @JvmField + var THANKSGIVING_EVENT_ENABLED = false - @JvmField - var THANKSGIVING_EVENT_ENABLED = false + @JvmField + var CHRISTMAS_EVENT_ENABLED = false - @JvmField - var CHRISTMAS_EVENT_ENABLED = false + private val calendar: Calendar = Calendar.getInstance() + private val month = calendar.get(Calendar.MONTH) + private val day = calendar.get(Calendar.DAY_OF_MONTH) - private val calendar: Calendar = Calendar.getInstance() - private val month = calendar.get(Calendar.MONTH) - private val day = calendar.get(Calendar.DAY_OF_MONTH) - - @JvmStatic - fun implementHoliday() { - if (HOLIDAYS_ENABLED) { - when (month) { - 3 -> { - if (day <= 8) { - EASTER_EVENT_ENABLED = true - } + @JvmStatic + fun implementHoliday() { + if (HOLIDAYS_ENABLED) { + when (month) { + 3 -> { + if (day <= 8) { + EASTER_EVENT_ENABLED = true } - 9 -> HALLOWEEN_EVENT_ENABLED = true - 10 -> THANKSGIVING_EVENT_ENABLED = true - 11 -> CHRISTMAS_EVENT_ENABLED = true } + 9 -> HALLOWEEN_EVENT_ENABLED = true + 10 -> THANKSGIVING_EVENT_ENABLED = true + 11 -> CHRISTMAS_EVENT_ENABLED = true } } } diff --git a/Management-Server/managementprops/properties.json b/Management-Server/managementprops/properties.json index 85bbcfb28..e081156a1 100644 --- a/Management-Server/managementprops/properties.json +++ b/Management-Server/managementprops/properties.json @@ -10,6 +10,6 @@ "WorldTechnicalInformation": { "world_limit": "10", "worldhop_delay": "20000" - } - + }, + "secret_key": "2009scape_development" } \ No newline at end of file diff --git a/Management-Server/src/main/java/ms/Management.java b/Management-Server/src/main/java/ms/Management.java index 2c9863111..5d44a4e37 100644 --- a/Management-Server/src/main/java/ms/Management.java +++ b/Management-Server/src/main/java/ms/Management.java @@ -1,7 +1,8 @@ package ms; -import ms.classloader.ClassLoadServer; import ms.net.NioReactor; +import ms.net.packet.IoBuffer; +import ms.net.packet.PacketHeader; import ms.net.packet.WorldPacketRepository; import ms.system.ShutdownSequence; import ms.system.mysql.SQLManager; @@ -100,7 +101,6 @@ public final class Management { new Command("-rlcache", "Reloads launcher/client resource cache") { @Override public void run(String... args) { - ClassLoadServer.resetResourceCache(); System.out.println("Reloaded resource cache!"); } }, @@ -118,6 +118,27 @@ public final class Management { player.setWorldId(0); System.out.println("Kicked player " + name + "!"); } + }, + + new Command("-say", "Send a message to all worlds") { + @Override + public void run(String... args) { + String message = String.join(" ", args); + message = message.substring(4); + for(GameServer server : WorldDatabase.getWorlds()){ + if(server == null) continue; + String finalMessage = message; + server.getPlayers().forEach((String uname, PlayerSession p) -> { + IoBuffer buffer = new IoBuffer(5, PacketHeader.BYTE); + buffer.putString(p.getUsername()); + buffer.putString("Server"); + buffer.put(2); + buffer.put(2); + buffer.putString(finalMessage); + p.getWorld().getSession().write(buffer); + }); + } + } } }; @@ -136,7 +157,6 @@ public final class Management { SQLManager.init(); //NioReactor.configure(ServerConstants.PORT).start(); NioReactor.configure(5555).start(); - new ClassLoadServer().start(); Runtime.getRuntime().addShutdownHook(new ShutdownSequence()); System.out.println("Status: ready."); System.out.println("Use -commands for a list of commands!"); diff --git a/Management-Server/src/main/java/ms/ServerConstants.java b/Management-Server/src/main/java/ms/ServerConstants.java index dab98279f..60d4af36d 100644 --- a/Management-Server/src/main/java/ms/ServerConstants.java +++ b/Management-Server/src/main/java/ms/ServerConstants.java @@ -29,18 +29,6 @@ public final class ServerConstants { */ public static final OperatingSystem OS = System.getProperty("os.name").toUpperCase().contains("WIN") ? OperatingSystem.WINDOWS : OperatingSystem.UNIX; - /** - * The administrators. - */ - public static final String[] ADMINISTRATORS = { - "redsparr0w", - }; - - public static final String[] DATABASE_NAMES = { - "server", - "global", - }; - /** * Stops from instantiating. */ diff --git a/Management-Server/src/main/java/ms/classloader/ClassLoadServer.java b/Management-Server/src/main/java/ms/classloader/ClassLoadServer.java deleted file mode 100644 index ef35db3eb..000000000 --- a/Management-Server/src/main/java/ms/classloader/ClassLoadServer.java +++ /dev/null @@ -1,111 +0,0 @@ -package ms.classloader; - -import ms.Management; -import ms.ServerConstants; - -import java.io.File; -import java.io.IOException; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.UnknownHostException; -import java.nio.file.Files; -import java.util.HashMap; - -/** - * ClassLoadServer - * @author Clayton Williams (Hope) - */ -public class ClassLoadServer extends Thread { - - /** - * Listening port - */ - private static final int PORT = 5050; - - /** - * serverSocket for incoming connections - */ - private ServerSocket serverSocket = null; - - /** - * Holds classes and resources already added in the server - */ - protected final static HashMap resourceCache = new HashMap(); - - /** - * New socket - * @throws UnknownHostException - * @throws IOException - */ - public ClassLoadServer() { - try { - serverSocket = new ServerSocket(PORT); - } catch (Exception e) { - e.printStackTrace(); - } - } - - - /** - * Listen for incoming connections - */ - @Override - public void run() { - resetResourceCache(); - // System.out.println("Listening on port " + PORT + "..."); - while (Management.active) { - Socket clientSocket = null; - try { - clientSocket = serverSocket.accept(); - //System.out.println("New Connection from : " + clientSocket.getInetAddress()); - WorkerThread wcs = new WorkerThread(clientSocket); - wcs.start(); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - /** - * Loads resources recursively from a starting root directory and adds the file bytes to our cache - * @param path - * @param pathRoot - */ - private static void loadResources(String path, String pathRoot) { - try { - path = ServerConstants.fixPath(null, path); - pathRoot = ServerConstants.fixPath(null, pathRoot); - File root = new File(path); - File[] list = root.listFiles(); - if (list == null) return; - for (File f : list) { - if (f.isDirectory()) { - loadResources(f.getAbsolutePath(), pathRoot); - } else { - if (f.exists()) { - if (!f.getName().startsWith(".")) { - byte[] bytes = Files.readAllBytes(f.toPath()); - String name = ServerConstants.fixPath(null, f.getAbsolutePath().substring(f.getAbsolutePath().lastIndexOf(pathRoot))); - //System.out.println("[ClassLoadServer] Loaded resource '" + f.getName() + - // "' Size: " + NumberFormat.getInstance().format(bytes.length) + " bytes"); - resourceCache.put(name, bytes); - } - } - } - } - } catch(Exception e) { - e.printStackTrace(); - } - } - - /** - * Empties the class cache and loads resources - */ - public static void resetResourceCache() { - resourceCache.clear(); - //loadResources("bin/org/keldagrim/launcher/", "org/arios/launcher/"); - //loadResources("resources/", "org/keldagrim/launcher/"); - //System.out.println("Loaded all resources!"); - } - -} diff --git a/Management-Server/src/main/java/ms/classloader/WorkerThread.java b/Management-Server/src/main/java/ms/classloader/WorkerThread.java deleted file mode 100644 index c9af27f6a..000000000 --- a/Management-Server/src/main/java/ms/classloader/WorkerThread.java +++ /dev/null @@ -1,136 +0,0 @@ -package ms.classloader; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.net.Socket; -import java.util.Map; - -import ms.ServerConstants; -import ms.system.OperatingSystem; - -/** - * Worker thread for launcher connections - * @author Clayton Williams (Hope) - * - */ -public class WorkerThread extends Thread { - - /** - * Our launcher connection - */ - private Socket launcher = null; - - /** - * Input stream from launcher - */ - private ObjectInputStream is = null; - - /** - * Output stream to launcher - */ - private ObjectOutputStream os = null; - - /** - * The user's operating system type - */ - private OperatingSystem operatingSystem = OperatingSystem.WINDOWS; - - /** - * Creates a new worker thread to handle the launcher requests - * @param socket - * @param classesCache - * @throws IOException - */ - public WorkerThread(Socket launcher) throws IOException { - super(); - this.launcher = launcher; - try { - os = new ObjectOutputStream(new BufferedOutputStream(this.launcher.getOutputStream())); - os.flush(); - is = new ObjectInputStream(new BufferedInputStream(launcher.getInputStream())); - } catch (IOException ioe) { - this.launcher.close(); - } - } - - /** - * Input Stream handler - */ - @SuppressWarnings("unused") //saving resource type for later - public void run() { - byte opcode = -1; - try { - while (true) { - opcode = is.readByte(); - switch(opcode) { - case 1: //requests revision - operatingSystem = is.readUTF().contains("UNIX") ? OperatingSystem.UNIX : OperatingSystem.WINDOWS; - os.reset(); - os.writeInt(ClassLoadServer.resourceCache.size());//#customresources - for (Map.Entry hm : ClassLoadServer.resourceCache.entrySet()) { - os.writeUTF(ServerConstants.fixPath(operatingSystem, (String) hm.getKey())); - os.writeInt(hm.getValue().length); - } - os.writeByte(1); //number of custom resources - //followed by 2 strings - //System.err.println(operatingSystem.name()); - os.writeUTF(ServerConstants.fixPath(operatingSystem, "ms/launcher/arios-gamepack-530.jar")); - os.writeUTF("BINARY"); - os.flush(); - break; - case 2: //resource request - String resourceName = ServerConstants.fixPath(null, is.readUTF()); - String resourceType = is.readUTF(); - if (ClassLoadServer.resourceCache.containsKey(resourceName)) { - sendResource(ClassLoadServer.resourceCache.get(resourceName)); - //System.out.println("Sent Resource: " + resourceName); - } else { - sendOpcode(-1); - //System.out.println("Could not send resource '" + resourceName + "'"); - } - break; - default: - System.out.println("Unhandled opcode=" + opcode); - break; - } - } - } catch(Exception e) { - //System.out.println("Client force disconnect."); - } finally { - try { - is.close(); - os.close(); - launcher.close(); - } catch (Exception e) {} - } - } - - /** - * send a byte array packet to the client - * @exception IOException file read error. - */ - protected void sendResource(byte [] bytes) throws IOException { - os.reset(); - os.writeByte(2); - os.writeInt(bytes.length); - for (int i = 0; i < bytes.length; i++) { - os.writeByte(bytes[i]); - } - os.flush(); - } - - /** - * Send no data opcodes - * @param opcode - * @throws IOException - */ - protected void sendOpcode(int opcode) throws IOException { - os.reset(); - os.writeByte(opcode); - os.flush(); - } - -} diff --git a/Management-Server/src/main/java/ms/net/IoEventHandler.java b/Management-Server/src/main/java/ms/net/IoEventHandler.java index 907ad9bbf..1971fffa7 100644 --- a/Management-Server/src/main/java/ms/net/IoEventHandler.java +++ b/Management-Server/src/main/java/ms/net/IoEventHandler.java @@ -67,6 +67,10 @@ public final class IoEventHandler { ByteBuffer buffer = ByteBuffer.allocate(100_000); IoSession session = (IoSession) key.attachment(); if (channel.read(buffer) == -1) { + if(session == null){ + key.cancel(); + return; + } if(session.getGameServer() != null){ WorldDatabase.unRegister(session.getGameServer()); } @@ -87,8 +91,10 @@ public final class IoEventHandler { */ public void write(SelectionKey key) { IoSession session = (IoSession) key.attachment(); - key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE); - session.write(); + if(session != null) { + key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE); + session.write(); + } } /** diff --git a/Management-Server/src/main/java/ms/net/IoSession.java b/Management-Server/src/main/java/ms/net/IoSession.java index dd722db17..5fc70344f 100644 --- a/Management-Server/src/main/java/ms/net/IoSession.java +++ b/Management-Server/src/main/java/ms/net/IoSession.java @@ -168,9 +168,9 @@ public class IoSession { } writingQueue.remove(0); } - writingLock.unlock(); } catch (IOException e) { disconnect(); + } finally { writingLock.unlock(); } } diff --git a/Management-Server/src/main/java/ms/net/NioReactor.java b/Management-Server/src/main/java/ms/net/NioReactor.java index 8c28177ad..21a17ec65 100644 --- a/Management-Server/src/main/java/ms/net/NioReactor.java +++ b/Management-Server/src/main/java/ms/net/NioReactor.java @@ -96,6 +96,7 @@ public final class NioReactor implements Runnable { SelectionKey key = keys.next(); keys.remove(); try { + if(key == null) continue; if (!key.isValid() || !key.channel().isOpen()) { key.cancel(); continue; diff --git a/Management-Server/src/main/java/ms/net/event/HSReadEvent.java b/Management-Server/src/main/java/ms/net/event/HSReadEvent.java index ac12befc0..d92f5dbc7 100644 --- a/Management-Server/src/main/java/ms/net/event/HSReadEvent.java +++ b/Management-Server/src/main/java/ms/net/event/HSReadEvent.java @@ -4,6 +4,7 @@ import java.nio.ByteBuffer; import ms.net.IoReadEvent; import ms.net.IoSession; +import ms.system.util.ManagementConstants; import ms.world.WorldDatabase; import ms.system.util.ByteBufferUtils; @@ -12,11 +13,6 @@ import ms.system.util.ByteBufferUtils; * @author Emperor */ public final class HSReadEvent extends IoReadEvent { - - /** - * The password used to verify - */ - private static final String PASSWORD = "0x14ari0SSbh98989910"; /** * Constructs a new {@code HSReadEvent}. @@ -33,7 +29,7 @@ public final class HSReadEvent extends IoReadEvent { switch (opcode) { case 88: String password = ByteBufferUtils.getString(buffer); - if (!password.equals(PASSWORD)) { + if (!password.equals(ManagementConstants.getSECRET_KEY())) { System.out.println("Password mismatch (attempt=" + password + ")!"); session.disconnect(); break; diff --git a/Management-Server/src/main/java/ms/net/packet/IoBuffer.java b/Management-Server/src/main/java/ms/net/packet/IoBuffer.java index 8bd8199b7..c35fb5ab6 100644 --- a/Management-Server/src/main/java/ms/net/packet/IoBuffer.java +++ b/Management-Server/src/main/java/ms/net/packet/IoBuffer.java @@ -547,7 +547,7 @@ public class IoBuffer { long second = getIntB(); if (second < 0) second = second & 0xffffffffL; - return (first << -41780448) + second; + return (first << 32) + second; } /** @@ -567,7 +567,7 @@ public class IoBuffer { if (peek <= Short.MAX_VALUE) { return buf.getShort() & 0xFFFF; } - return (buf.getInt() & 0xFFFFFFFF) - 32768; + return buf.getInt() - 32768; } /** diff --git a/Management-Server/src/main/java/ms/net/packet/WorldPacketRepository.kt b/Management-Server/src/main/java/ms/net/packet/WorldPacketRepository.kt index 6b9233cae..b72f731e1 100644 --- a/Management-Server/src/main/java/ms/net/packet/WorldPacketRepository.kt +++ b/Management-Server/src/main/java/ms/net/packet/WorldPacketRepository.kt @@ -5,7 +5,7 @@ import ms.system.PunishmentStorage import ms.system.communication.ClanRank import ms.system.communication.ClanRepository import ms.system.communication.CommunicationInfo -import ms.system.util.ManagementConstants.Companion.WORLD_HOP_DELAY +import ms.system.util.ManagementConstants.WORLD_HOP_DELAY import ms.world.GameServer import ms.world.PlayerSession import ms.world.WorldDatabase diff --git a/Management-Server/src/main/java/ms/system/PunishmentStorage.java b/Management-Server/src/main/java/ms/system/PunishmentStorage.java index a82dad781..3fd0b00a5 100644 --- a/Management-Server/src/main/java/ms/system/PunishmentStorage.java +++ b/Management-Server/src/main/java/ms/system/PunishmentStorage.java @@ -49,7 +49,7 @@ public final class PunishmentStorage { return; } long end = Long.MAX_VALUE; - if (duration != -1l && duration != 0L) { + if (duration != -1L && duration != 0L) { end = System.currentTimeMillis() + duration; } else if (duration == 0L) { end = 0L; diff --git a/Management-Server/src/main/java/ms/system/communication/CommunicationInfo.java b/Management-Server/src/main/java/ms/system/communication/CommunicationInfo.java index 1fd106fd3..86afae5ec 100644 --- a/Management-Server/src/main/java/ms/system/communication/CommunicationInfo.java +++ b/Management-Server/src/main/java/ms/system/communication/CommunicationInfo.java @@ -12,10 +12,7 @@ import java.nio.ByteBuffer; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; /** @@ -184,9 +181,7 @@ public final class CommunicationInfo { String bl = set.getString("blocked"); if (bl != null && !bl.isEmpty()) { tokens = bl.split(","); - for (String name : tokens) { - blocked.add(name); - } + blocked.addAll(Arrays.asList(tokens)); } clanName = set.getString("clanName"); currentClan = set.getString("currentClan"); @@ -236,6 +231,9 @@ public final class CommunicationInfo { case 2: tradeSetting = Integer.parseInt(tokens[2]); break; + default: + System.out.println("Illegal arg count in chatsetting string: " + chatSettings); + break; } } } diff --git a/Management-Server/src/main/java/ms/system/mysql/SQLManager.kt b/Management-Server/src/main/java/ms/system/mysql/SQLManager.kt index e4704ea29..05affcacc 100644 --- a/Management-Server/src/main/java/ms/system/mysql/SQLManager.kt +++ b/Management-Server/src/main/java/ms/system/mysql/SQLManager.kt @@ -1,11 +1,11 @@ package ms.system.mysql import ms.system.util.ManagementConstants -import ms.system.util.ManagementConstants.Companion.DATABASE_HOST_ADDRESS -import ms.system.util.ManagementConstants.Companion.DATABASE_NAME -import ms.system.util.ManagementConstants.Companion.DATABASE_PASSWORD -import ms.system.util.ManagementConstants.Companion.DATABASE_PORT -import ms.system.util.ManagementConstants.Companion.DATABASE_USERNAME +import ms.system.util.ManagementConstants.DATABASE_HOST_ADDRESS +import ms.system.util.ManagementConstants.DATABASE_NAME +import ms.system.util.ManagementConstants.DATABASE_PASSWORD +import ms.system.util.ManagementConstants.DATABASE_PORT +import ms.system.util.ManagementConstants.DATABASE_USERNAME import java.sql.Connection import java.sql.DriverManager import java.sql.SQLException diff --git a/Management-Server/src/main/java/ms/system/util/ManagementConfigParser.kt b/Management-Server/src/main/java/ms/system/util/ManagementConfigParser.kt index 5cc872e9e..7aba7f237 100644 --- a/Management-Server/src/main/java/ms/system/util/ManagementConfigParser.kt +++ b/Management-Server/src/main/java/ms/system/util/ManagementConfigParser.kt @@ -30,19 +30,20 @@ class ManagementConfigParser(path: String) { data = parser.parse(reader) as JSONObject parseDatabaseInformation() parseWorldTechnicalSettings() + ManagementConstants.SECRET_KEY = data!!["secret_key"].toString() } } private fun parseDatabaseInformation(){ data ?: return val dbData = data!!["DatabaseInformation"] as JSONObject - ManagementConstants().parseDBProp(dbData) + ManagementConstants.parseDBProp(dbData) } private fun parseWorldTechnicalSettings(){ data ?: return val wtiData = data!!["WorldTechnicalInformation"] as JSONObject - ManagementConstants().parseWTIProp(wtiData) + ManagementConstants.parseWTIProp(wtiData) } /** diff --git a/Management-Server/src/main/java/ms/system/util/ManagementConstants.kt b/Management-Server/src/main/java/ms/system/util/ManagementConstants.kt index 5f07849c4..01d40fb5a 100644 --- a/Management-Server/src/main/java/ms/system/util/ManagementConstants.kt +++ b/Management-Server/src/main/java/ms/system/util/ManagementConstants.kt @@ -2,32 +2,31 @@ package ms.system.util import org.json.simple.JSONObject -class ManagementConstants { +object ManagementConstants { - companion object { + //MySQL main database name + var DATABASE_NAME: String = "global" - //MySQL main database name - var DATABASE_NAME: String = "global" + //MySQL database username + var DATABASE_USERNAME: String = "root" - //MySQL database username - var DATABASE_USERNAME: String = "root" + //MySQL database password + var DATABASE_PASSWORD: String = "" - //MySQL database password - var DATABASE_PASSWORD: String = "" + //MySQL host + var DATABASE_HOST_ADDRESS: String = "127.0.0.1" - //MySQL host - var DATABASE_HOST_ADDRESS: String = "127.0.0.1" + //MySQL port + var DATABASE_PORT: Int = 3306 - //MySQL port - var DATABASE_PORT: Int = 3306 + //Max amount of worlds supported on the world list + var MAX_WORLD_AMOUNT: Int = 10 - //Max amount of worlds supported on the world list - var MAX_WORLD_AMOUNT: Int = 10 + //User world hop delay in seconds + var WORLD_HOP_DELAY: Long = 20_000L - //User world hop delay in seconds - var WORLD_HOP_DELAY: Long = 20_000L - - } + @JvmStatic + var SECRET_KEY: String = "" fun parseDBProp(data: JSONObject) { DATABASE_NAME = data["database_name"].toString() diff --git a/Management-Server/src/main/java/ms/system/util/StringUtils.java b/Management-Server/src/main/java/ms/system/util/StringUtils.java index 2d997bb9a..2a85aea8f 100644 --- a/Management-Server/src/main/java/ms/system/util/StringUtils.java +++ b/Management-Server/src/main/java/ms/system/util/StringUtils.java @@ -409,8 +409,9 @@ public final class StringUtils { } } } - return -i_26_ + ((7 + i_30_) >> -662855293); + return -i_26_ + ((7 + i_30_) >> 3); } catch (RuntimeException runtimeexception) { + runtimeexception.printStackTrace(); } return 0; } diff --git a/Management-Server/src/main/java/ms/world/PlayerSession.java b/Management-Server/src/main/java/ms/world/PlayerSession.java index cccb91cf1..09c4682d5 100644 --- a/Management-Server/src/main/java/ms/world/PlayerSession.java +++ b/Management-Server/src/main/java/ms/world/PlayerSession.java @@ -66,7 +66,7 @@ public final class PlayerSession { /** * The time stamp of last disconnection. */ - private long disconnectionTime = 0l; + private long disconnectionTime = 0L; /** * How long the player is banned for. @@ -463,11 +463,8 @@ public final class PlayerSession { this.disconnectionTime = time; } - @Override - public boolean equals(Object o) { - if(o instanceof PlayerSession) { - return username.equals(((PlayerSession) o).username); - } else return false; + public boolean equalsSession(PlayerSession o){ + return username.equals(o.username); } @Override diff --git a/Management-Server/src/main/kotlin/ms09/MSLogger.kt b/Management-Server/src/main/kotlin/ms09/MSLogger.kt index b629b1595..5bd7a7b7f 100644 --- a/Management-Server/src/main/kotlin/ms09/MSLogger.kt +++ b/Management-Server/src/main/kotlin/ms09/MSLogger.kt @@ -9,12 +9,12 @@ import java.util.* object MSLogger { val t = Terminal() - val formatter = SimpleDateFormat("HH:mm:ss") var tradeLog: Writer? = null var tradeLogWriter: BufferedWriter? = null fun getTime(): String{ + val formatter = SimpleDateFormat("HH:mm:ss") return "[" + formatter.format(Date(System.currentTimeMillis())) +"]" } diff --git a/Server/data/configs/drop_tables.json b/Server/data/configs/drop_tables.json index c1777d621..288dad9d1 100644 --- a/Server/data/configs/drop_tables.json +++ b/Server/data/configs/drop_tables.json @@ -62771,7 +62771,7 @@ { "default": [], "charm": [], - "ids": "428, 429", + "ids": "428,429", "description": "Shade (Stronghold of Security) (So Shade Robes can drop)", "main": [ { diff --git a/Server/server.jar b/Server/server.jar deleted file mode 100644 index 7c1a8ef48..000000000 Binary files a/Server/server.jar and /dev/null differ diff --git a/Server/src/main/java/core/game/content/activity/CutscenePlugin.java b/Server/src/main/java/core/game/content/activity/CutscenePlugin.java index 4a999361f..bc9a214a1 100644 --- a/Server/src/main/java/core/game/content/activity/CutscenePlugin.java +++ b/Server/src/main/java/core/game/content/activity/CutscenePlugin.java @@ -100,6 +100,7 @@ public abstract class CutscenePlugin extends ActivityPlugin { unpause(); } player.unlock(); + player.getInterfaceManager().openDefaultTabs(); player.getWalkingQueue().reset(); player.getLocks().unlockMovement(); } diff --git a/Server/src/main/java/core/game/content/activity/guild/WizardGuildPlugin.java b/Server/src/main/java/core/game/content/activity/guild/WizardGuildPlugin.java index 9f94f10f3..3dfd6ad90 100644 --- a/Server/src/main/java/core/game/content/activity/guild/WizardGuildPlugin.java +++ b/Server/src/main/java/core/game/content/activity/guild/WizardGuildPlugin.java @@ -1,5 +1,6 @@ package core.game.content.activity.guild; +import api.ContentAPI; import core.cache.def.impl.NPCDefinition; import core.cache.def.impl.SceneryDefinition; import core.game.content.dialogue.DialoguePlugin; @@ -60,7 +61,7 @@ public final class WizardGuildPlugin extends OptionHandler { switch (id) { case 1600: case 1601: - if (player.getSkills().getStaticLevel(Skills.MAGIC) < 66) { + if (ContentAPI.getDynLevel(player, Skills.MAGIC) < 66) { player.getDialogueInterpreter().sendDialogue("You need a Magic level of at least 66 to enter."); return true; } diff --git a/Server/src/main/java/core/game/content/dialogue/BillTeachDialogue.java b/Server/src/main/java/core/game/content/dialogue/BillTeachDialogue.java deleted file mode 100644 index 8ec4998bc..000000000 --- a/Server/src/main/java/core/game/content/dialogue/BillTeachDialogue.java +++ /dev/null @@ -1,219 +0,0 @@ -package core.game.content.dialogue; - -import core.game.node.entity.npc.NPC; -import core.game.node.entity.player.Player; -import core.plugin.Initializable; -import core.game.world.map.Location; - -/** - * Represents the dialogue plugin used for Bill Teach - * @author Charlie - * @version 1.0 - */ -@Initializable -public final class BillTeachDialogue extends DialoguePlugin { - - /** - * Constructs a new {@code BarfyBill} {@code Object}. - */ - public BillTeachDialogue() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code BarfyBill} {@code Object}. - * @param player the player. - */ - public BillTeachDialogue(Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new BillTeachDialogue(player); - } - - @Override - public boolean open(Object... args) { - npc = new NPC(3155); - player("Hello there."); - stage = 0; - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 0: - npc("Arr'! Avast ye' scallywag!", "You be lookin' to get somewhere " + (player.isMale() ? "lad?" : "lass?")); - stage = 1; - break; - case 1: - interpreter.sendOptions("Select an Option", "Yes", "No, thank you"); - stage = 2; - break; - case 2: - switch (buttonId) { - case 1: - player("Yes, where can you take me?"); - stage = 1000; - break; - case 2: - npc("Arr'! You be wastin' my time again.."); - stage = 7; - break; - } - break; - case 1000: - npc("Aye, take a browse through me options."); - stage++; - break; - case 1001: - interpreter.sendOptions("Select an Option", "Slayer Tower", "Zanaris Fairy Ring", "Gnome Stronghold", "Rellekka", "More"); - stage = 2000; - break; - case 2000: - switch (buttonId) { - case 1: - if(!player.getQuestRepository().isComplete("Priest in Peril")) { - npc("Aye, sorry there " + pirateGender() + ", but you'll be needing to ", "help King Roald with something first."); - stage = 7; - } else { - end(); - player.teleport(new Location(3429, 3526, 0)); - } - break; - case 2: - if(!player.getQuestRepository().isComplete("Lost City")) { - npc("Aye, sorry there " + pirateGender() + ", but you'll be needing to ", "discover Zanaris first."); - stage = 7; - } else { - end(); - player.teleport(new Location(2412, 4433, 0)); - } - break; - case 3: - end(); - player.teleport(new Location(2461, 3444, 0)); - break; - case 4: - end(); - player.teleport(new Location(2669, 3631, 0)); - break; - case 5: - interpreter.sendOptions("Select an Option", "Kalphite Lair", "Asgarnian Ice Dungeon", "Fremmenik Dungeon", "Taverley Dungeon", "More"); - stage = 3000; - break; - } - break; - case 3000: - switch (buttonId) { - case 1: - end(); - player.teleport(new Location(3227, 3107, 0)); - break; - case 2: - end(); - player.teleport(new Location(3007, 9550, 0)); - break; - case 3: - end(); - player.teleport(new Location(2808, 10002, 0)); - break; - case 4: - end(); - player.teleport(new Location(2884, 9798, 0)); - break; - case 5: - interpreter.sendOptions("Select an Option", "Waterfall Dungeon", "Brimhaven Dungeon", "Ape Atoll Dungeon", "God Wars Dungeon", "More"); - stage = 4000; - break; - } - break; - case 4000: - switch (buttonId) { - case 1: - end(); - player.teleport(new Location(2575, 9861, 0)); - break; - case 2: - end(); - player.teleport(new Location(2713, 9564, 0)); - break; - case 3: - end(); - player.teleport(new Location(2715, 9184, 0)); - break; - case 4: - end(); - player.teleport(new Location(2898, 3710, 0)); - break; - case 5: - interpreter.sendOptions("Select an Option", "Shilo Village", "Yanille", "Zul-Andra", "Piscatoris Fishing Colony", "More"); - stage = 5000; - break; - } - break; - case 5000: - switch (buttonId) { - case 1: - end(); - player.teleport(new Location(2867, 2952, 0)); - break; - case 2: - end(); - player.teleport(new Location(2544, 3096, 0)); - break; - case 3: - end(); - player.teleport(new Location(2193, 3055, 0)); - break; - case 4: - end(); - player.teleport(new Location(2343, 3663, 0)); - break; - case 5: - interpreter.sendOptions("Select an Option", "Bandit Camp", "Miscellenia", "Mort'ton", "Feldip Hills", "Back"); - stage = 6000; - break; - } - break; - case 6000: - switch (buttonId) { - case 1: - end(); - player.teleport(new Location(3176, 2987, 0)); - break; - case 2: - end(); - player.teleport(new Location(2581, 3845, 0)); - break; - case 3: - end(); - player.teleport(new Location(3488, 3296, 0)); - break; - case 4: - end(); - player.teleport(new Location(2525, 2915, 0)); - break; - case 5: - interpreter.sendOptions("Select an Option", "Slayer Tower", "Zanaris Fairy Ring", "Gnome Stronghold", "Rellekka", "More"); - stage = 2000; - break; - } - break; - case 7: - end(); - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[] { 3155 }; - } - -} diff --git a/Server/src/main/java/core/game/content/dialogue/HansDialoguePlugin.java b/Server/src/main/java/core/game/content/dialogue/HansDialoguePlugin.java index 2639d98a0..2b2010c97 100644 --- a/Server/src/main/java/core/game/content/dialogue/HansDialoguePlugin.java +++ b/Server/src/main/java/core/game/content/dialogue/HansDialoguePlugin.java @@ -137,7 +137,7 @@ public final class HansDialoguePlugin extends DialoguePlugin { case 12: switch(buttonId){ case 1: - options("1.0x","2.5x","10x","20x"); + options("1.0x","2.5x","Stay 5.0x"); stage++; break; case 2: @@ -166,13 +166,9 @@ public final class HansDialoguePlugin extends DialoguePlugin { } break; case 3: - player.getSkills().experienceMutiplier = 10.0; - stage = 14; - break; - case 4: - player.getSkills().experienceMutiplier = 20.0; - stage = 14; - break; + playerl(FacialExpression.FRIENDLY, "I'd rather stay 5x, thank you."); + stage = END_DIALOGUE; + return true; } npc("One moment, please..."); break; diff --git a/Server/src/main/java/core/game/content/dialogue/SimonTempleton.java b/Server/src/main/java/core/game/content/dialogue/SimonTempleton.java index abe12c03e..47ea1a4c4 100644 --- a/Server/src/main/java/core/game/content/dialogue/SimonTempleton.java +++ b/Server/src/main/java/core/game/content/dialogue/SimonTempleton.java @@ -38,7 +38,6 @@ public final class SimonTempleton extends DialoguePlugin{ return true; } } - player.getPacketDispatch().sendMessage("" + args.length); npc("G'day, mate!. Got any new", "pyramid artefacts for me?"); return true; } diff --git a/Server/src/main/java/core/game/content/global/shop/Shop.java b/Server/src/main/java/core/game/content/global/shop/Shop.java deleted file mode 100644 index 5b44cfc1c..000000000 --- a/Server/src/main/java/core/game/content/global/shop/Shop.java +++ /dev/null @@ -1,913 +0,0 @@ -package core.game.content.global.shop; - -import api.ContentAPI; -import core.cache.def.impl.ItemDefinition; -import core.game.container.Container; -import core.game.container.ContainerType; -import org.rs09.consts.Items; -import core.game.node.entity.player.Player; -import core.game.node.entity.player.link.diary.DiaryType; -import core.game.node.item.Item; -import rs09.game.system.SystemLogger; -import rs09.game.system.config.ItemConfigParser; -import rs09.game.world.GameWorld; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * A class representing a shop. - * - * @author 'Vexia - * @author Jamix77 - */ -public class Shop { - - /** - * Represents the general store items. - */ - public final static Item[] GENERAL_STORE_ITEMS = new Item[]{ - new Item(Items.EMPTY_POT_1931,5), - new Item(Items.JUG_1935,5), - new Item(Items.SHEARS_1735,2), - new Item(Items.BUCKET_1925,3), - new Item(Items.BOWL_1923,2), - new Item(Items.CAKE_TIN_1887,2), - new Item(Items.TINDERBOX_590,2), - new Item(Items.CHISEL_1755,2), - new Item(Items.HAMMER_2347,5), - new Item(Items.NEWCOMER_MAP_550,5), - new Item(Items.SECURITY_BOOK_9003,5) - }; - /** - * Represents the coins item. - */ - private static final int COINS = 995; - /** - * Represents the tokkul item id. - */ - private static final int TOKKUL = 6529; - - /** - * Represents the archery ticket item id - */ - private static final int ARCHERY_TICKET = 1464; - - /** - * Represents the shop containers. - */ - private final Container[] containers = new Container[]{new Container(40, ContainerType.SHOP), new Container(40, ContainerType.SHOP)}; - /** - * Represents the list of shop viewers. - */ - private final List viewers = new ArrayList<>(20); - - /** - * Represents the title of the shop. - */ - private final String title; - - /** - * Represents the items in the store. - */ - private Item[] items; - - /** - * Represents if it's a general store. - */ - private final boolean general; - - /** - * Represents the currency the shop allows. - */ - private final int currency; - - /** - * If the shop buys for high alch. - */ - private final boolean highAlch; - - /** - * Sell price for all shop items, if needed. - */ - private int sellAllFor; - - /** - * The last restock. - */ - private int lastRestock; - - /** - * If the shop should restock. - */ - private boolean restock; - - /** - * If it's a point shop. - */ - private boolean pointShop; - - /** - * The npcs of the shop. - */ - private int[] npcs; - - /** - * Constructs a new {@code Shop} {@code Object}. - * - * @param title the title. - * @param items the items. - * @param general the general. - * @param currency the currency. - * @param highAlch if high alch. - */ - public Shop(String title, Item[] items, boolean general, int currency, boolean highAlch) { - this.title = title; - this.items = items; - this.general = general; - this.currency = currency; - this.highAlch = highAlch; - this.getContainer(0).add(items); - this.setRestock(true); - lastRestock = GameWorld.getTicks() + 100; - } - - - /** - * Constructs a new {@code Shop} {@code Object}. - * - * @param title the title. - * @param items the items. - * @param general the general. - * @param currency the currency. - * @param highAlch if high alch. - * @param restock if restock. - */ - public Shop(String title, Item[] items, boolean general, int currency, boolean highAlch, boolean restock, int sellAllFor) { - this(title, items, general, currency, highAlch); - this.sellAllFor = sellAllFor; - this.setRestock(restock); - } - - /** - * Constructs a new {@code Shop} {@code Object} - * - * @param title the shop title - * @param items items the shop can handle - * @param general is this a general store - * @param currency what currency is used - */ - public Shop(String title, Item[] items, int[] npcs, boolean general, int currency) { - this(title, items, general, currency, false); - this.setNpcs(npcs); - } - - /** - * Constructs a new {@code Shop} {@code Object}. - * - * @param title the title. - * @param items the items. - * @param general the general. - */ - public Shop(String title, Item[] items, boolean general) { - this(title, items, general, COINS, false); - } - - /** - * Constructs a new {@code Shop} {@code Object}. - * - * @param title the title. - * @param general the general. - */ - public Shop(String title, boolean general) { - this(title, GENERAL_STORE_ITEMS, general); - } - - /** - * Constructs a new {@code Shop} {@code Object}. - * - * @param title the title. - * @param general the general. - * @param highAlch if highAlch. - */ - public Shop(String title, boolean general, boolean highAlch) { - this(title, GENERAL_STORE_ITEMS, general, COINS, highAlch); - } - - /** - * Constructs a new {@code Shop} {@code Object}. - * - * @param title the title. - * @param general the general. - * @param highAlch if highAlch. - */ - public Shop(String title, boolean general, int currency, boolean highAlch) { - this(title, GENERAL_STORE_ITEMS, general, currency, highAlch); - } - - /** - * Constructs a new {@code Shop} {@code Object}. - * - * @param title the title. - * @param items the items. - * @param npcs the npcs. - * @param general the general. - */ - public Shop(String title, Item[] items, int[] npcs, boolean general) { - this(title, items, general, COINS, false); - this.setNpcs(npcs); - } - - /** - * Constructs a new {@code Shop} {@code Object}. - * - * @param title the title. - * @param npcs the npcs. - * @param general the general. - */ - public Shop(String title, int[] npcs, boolean general) { - this(title, GENERAL_STORE_ITEMS, npcs, general); - this.setNpcs(npcs); - } - - /** - * Constructs a new {@code Shop} {@code Object}. - * - * @param title the title. - * @param npcs the npcs. - * @param general the general. - * @param highAlch if highAlch. - */ - public Shop(String title, int[] npcs, boolean general, boolean highAlch) { - this(title, GENERAL_STORE_ITEMS, general, 995, highAlch); - this.setNpcs(npcs); - } - - /** - * Method used to open the shop. - * - * @param player the shop. - */ - public void open(final Player player) { - ShopViewer.extend(player, this).open(); - - // Browse the Lumbridge General Store - if (getTitle().equalsIgnoreCase("Lumbridge General Store")) { - player.getAchievementDiaryManager().finishTask(player, DiaryType.LUMBRIDGE, 0, 18); - } - - // Browse through Oziach's Armour Shop - if (getTitle().equalsIgnoreCase("Oziach's Armour")) { - player.getAchievementDiaryManager().finishTask(player, DiaryType.VARROCK, 1, 20); - } - } - - public void give(Player player, final int slot, int amount, int tabIndex) { - final Container container = getContainer(tabIndex); - final Item item = container.get(slot); - if (item == null) { - return; - } - final Item add = new Item(item.getId(), amount); - if (add.getAmount() < 1 || !player.getInventory().hasSpaceFor(add)) { - player.getPacketDispatch().sendMessage("You have no inventory space at the moment and cannot get anything."); - return; - } - add.setAmount(getAmount(player, add)); - if (add.getAmount() < 1 || !player.getInventory().hasSpaceFor(add)) { - player.getPacketDispatch().sendMessage("You have no inventory space at the moment and cannot get anything."); - return; - } - player.getInventory().add(add); - update(); - } - - /** - * Method used to buy an item from the shop. - * - * @param slot the slot. - * @param amount the amount. - */ - public void buy(Player player, final int slot, int amount, int tabIndex) { - if (tabIndex == 1 && player.getIronmanManager().checkRestriction()) { - return; - } - final Container container = getContainer(tabIndex); - final Item item = container.get(slot); - if (item == null) { - return; - } - if (item.getAmount() == 0) { - player.getPacketDispatch().sendMessage("There is no stock of that item at the moment."); - return; - } - if (amount > item.getAmount() && !(item.getAmount() == -1)) { - amount = item.getAmount(); - } - final Item add = new Item(item.getId(), amount); - if (player.getInventory().getMaximumAdd(add) < amount) { - add.setAmount(player.getInventory().getMaximumAdd(add)); - } - if (add.getAmount() < 1 || !player.getInventory().hasSpaceFor(add)) { - player.getPacketDispatch().sendMessage("You have no inventory space at the moment and cannot buy anything."); - return; - } - add.setAmount(getAmount(player, add)); - if (add.getAmount() < 1 || !player.getInventory().hasSpaceFor(add)) { - player.getPacketDispatch().sendMessage("You have no inventory space at the moment and cannot buy anything."); - return; - } - int price = add.getAmount() * getBuyPrice(item, player); - final Item currency = new Item(getCurrency(), price); - if (!canBuy(player, item, price, currency)) { - return; - } - if (handleBuy(player, currency)) { - if (pointShop) { - decrementPoints(player, price); - } - if (tabIndex == 0) { - if(!(container.getAmount(item) == -1)) - container.replace(new Item(item.getId(), container.getAmount(item) - add.getAmount()), slot, true); - } else { - container.remove(add); - container.shift(); - } - - // Achievement Diary Handlers - if (add.getId() == Items.BLACK_CHAINBODY_1107 && getTitle().equalsIgnoreCase("Wayne's Chains") && !player.getAttribute("diary:falador:black-chain-bought", false)) { - player.setAttribute("/save:diary:falador:black-chain-bought", true); - } - if (add.getId() == 12622 && getTitle().equalsIgnoreCase("Sarah's Farming Shop")) { - player.getAchievementDiaryManager().finishTask(player, DiaryType.FALADOR, 0, 0); - } - if (add.getId() == Items.CANDLE_36 && getTitle().equalsIgnoreCase("Candle Shop")) { - player.getAchievementDiaryManager().finishTask(player, DiaryType.SEERS_VILLAGE, 0, 9); - } - if (getTitle().equalsIgnoreCase("Ranging Guild Ticket Exchange")) { - player.getAchievementDiaryManager().finishTask(player, DiaryType.SEERS_VILLAGE, 1, 8); - } - - player.getInventory().add(add); - update(); - } - } - - /** - * Method used to sell an item to the shop. - * - * @param slot the slot. - * @param amount the amount. - */ - public void sell(Player player, final int slot, int amount, int tabIndex) { - final Item item = player.getInventory().get(slot); - if (item == null) { - return; - } - final ItemDefinition def = ItemDefinition.forId(item.getId()); - if (!canSell(player, item, def)) { - return; - } - final Container container = getContainer(item); - if (amount > player.getInventory().getAmount(item)) { - amount = player.getInventory().getAmount(item); - } - Item add = new Item(item.getId(), amount); - if (add.getAmount() > container.getMaximumAdd(add)) { - add.setAmount(container.getMaximumAdd(add)); - } - player.debug("" + add.getAmount()); - if (!container.hasSpaceFor(add) || add.getAmount() < 1) { - player.getPacketDispatch().sendMessage("The shop has ran out of space."); - return; - } - final Item currency = new Item(getCurrency(), getSellingValue(add, player)); - if(item.getDefinition().isStackable()){ - if (!player.getInventory().hasSpaceFor(currency)) { - player.getPacketDispatch().sendMessage("You don't have enough space for that many " + currency.getName().toLowerCase() + "."); - return; - } - } - player.debug("Selling item"); - if (player.getInventory().remove(add, slot, true)) { - if (currency.getAmount() > player.getInventory().getMaximumAdd(currency)) { - currency.setAmount(player.getInventory().getMaximumAdd(currency)); - } - if (!add.getDefinition().isUnnoted()) { - add = new Item(add.getNoteChange(), add.getAmount()); - } - if (container.getAmount(add.getId()) == -1 || container.add(add)) { - if (currency.getAmount() > 0) { - player.debug("Adding coins to inventory"); - player.getInventory().add(currency); - } - final ShopViewer viewer = player.getExtension(ShopViewer.class); - tabIndex = container == getContainers()[0] ? 0 : 1; - sendStock(player, tabIndex); - if (viewer != null) { - viewer.setTabIndex(tabIndex); - } - update(); - } - } - } - - /** - * Values an item. - * - * @param player the player. - * @param viewer the viewer. - * @param item the item. - * @param sell the sell. - */ - public void value(Player player, ShopViewer viewer, Item item, boolean sell) { - if (sell) { - if (pointShop || item.getId() == viewer.getShop().getCurrency() || !item.getDefinition().isTradeable() || !viewer.getShop().itemAllowed(item.getId())) { - player.getPacketDispatch().sendMessage("You can't sell this item."); - return; - } - final int value = viewer.getShop().getSellingValue(new Item(item.getId(), 1), player); - String currency = pointShop ? getPointsName() : ItemDefinition.forId(viewer.getShop().getCurrency()).getName().toLowerCase(); - if (value == 1 && currency.charAt(currency.length() - 1) == 's') { - currency = currency.substring(0, currency.length() - 1); - } - player.getPacketDispatch().sendMessage(item.getName() + ": shop will buy for " + value + " " + currency + "."); - } else { - int value = viewer.getShop().getBuyPrice(item, player); - String name = pointShop ? getPointsName() + "s" : ItemDefinition.forId(viewer.getShop().getCurrency()).getName().toLowerCase(); - if (value == 1 && (name.charAt(name.length() - 1) == 's')) { - name = name.substring(0, name.length() - 1); - } - player.getPacketDispatch().sendMessage("" + item.getName() + ": currently costs " + value + " " + name + "."); - } - } - - /** - * Method used to send a stock - * - * @param player - * @param tabIndex - */ - public void sendStock(final Player player, int tabIndex) { - final boolean main = tabIndex == 0; - player.getPacketDispatch().sendInterfaceConfig(620, 23, !main); - player.getPacketDispatch().sendInterfaceConfig(620, 24, main); - player.getPacketDispatch().sendInterfaceConfig(620, 29, !main); - player.getPacketDispatch().sendInterfaceConfig(620, 25, main); - player.getPacketDispatch().sendInterfaceConfig(620, 27, main); - player.getPacketDispatch().sendInterfaceConfig(620, 26, false); - player.getPacketDispatch().sendAccessMask(1278, main ? 23 : 24, 620, 0, 40); - } - - /** - * Method used to update the viewers. - */ - public void update() { - for (ShopViewer viewer : viewers) { - viewer.update(); - } - } - - /** - * Method used to restock the shop. - */ - public void restock() { - for (Container container : containers) { - for (int i = 0; i < container.toArray().length; i++) { - final boolean main = (container == containers[0]); - final Item item = container.toArray()[i]; - if (item == null) { - continue; - } - boolean reduce = !main; - if (main) { - if (item.getAmount() < items[i].getAmount()) { - item.setAmount(item.getAmount() + 1); - } - reduce = item.getAmount() > items[i].getAmount(); - } - if (reduce) { - int amount = item.getAmount() - 1; - if (amount < 1 && !main) { - container.remove(item); - } else { - item.setAmount(amount); - } - if (!main) { - container.shift(); - } - } - } - } - update(); - } - - /** - * Checks if the player can sell an item to the shop. - * - * @param player the player. - * @param item the item. - * @param def the def. - * @return {@code True} if so. - */ - public boolean canSell(Player player, Item item, ItemDefinition def) { - if (pointShop || item.getDefinition().hasDestroyAction() || !def.isTradeable() || !itemAllowed(item.getId())) { - player.getPacketDispatch().sendMessage("You can't sell this item to this shop."); - return false; - } - if (item.getId() == getCurrency()) { - player.getPacketDispatch().sendMessage("You can't sell " + item.getName().toLowerCase() + " to a shop."); - return false; - } - return true; - } - - /** - * Gets the amount to buy/sell. - * - * @param player the player. - * @param add the added item. - * @return the amount. - */ - public int getAmount(Player player, Item add) { - return add.getAmount(); - } - - /** - * Checks if the player can buy the item. - * - * @param player the player. - * @param currency the currency. - * @return {@code True} if so. - */ - public boolean handleBuy(Player player, Item currency) { - return pointShop || player.getInventory().remove(currency); - } - - /** - * Checks if the player can buy from the shop. - * - * @param player the player. - * @param item the item. - * @param price the price. - * @param currency the currency. - * @return {@code True} if they can buy. - */ - public boolean canBuy(Player player, Item item, int price, Item currency) { - if (!pointShop && !player.getInventory().containsItem(currency)) { - player.getPacketDispatch().sendMessage("You don't have enough " + ItemDefinition.forId(getCurrency()).getName().toLowerCase() + "."); - return false; - } - if (pointShop && getPoints(player) < price) { - player.sendMessage("You don't have enough " + getPointsName() + "s."); - return false; - } - return true; - } - - /** - * Gets the points. - * - * @param player the player. - * @return the points. - */ - public int getPoints(Player player) { - return 0; - } - - /** - * Decrements the points. - * - * @param player the player. - * @param decrement the decrementation. - */ - public void decrementPoints(Player player, int decrement) { - - } - - /** - * Gets the points name. - * - * @return the name. - */ - public String getPointsName() { - return ""; - } - - /** - * Gets the value gained for selling this item to a certain shop. - * - * @param item The item to sell. - * @param player the player. - * @return The value. - */ - public int getSellingValue(Item item, Player player) { - if (!item.getDefinition().isUnnoted()) { - player.setAttribute("shop:originalId",item.getId()); - item = new Item(item.getNoteChange(), item.getAmount()); - } - int amount = getContainer(1).getAmount(item); - if (amount < 1) { - amount = getContainer(0).getAmount(item); - } - int value = getSellValue(player, amount, item); - return value; - } - - /** - * Gets the selling value formula based. - * - * @param amount the amount. - * @param item the item. - * @return the selling value. - */ - private int getSellValue(Player player, int amount, Item item) { - int id = player.getAttribute("shop:originalId",item.getId()); - if(item.getAmount() > ContentAPI.amountInInventory(player, id)){ - item.setAmount(ContentAPI.amountInInventory(player, id)); - player.removeAttribute("shop:originalId"); - } - double diff = item.getDefinition().isStackable() ? 0.005 : 0.05; - double maxMod = 1.0 - (amount * diff); - if (maxMod < 0.25) { - maxMod = 0.25; - } - double minMod = maxMod - ((item.getAmount() - 1) * diff); - if (minMod < 0.25) { - minMod = 0.25; - } - double mod = (maxMod + minMod) / 2; - SystemLogger.logInfo("" + item.getDefinition().getAlchemyValue(highAlch) + " " + mod + " " + item.getAmount()); - int baseValue = item.getDefinition().getAlchemyValue(highAlch); - int value = (int) (baseValue * mod * item.getAmount()); - if(getCurrency() == Items.TOKKUL_6529 && item.getId() == Items.CHAOS_RUNE_562) value = 13; - if(getCurrency() == Items.TOKKUL_6529 && item.getId() == Items.DEATH_RUNE_560) value = 27; - if(item.getId() == 12183){ - value = 25 * item.getAmount(); - } - return value; - } - - /** - * Gets the buying price. - * - * @param item the item. - * @return the price. - */ - public int getBuyPrice(Item item, Player player) { - item = new Item(item.getId(), 1); - int price = item.getDefinition().getMaxValue(); - int sellVal = getSellingValue(item, player); - if (price < sellVal) { - price = getSellValue(player, 0, item) + sellVal - (sellVal - item.getDefinition().getMaxValue()); - } - if (price < 0) { - price = 1; - } - if (getCurrency() == TOKKUL) { - int tokkul = item.getDefinition().getConfiguration("tokkul_price", -1); - if (tokkul > 0) { - price = tokkul; - } - if (player.getAchievementDiaryManager().getKaramjaGlove() != -1) { - price *= 0.86666666667; - } - } - if (getCurrency() == ARCHERY_TICKET) { - int tickets = item.getDefinition().getConfiguration(ItemConfigParser.ARCHERY_TICKET_PRICE,-1); - if (tickets > 0) { - price = tickets; - } - } - return (getSellAllFor() > 0 ? getSellAllFor() : price); - } - - /** - * Checks if the item is allowed to be sold to the shop. - * - * @param itemId the item id. - * @return {@code True} if so. - */ - public boolean itemAllowed(int itemId) { - if (general) { - return true; - } - int noteId = ItemDefinition.forId(itemId).getNoteId(); - if (!ItemDefinition.forId(itemId).isUnnoted()) { - noteId = ItemDefinition.forId(noteId).getNoteId(); - } - for (Item id : items) { - if (itemId == id.getId() || (noteId > -1 && noteId == ItemDefinition.forId(id.getId()).getNoteId())) { - return true; - } - } - return false; - } - - /** - * Gets the container the item should go to. - * - * @param item the item. - * @return the container. - */ - public Container getContainer(Item item) { - int itemId = item.getId(); - int noteId = ItemDefinition.forId(itemId).getNoteId(); - if (!ItemDefinition.forId(itemId).isUnnoted()) { - noteId = ItemDefinition.forId(noteId).getNoteId(); - } - for (Item i : items) { - if (i.getId() == item.getId() || (noteId > -1 && noteId == ItemDefinition.forId(i.getId()).getNoteId())) { - return getContainer(0); - } - } - return getContainer(1); - } - - /** - * Creates a copy of this shop. - * - * @return the shop. - */ - public Shop copy() { - return new Shop(title, items, general, currency, highAlch); - } - - /** - * Gets the container on the slot. - * - * @param tabIndex the tab index. - * @return the container. - */ - public Container getContainer(int tabIndex) { - if (tabIndex > containers.length) { - throw new IndexOutOfBoundsException("Error! Shop tab index out of bounds."); - } - return containers[tabIndex]; - } - - /** - * Gets the viewers. - * - * @return The viewers. - */ - public List getViewers() { - return viewers; - } - - /** - * Gets the title. - * - * @return The title. - */ - public String getTitle() { - return title; - } - - /** - * Gets the items. - * - * @return The items. - */ - public Item[] getItems() { - return items; - } - - /** - * Sets the items. - * - * @return true if the items were changed. - */ - public boolean setItems(Item... item) { - return items == item; - } - - /** - * Gets the general. - * - * @return The general. - */ - public boolean isGeneral() { - return general; - } - - /** - * Gets the currency. - * - * @return The currency. - */ - public int getCurrency() { - return currency; - } - - /** - * Gets the containers. - * - * @return The containers. - */ - public Container[] getContainers() { - return containers; - } - - /** - * Gets the bhighAlch. - * - * @return the highAlch - */ - public boolean isHighAlch() { - return highAlch; - } - - @Override - public String toString() { - return "Shop [containers=" + Arrays.toString(containers) + ", viewers=" + viewers + ", title=" + title + ", items=" + Arrays.toString(items) + ", general=" + general + ", currency=" + currency + ", highAlch=" + highAlch + "]"; - } - - /** - * Gets the lastRestock. - * - * @return the lastRestock - */ - public int getLastRestock() { - return lastRestock; - } - - /** - * Sets the balastRestock. - * - * @param lastRestock the lastRestock to set. - */ - public void setLastRestock(int lastRestock) { - this.lastRestock = lastRestock; - } - - /** - * Gets the npcs. - * - * @return the npcs - */ - public int[] getNpcs() { - return npcs; - } - - /** - * Sets the banpcs. - * - * @param npcs the npcs to set. - */ - public void setNpcs(int[] npcs) { - this.npcs = npcs; - } - - /** - * Gets the pointShop. - * - * @return the pointShop - */ - public boolean isPointShop() { - return pointShop; - } - - /** - * Sets the pointShop. - * - * @param pointShop the pointShop to set. - */ - public void setPointShop(boolean pointShop) { - this.pointShop = pointShop; - } - - /** - * Check if shop should restock. - * - * @return the restock - */ - public boolean isRestock() { - return restock; - } - - /** - * Sets the restock. - * - * @param reStock - */ - public void setRestock(boolean reStock) { - restock = reStock; - } - - - /** - * Gets the SellAllFor value. - * - * @return the sellAllFor - */ - public int getSellAllFor() { - return sellAllFor; - } - - public void setItems(ArrayList items){ - this.items = items.toArray(new Item[0]); - } - -} \ No newline at end of file diff --git a/Server/src/main/java/core/game/content/global/shop/Shop.kt b/Server/src/main/java/core/game/content/global/shop/Shop.kt new file mode 100644 index 000000000..1ae9e865e --- /dev/null +++ b/Server/src/main/java/core/game/content/global/shop/Shop.kt @@ -0,0 +1,865 @@ +package core.game.content.global.shop + +import rs09.game.world.GameWorld.ticks +import api.ContentAPI.amountInInventory +import rs09.game.system.SystemLogger.logInfo +import core.game.node.entity.player.link.diary.DiaryType +import core.cache.def.impl.ItemDefinition +import core.game.container.Container +import core.game.container.ContainerType +import core.game.node.entity.player.Player +import core.game.node.item.Item +import org.rs09.consts.Items.BLACK_CHAINBODY_1107 +import org.rs09.consts.Items.BOWL_1923 +import org.rs09.consts.Items.BUCKET_1925 +import org.rs09.consts.Items.CAKE_TIN_1887 +import org.rs09.consts.Items.CANDLE_36 +import org.rs09.consts.Items.CHAOS_RUNE_562 +import org.rs09.consts.Items.CHISEL_1755 +import org.rs09.consts.Items.DEATH_RUNE_560 +import org.rs09.consts.Items.EMPTY_POT_1931 +import org.rs09.consts.Items.HAMMER_2347 +import org.rs09.consts.Items.JUG_1935 +import org.rs09.consts.Items.NEWCOMER_MAP_550 +import org.rs09.consts.Items.SECURITY_BOOK_9003 +import org.rs09.consts.Items.SHEARS_1735 +import org.rs09.consts.Items.TINDERBOX_590 +import org.rs09.consts.Items.TOKKUL_6529 +import rs09.game.system.config.ItemConfigParser +import java.lang.IndexOutOfBoundsException +import java.util.Arrays +import java.util.ArrayList + +/** + * A class representing a shop. + * + * @author 'Vexia + * @author Jamix77 + */ +open class Shop @JvmOverloads constructor( + /** + * Represents the title of the shop. + */ + val title: String, + /** + * Represents the items in the store. + */ + var items: Array, + /** + * Represents if it's a general store. + */ + val isGeneral: Boolean, + /** + * Represents the currency the shop allows. + */ + val currency: Int = COINS, + /** + * If the shop buys for high alch. + */ + val isHighAlch: Boolean = false +) { + /** + * Gets the containers. + * + * @return The containers. + */ + /** + * Represents the shop containers. + */ + val containers = arrayOf(Container(40, ContainerType.SHOP), Container(40, ContainerType.SHOP)) + /** + * Gets the viewers. + * + * @return The viewers. + */ + /** + * Represents the list of shop viewers. + */ + val viewers: List = ArrayList(20) + /** + * Gets the title. + * + * @return The title. + */ + /** + * Gets the items. + * + * @return The items. + */ + /** + * Gets the general. + * + * @return The general. + */ + /** + * Gets the currency. + * + * @return The currency. + */ + /** + * Gets the bhighAlch. + * + * @return the highAlch + */ + /** + * Gets the SellAllFor value. + * + * @return the sellAllFor + */ + /** + * Sell price for all shop items, if needed. + */ + var sellAllFor = 0 + private set + /** + * Gets the lastRestock. + * + * @return the lastRestock + */ + /** + * Sets the balastRestock. + * + * @param lastRestock the lastRestock to set. + */ + /** + * The last restock. + */ + var lastRestock = 0 + /** + * Check if shop should restock. + * + * @return the restock + */ + /** + * Sets the restock. + * + * @param reStock + */ + /** + * If the shop should restock. + */ + var isRestock = false + /** + * Gets the pointShop. + * + * @return the pointShop + */ + /** + * Sets the pointShop. + * + * @param pointShop the pointShop to set. + */ + /** + * If it's a point shop. + */ + var isPointShop = false + /** + * Gets the npcs. + * + * @return the npcs + */ + /** + * Sets the banpcs. + * + * @param npcs the npcs to set. + */ + /** + * The npcs of the shop. + */ + var npcs: IntArray = intArrayOf() + + /** + * Constructs a new `Shop` `Object`. + * + * @param title the title. + * @param items the items. + * @param general the general. + * @param currency the currency. + * @param highAlch if high alch. + * @param restock if restock. + */ + constructor( + title: String, + items: Array, + general: Boolean, + currency: Int, + highAlch: Boolean, + restock: Boolean, + sellAllFor: Int + ) : this(title, items, general, currency, highAlch) { + this.sellAllFor = sellAllFor + isRestock = restock + } + + /** + * Constructs a new `Shop` `Object` + * + * @param title the shop title + * @param items items the shop can handle + * @param general is this a general store + * @param currency what currency is used + */ + constructor(title: String, items: Array, npcs: IntArray, general: Boolean, currency: Int) : this( + title, + items, + general, + currency, + false + ) { + this.npcs = npcs + } + + /** + * Constructs a new `Shop` `Object`. + * + * @param title the title. + * @param general the general. + */ + constructor(title: String, general: Boolean) : this(title, GENERAL_STORE_ITEMS, general) {} + + /** + * Constructs a new `Shop` `Object`. + * + * @param title the title. + * @param general the general. + * @param highAlch if highAlch. + */ + constructor(title: String, general: Boolean, highAlch: Boolean) : this( + title, + GENERAL_STORE_ITEMS, + general, + COINS, + highAlch + ) { + } + + /** + * Constructs a new `Shop` `Object`. + * + * @param title the title. + * @param general the general. + * @param highAlch if highAlch. + */ + constructor(title: String, general: Boolean, currency: Int, highAlch: Boolean) : this( + title, + GENERAL_STORE_ITEMS, + general, + currency, + highAlch + ) { + } + + /** + * Constructs a new `Shop` `Object`. + * + * @param title the title. + * @param items the items. + * @param npcs the npcs. + * @param general the general. + */ + constructor(title: String, items: Array, npcs: IntArray, general: Boolean) : this( + title, + items, + general, + COINS, + false + ) { + this.npcs = npcs + } + + /** + * Constructs a new `Shop` `Object`. + * + * @param title the title. + * @param npcs the npcs. + * @param general the general. + */ + constructor(title: String, npcs: IntArray, general: Boolean) : this(title, GENERAL_STORE_ITEMS, npcs, general) { + this.npcs = npcs + } + + /** + * Constructs a new `Shop` `Object`. + * + * @param title the title. + * @param npcs the npcs. + * @param general the general. + * @param highAlch if highAlch. + */ + constructor(title: String, npcs: IntArray, general: Boolean, highAlch: Boolean) : this( + title, + GENERAL_STORE_ITEMS, + general, + 995, + highAlch + ) { + this.npcs = npcs + } + + /** + * Method used to open the shop. + * + * @param player the shop. + */ + fun open(player: Player) { + ShopViewer.extend(player, this).open() + + // Browse the Lumbridge General Store + if (title.equals("Lumbridge General Store", ignoreCase = true)) { + player.achievementDiaryManager.finishTask(player, DiaryType.LUMBRIDGE, 0, 18) + } + + // Browse through Oziach's Armour Shop + if (title.equals("Oziach's Armour", ignoreCase = true)) { + player.achievementDiaryManager.finishTask(player, DiaryType.VARROCK, 1, 20) + } + } + + fun give(player: Player, slot: Int, amount: Int, tabIndex: Int) { + val container = getContainer(tabIndex) + val item = container[slot] ?: return + val add = Item(item.id, amount) + if (add.amount < 1 || !player.inventory.hasSpaceFor(add)) { + player.packetDispatch.sendMessage("You have no inventory space at the moment and cannot get anything.") + return + } + add.amount = getAmount(player, add) + if (add.amount < 1 || !player.inventory.hasSpaceFor(add)) { + player.packetDispatch.sendMessage("You have no inventory space at the moment and cannot get anything.") + return + } + player.inventory.add(add) + update() + } + + /** + * Method used to buy an item from the shop. + * + * @param slot the slot. + * @param amount the amount. + */ + fun buy(player: Player, slot: Int, amount: Int, tabIndex: Int) { + var amount = amount + if (tabIndex == 1 && player.ironmanManager.checkRestriction()) { + return + } + val container = getContainer(tabIndex) + val item = container[slot] ?: return + if (item.amount == 0) { + player.packetDispatch.sendMessage("There is no stock of that item at the moment.") + return + } + if (amount > item.amount && item.amount != -1) { + amount = item.amount + } + val add = Item(item.id, amount) + if (player.inventory.getMaximumAdd(add) < amount) { + add.amount = player.inventory.getMaximumAdd(add) + } + if (add.amount < 1 || !player.inventory.hasSpaceFor(add)) { + player.packetDispatch.sendMessage("You have no inventory space at the moment and cannot buy anything.") + return + } + add.amount = getAmount(player, add) + if (add.amount < 1 || !player.inventory.hasSpaceFor(add)) { + player.packetDispatch.sendMessage("You have no inventory space at the moment and cannot buy anything.") + return + } + val price = add.amount * getBuyPrice(item, player) + val currency = Item(currency, price) + if (!canBuy(player, item, price, currency)) { + return + } + if (handleBuy(player, currency)) { + if (isPointShop) { + decrementPoints(player, price) + } + if (tabIndex == 0) { + if (container.getAmount(item) != -1) container.replace( + Item( + item.id, + container.getAmount(item) - add.amount + ), slot, true + ) + } else { + container.remove(add) + container.shift() + } + + // Achievement Diary Handlers + if (add.id == BLACK_CHAINBODY_1107 && title.equals("Wayne's Chains", ignoreCase = true) && !player.getAttribute("diary:falador:black-chain-bought", false)) { + player.setAttribute("/save:diary:falador:black-chain-bought", true) + } + if (add.id == 12622 && title.equals("Sarah's Farming Shop", ignoreCase = true)) { + player.achievementDiaryManager.finishTask(player, DiaryType.FALADOR, 0, 0) + } + if (add.id == CANDLE_36 && title.equals("Candle Shop", ignoreCase = true)) { + player.achievementDiaryManager.finishTask(player, DiaryType.SEERS_VILLAGE, 0, 9) + } + if (title.equals("Ranging Guild Ticket Exchange", ignoreCase = true)) { + player.achievementDiaryManager.finishTask(player, DiaryType.SEERS_VILLAGE, 1, 8) + } + player.inventory.add(add) + update() + } + } + + /** + * Method used to sell an item to the shop. + * + * @param slot the slot. + * @param amount the amount. + */ + fun sell(player: Player, slot: Int, amount: Int, tabIndex: Int) { + var amount = amount + var tabIndex = tabIndex + val item = player.inventory[slot] ?: return + val def = ItemDefinition.forId(item.id) + if (!canSell(player, item, def)) { + return + } + val container = getContainer(item) + if (amount > player.inventory.getAmount(item)) { + amount = player.inventory.getAmount(item) + } + var add = Item(item.id, amount) + if (add.amount > container.getMaximumAdd(add)) { + add.amount = container.getMaximumAdd(add) + } + player.debug("" + add.amount) + if (!container.hasSpaceFor(add) || add.amount < 1) { + player.packetDispatch.sendMessage("The shop has ran out of space.") + return + } + val currency = Item(currency, getSellingValue(add, player)) + if (item.definition.isStackable) { + if (!player.inventory.hasSpaceFor(currency)) { + player.packetDispatch.sendMessage("You don't have enough space for that many " + currency.name.toLowerCase() + ".") + return + } + } + player.debug("Selling item") + if (player.inventory.remove(add, slot, true)) { + if (currency.amount > player.inventory.getMaximumAdd(currency)) { + currency.amount = player.inventory.getMaximumAdd(currency) + } + if (!add.definition.isUnnoted) { + add = Item(add.noteChange, add.amount) + } + if (container.getAmount(add.id) == -1 || container.add(add)) { + if (currency.amount > 0) { + player.debug("Adding coins to inventory") + player.inventory.add(currency) + } + val viewer = player.getExtension(ShopViewer::class.java) + tabIndex = if (container === containers[0]) 0 else 1 + sendStock(player, tabIndex) + if (viewer != null) { + viewer.tabIndex = tabIndex + } + update() + } + } + } + + /** + * Values an item. + * + * @param player the player. + * @param viewer the viewer. + * @param item the item. + * @param sell the sell. + */ + fun value(player: Player, viewer: ShopViewer, item: Item, sell: Boolean) { + if (sell) { + if (isPointShop || item.id == viewer.shop.currency || !item.definition.isTradeable || !viewer.shop.itemAllowed( + item.id + ) + ) { + player.packetDispatch.sendMessage("You can't sell this item.") + return + } + val value = viewer.shop.getSellingValue(Item(item.id, 1), player) + var currency = + if (isPointShop) pointsName else ItemDefinition.forId(viewer.shop.currency).name.toLowerCase() + if (value == 1 && currency[currency.length - 1] == 's') { + currency = currency.substring(0, currency.length - 1) + } + player.packetDispatch.sendMessage(item.name + ": shop will buy for " + value + " " + currency + ".") + } else { + val value = viewer.shop.getBuyPrice(item, player) + var name = + if (isPointShop) pointsName + "s" else ItemDefinition.forId(viewer.shop.currency).name.toLowerCase() + if (value == 1 && name[name.length - 1] == 's') { + name = name.substring(0, name.length - 1) + } + player.packetDispatch.sendMessage("" + item.name + ": currently costs " + value + " " + name + ".") + } + } + + /** + * Method used to send a stock + * + * @param player + * @param tabIndex + */ + fun sendStock(player: Player, tabIndex: Int) { + val main = tabIndex == 0 + player.packetDispatch.sendInterfaceConfig(620, 23, !main) + player.packetDispatch.sendInterfaceConfig(620, 24, main) + player.packetDispatch.sendInterfaceConfig(620, 29, !main) + player.packetDispatch.sendInterfaceConfig(620, 25, main) + player.packetDispatch.sendInterfaceConfig(620, 27, main) + player.packetDispatch.sendInterfaceConfig(620, 26, false) + player.packetDispatch.sendAccessMask(1278, if (main) 23 else 24, 620, 0, 40) + } + + /** + * Method used to update the viewers. + */ + fun update() { + for (viewer in viewers) { + viewer.update() + } + } + + /** + * Method used to restock the shop. + */ + fun restock() { + for (container in containers) { + for (i in container.toArray().indices) { + val main = container === containers[0] + val item = container.toArray()[i] ?: continue + var reduce = !main + if (main) { + if (item.amount < items[i].amount) { + item.amount = item.amount + 1 + } + reduce = item.amount > items[i].amount + } + if (reduce) { + val amount = item.amount - 1 + if (amount < 1 && !main) { + container.remove(item) + } else { + item.amount = amount + } + if (!main) { + container.shift() + } + } + } + } + update() + } + + /** + * Checks if the player can sell an item to the shop. + * + * @param player the player. + * @param item the item. + * @param def the def. + * @return `True` if so. + */ + open fun canSell(player: Player, item: Item, def: ItemDefinition): Boolean { + if (isPointShop || item.definition.hasDestroyAction() || !def.isTradeable || !itemAllowed(item.id)) { + player.packetDispatch.sendMessage("You can't sell this item to this shop.") + return false + } + if (item.id == currency) { + player.packetDispatch.sendMessage("You can't sell " + item.name.toLowerCase() + " to a shop.") + return false + } + return true + } + + /** + * Gets the amount to buy/sell. + * + * @param player the player. + * @param add the added item. + * @return the amount. + */ + fun getAmount(player: Player?, add: Item): Int { + return add.amount + } + + /** + * Checks if the player can buy the item. + * + * @param player the player. + * @param currency the currency. + * @return `True` if so. + */ + fun handleBuy(player: Player, currency: Item?): Boolean { + return isPointShop || player.inventory.remove(currency) + } + + /** + * Checks if the player can buy from the shop. + * + * @param player the player. + * @param item the item. + * @param price the price. + * @param currency the currency. + * @return `True` if they can buy. + */ + fun canBuy(player: Player, item: Item, price: Int, currency: Item): Boolean { + if (!isPointShop && !player.inventory.containsItem(currency)) { + player.packetDispatch.sendMessage( + "You don't have enough " + ItemDefinition.forId(currency.id).name.toLowerCase() + "." + ) + return false + } + if (isPointShop && getPoints(player) < price) { + player.sendMessage("You don't have enough " + pointsName + "s.") + return false + } + return true + } + + /** + * Gets the points. + * + * @param player the player. + * @return the points. + */ + fun getPoints(player: Player?): Int { + return 0 + } + + /** + * Decrements the points. + * + * @param player the player. + * @param decrement the decrementation. + */ + fun decrementPoints(player: Player?, decrement: Int) {} + + /** + * Gets the points name. + * + * @return the name. + */ + val pointsName: String + get() = "" + + /** + * Gets the value gained for selling this item to a certain shop. + * + * @param item The item to sell. + * @param player the player. + * @return The value. + */ + fun getSellingValue(item: Item, player: Player): Int { + var item = item + if (!item.definition.isUnnoted) { + player.setAttribute("shop:originalId", item.id) + item = Item(item.noteChange, item.amount) + } + var amount = getContainer(1).getAmount(item) + if (amount < 1) { + amount = getContainer(0).getAmount(item) + } + return getSellingValue(player, amount, item) + } + + /** + * Gets the selling value formula based. + * + * @param amount the amount. + * @param item the item. + * @return the selling value. + */ + private fun getSellingValue(player: Player, amount: Int, item: Item): Int { + val id = player.getAttribute("shop:originalId", item.id) + if (item.amount > amountInInventory(player, id)) { + item.amount = amountInInventory(player, id) + player.removeAttribute("shop:originalId") + } + val diff = if (item.definition.isStackable) 0.005 else 0.05 + var maxMod = 1.0 - amount * diff + if (maxMod < 0.25) { + maxMod = 0.25 + } + var minMod = maxMod - (item.amount - 1) * diff + if (minMod < 0.25) { + minMod = 0.25 + } + val mod = (maxMod + minMod) / 2 + logInfo("" + item.definition.getAlchemyValue(isHighAlch) + " " + mod + " " + item.amount) + val baseValue = item.definition.getAlchemyValue(isHighAlch) + var value = (baseValue * mod * item.amount).toInt() + if (currency == TOKKUL_6529 && item.id == CHAOS_RUNE_562) value = 13 * item.amount + if (currency == TOKKUL_6529 && item.id == DEATH_RUNE_560) value = 27 * item.amount + if (item.id == 12183) { + value = 25 * item.amount + } + return value + } + + /** + * Gets the buying price. + * + * @param item the item. + * @return the price. + */ + open fun getBuyPrice(item: Item, player: Player): Int { + var item = item + item = Item(item.id, 1) + var price = item.definition.maxValue + val sellVal = getSellingValue(item, player) + if (price < sellVal) { + price = getSellingValue(player, 0, item) + sellVal - (sellVal - item.definition.maxValue) + } + if (price < 0) { + price = 1 + } + if (currency == TOKKUL) { + val tokkul = item.definition.getConfiguration("tokkul_price", -1) + if (tokkul > 0) { + price = tokkul + } + if (player.achievementDiaryManager.karamjaGlove != -1) { + price = kotlin.math.floor(price * 0.87).toInt() + } + } + if (currency == ARCHERY_TICKET) { + val tickets = item.definition.getConfiguration(ItemConfigParser.ARCHERY_TICKET_PRICE, -1) + if (tickets > 0) { + price = tickets + } + } + return if (sellAllFor > 0) sellAllFor else price + } + + /** + * Checks if the item is allowed to be sold to the shop. + * + * @param itemId the item id. + * @return `True` if so. + */ + fun itemAllowed(itemId: Int): Boolean { + if (isGeneral) { + return true + } + var noteId = ItemDefinition.forId(itemId).noteId + if (!ItemDefinition.forId(itemId).isUnnoted) { + noteId = ItemDefinition.forId(noteId).noteId + } + for (id in items) { + if (itemId == id.id || noteId > -1 && noteId == ItemDefinition.forId(id.id).noteId) { + return true + } + } + return false + } + + /** + * Gets the container the item should go to. + * + * @param item the item. + * @return the container. + */ + fun getContainer(item: Item): Container { + val itemId = item.id + var noteId = ItemDefinition.forId(itemId).noteId + if (!ItemDefinition.forId(itemId).isUnnoted) { + noteId = ItemDefinition.forId(noteId).noteId + } + for (i in items) { + if (i.id == item.id || noteId > -1 && noteId == ItemDefinition.forId(i.id).noteId) { + return getContainer(0) + } + } + return getContainer(1) + } + + /** + * Creates a copy of this shop. + * + * @return the shop. + */ + fun copy(): Shop { + return Shop(title, items, isGeneral, currency, isHighAlch) + } + + /** + * Gets the container on the slot. + * + * @param tabIndex the tab index. + * @return the container. + */ + fun getContainer(tabIndex: Int): Container { + if (tabIndex > containers.size) { + throw IndexOutOfBoundsException("Error! Shop tab index out of bounds.") + } + return containers[tabIndex] + } + + override fun toString(): String { + return "Shop [containers=" + Arrays.toString(containers) + ", viewers=" + viewers + ", title=" + title + ", items=" + Arrays.toString( + items + ) + ", general=" + isGeneral + ", currency=" + currency + ", highAlch=" + isHighAlch + "]" + } + + fun setItems(items: ArrayList) { + this.items = items.toTypedArray() + } + + companion object { + /** + * Represents the general store items. + */ + val GENERAL_STORE_ITEMS = arrayOf( + Item(EMPTY_POT_1931, 5), + Item(JUG_1935, 5), + Item(SHEARS_1735, 2), + Item(BUCKET_1925, 3), + Item(BOWL_1923, 2), + Item(CAKE_TIN_1887, 2), + Item(TINDERBOX_590, 2), + Item(CHISEL_1755, 2), + Item(HAMMER_2347, 5), + Item(NEWCOMER_MAP_550, 5), + Item(SECURITY_BOOK_9003, 5) + ) + + /** + * Represents the coins item. + */ + private const val COINS = 995 + + /** + * Represents the tokkul item id. + */ + private const val TOKKUL = 6529 + + /** + * Represents the archery ticket item id + */ + private const val ARCHERY_TICKET = 1464 + } + /** + * Constructs a new `Shop` `Object`. + * + * @param title the title. + * @param items the items. + * @param isGeneral the general. + * @param currency the currency. + * @param isHighAlch if high alch. + */ + /** + * Constructs a new `Shop` `Object`. + * + * @param title the title. + * @param items the items. + * @param general the general. + */ + init { + this.getContainer(0).add(*items) + isRestock = true + lastRestock = ticks + 100 + } +} \ No newline at end of file diff --git a/Server/src/main/java/core/game/content/zone/ChaosTunnelZone.java b/Server/src/main/java/core/game/content/zone/ChaosTunnelZone.java index a3d4a3cb5..409ced2bb 100644 --- a/Server/src/main/java/core/game/content/zone/ChaosTunnelZone.java +++ b/Server/src/main/java/core/game/content/zone/ChaosTunnelZone.java @@ -13,6 +13,8 @@ import core.game.node.entity.Entity; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.object.Scenery; +import org.json.simple.JSONObject; +import rs09.ServerStore; import rs09.game.world.GameWorld; import core.game.world.map.Location; import core.game.world.map.zone.MapZone; @@ -261,13 +263,13 @@ public final class ChaosTunnelZone extends MapZone implements Plugin { * @param player The player. */ private void commenceBorkBattle(Player player) { - if ((System.currentTimeMillis() - player.getSavedData().getActivityData().getLastBorkBattle()) < 24 * 60 * 60_000 && GameWorld.getSettings().isHosted()) { + if (ServerStore.getBoolean(getStoreFile(), player.getUsername().toLowerCase()) && GameWorld.getSettings().isHosted()) { player.getPacketDispatch().sendMessage("The portal's magic is too weak to teleport you right now."); return; } player.lock(10); player.graphics(Graphics.create(110)); - player.getSavedData().getActivityData().setLastBorkBattle(System.currentTimeMillis()); + getStoreFile().put(player.getUsername().toLowerCase(), true); ActivityManager.start(player, "Bork cutscene", false); } @@ -352,4 +354,12 @@ public final class ChaosTunnelZone extends MapZone implements Plugin { PORTALS.put(location, loc); } + /** + * Returns the Server Store file for Bork being killed for the day + * @return The JSONObject containing the boolean of whether Bork has been killed + */ + private JSONObject getStoreFile() { + return ServerStore.getArchive("daily-bork-killed"); + } + } diff --git a/Server/src/main/java/core/game/interaction/npc/RoavarDialogue.java b/Server/src/main/java/core/game/interaction/npc/RoavarDialogue.java index 0af8a4669..5051340ba 100644 --- a/Server/src/main/java/core/game/interaction/npc/RoavarDialogue.java +++ b/Server/src/main/java/core/game/interaction/npc/RoavarDialogue.java @@ -44,7 +44,7 @@ public class RoavarDialogue extends DialoguePlugin { stage = 1; break; case 1: - interpreter.sendOptions("Select an Option", "Can I buy a beer?", "Can I hear some gossipp?", "Do you have a spare silver sickle?", "Nothing thanks."); + interpreter.sendOptions("Select an Option", "Can I buy a beer?", "Can I hear some gossipp?", "Nothing thanks."); stage = 2; break; case 2: @@ -58,10 +58,6 @@ public class RoavarDialogue extends DialoguePlugin { stage = 20; break; case 3: - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Would you happen to have a spare silver sickle?"); - stage = 30; - break; - case 4: interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Nothing thanks."); stage = 40; break; diff --git a/Server/src/main/java/core/game/node/entity/combat/spell/CurseSpells.java b/Server/src/main/java/core/game/node/entity/combat/spell/CurseSpells.java index 6167d4e46..4356c7853 100644 --- a/Server/src/main/java/core/game/node/entity/combat/spell/CurseSpells.java +++ b/Server/src/main/java/core/game/node/entity/combat/spell/CurseSpells.java @@ -1,5 +1,6 @@ package core.game.node.entity.combat.spell; +import api.ContentAPI; import core.game.node.entity.skill.Skills; import core.game.node.entity.skill.magic.Runes; import core.game.node.entity.Entity; @@ -181,6 +182,11 @@ public final class CurseSpells extends CombatSpell { } } + @Override + public void addExperience(Entity entity, int hit) { + entity.getSkills().addExperience(Skills.MAGIC, getExperience()); + } + @Override public Plugin newInstance(SpellType type) throws Throwable { SpellBook.MODERN.register(2, new CurseSpells(SpellType.CONFUSE, 3, 13.0, 99, CONFUSE_START, CONFUSE_PROJECTILE, CONFUSE_END, Runes.BODY_RUNE.getItem(1), Runes.EARTH_RUNE.getItem(2), Runes.WATER_RUNE.getItem(3))); diff --git a/Server/src/main/java/core/game/node/entity/npc/NPC.java b/Server/src/main/java/core/game/node/entity/npc/NPC.java index da1e44f90..b7cd9fc23 100644 --- a/Server/src/main/java/core/game/node/entity/npc/NPC.java +++ b/Server/src/main/java/core/game/node/entity/npc/NPC.java @@ -513,7 +513,7 @@ public class NPC extends Entity { if (getZoneMonitor().handleDeath(killer)) { return; } - if (task != null && killer instanceof Player && ((Player) killer).getSlayer().getTask() == task) { + if (task != null && killer instanceof Player && ((Player) killer).getSlayer().getTask() == task && ((Player) killer).getSlayer().hasTask()) { ((Player) killer).getSlayer().finalizeDeath(killer.asPlayer(), this); } if (killer instanceof Player && killer.getAttribute("jobs:id",null) != null) { diff --git a/Server/src/main/java/core/game/node/entity/skill/Skills.java b/Server/src/main/java/core/game/node/entity/skill/Skills.java index cbfe08d8f..2b5362b79 100644 --- a/Server/src/main/java/core/game/node/entity/skill/Skills.java +++ b/Server/src/main/java/core/game/node/entity/skill/Skills.java @@ -22,6 +22,9 @@ import org.rs09.consts.Items; import java.nio.ByteBuffer; +import static java.lang.Math.floor; +import static java.lang.Math.max; + /** * Represents an entity's skills. * @author Emperor @@ -453,8 +456,8 @@ public final class Skills { int points = 0; int output = 0; for (byte lvl = 1; lvl < 100; lvl++) { - points += Math.floor(lvl + 300.0 * Math.pow(2.0, lvl / 7.0)); - output = (int) Math.floor(points / 4); + points += floor(lvl + 300.0 * Math.pow(2.0, lvl / 7.0)); + output = (int) floor(points / 4); if ((output - 1) >= exp) { return lvl; } @@ -467,8 +470,8 @@ public final class Skills { int points = 0; int output = 0; for (byte lvl = 1; lvl < 100; lvl++) { - points += Math.floor(lvl + 300.0 * Math.pow(2.0, lvl / 7.0)); - output = (int) Math.floor(points / 4); + points += floor(lvl + 300.0 * Math.pow(2.0, lvl / 7.0)); + output = (int) floor(points / 4); if ((output - 1) >= exp) { return lvl; } @@ -485,11 +488,11 @@ public final class Skills { int points = 0; int output = 0; for (int lvl = 1; lvl <= level; lvl++) { - points += Math.floor(lvl + 300.0 * Math.pow(2.0, lvl / 7.0)); + points += floor(lvl + 300.0 * Math.pow(2.0, lvl / 7.0)); if (lvl >= level) { return output; } - output = (int) Math.floor(points / 4); + output = (int) floor(points / 4); } return 0; } @@ -523,19 +526,13 @@ public final class Skills { if (entity instanceof NPC) { return ((NPC) entity).getDefinition().getCombatLevel(); } - int combatLevel = 0; - int melee = staticLevels[ATTACK] + staticLevels[STRENGTH]; - int range = (int) (1.5 * staticLevels[RANGE]); - int mage = (int) (1.5 * staticLevels[MAGIC]); - if (melee > range && melee > mage) { - combatLevel = melee; - } else if (range > melee && range > mage) { - combatLevel = range; - } else { - combatLevel = mage; - } - combatLevel = staticLevels[DEFENCE] + staticLevels[HITPOINTS] + (staticLevels[PRAYER] / 2) + (int) (1.3 * combatLevel); - return combatLevel / 4; + + double base = 0.25 * (staticLevels[DEFENCE] + staticLevels[HITPOINTS] + floor(0.5 * staticLevels[PRAYER])); + double meleeBase = 0.325 * (staticLevels[ATTACK] + staticLevels[STRENGTH]); + double rangeBase = 0.325 * (floor(staticLevels[RANGE] / 2.0) * 1.5); + double magicBase = 0.325 * (floor(staticLevels[MAGIC] / 2.0) * 1.5); + + return (int) (base + max(meleeBase, max(rangeBase, magicBase))); } /** diff --git a/Server/src/main/java/core/game/node/entity/skill/construction/PortalOptionPlugin.java b/Server/src/main/java/core/game/node/entity/skill/construction/PortalOptionPlugin.java index a1578fc0c..433236eb2 100644 --- a/Server/src/main/java/core/game/node/entity/skill/construction/PortalOptionPlugin.java +++ b/Server/src/main/java/core/game/node/entity/skill/construction/PortalOptionPlugin.java @@ -119,6 +119,11 @@ public final class PortalOptionPlugin extends OptionHandler { player.getHouseManager().enter(player, buttonId == 2, true); break; case 3: + if(player.getIronmanManager().isIronman()){ + end(); + ContentAPI.sendMessage(player, "You can't do that as an ironman."); + return true; + } ContentAPI.sendInputDialogue(player, false, "Enter friend's name:", (value) -> { Player p = Repository.getPlayerByName((String) value); if (p == null || !p.isActive()) { diff --git a/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerManager.java b/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerManager.java index 669da7a1c..b40ca2c8c 100644 --- a/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerManager.java +++ b/Server/src/main/java/core/game/node/entity/skill/slayer/SlayerManager.java @@ -105,10 +105,12 @@ public final class SlayerManager { * @param npc The NPC. You're currently */ public void finalizeDeath(Player player, NPC npc) { - player.getSkills().addExperience(Skills.SLAYER,npc.getSkills().getMaximumLifepoints()); - decrementAmount(1); - if (!hasTask()) { - clear(); + if(hasTask()) { + player.getSkills().addExperience(Skills.SLAYER, npc.getSkills().getMaximumLifepoints()); + decrementAmount(1); + } + + if(!hasTask()){ flags.setTaskStreak(flags.getTaskStreak() + 1); flags.setCompletedTasks(flags.getCompletedTasks() + 1); if ((flags.getCompletedTasks() > 4 || flags.canEarnPoints() ) && flags.getMaster() != Master.TURAEL && flags.getPoints() < 64000) { @@ -251,7 +253,7 @@ public final class SlayerManager { * @return {@code True} if so. */ public boolean hasTask() { - return getAmount() != 0; + return getAmount() > 0; } /** diff --git a/Server/src/main/java/core/net/event/MSHSWriteEvent.java b/Server/src/main/java/core/net/event/MSHSWriteEvent.java index 6f55dfd71..b7f7aebb6 100644 --- a/Server/src/main/java/core/net/event/MSHSWriteEvent.java +++ b/Server/src/main/java/core/net/event/MSHSWriteEvent.java @@ -3,6 +3,8 @@ package core.net.event; import core.cache.misc.buffer.ByteBufferUtils; import core.net.IoSession; import core.net.IoWriteEvent; +import rs09.Server; +import rs09.ServerConstants; import java.nio.ByteBuffer; @@ -12,11 +14,6 @@ import java.nio.ByteBuffer; */ public final class MSHSWriteEvent extends IoWriteEvent { - /** - * The password used to verify - */ - private static final String PASSWORD = "0x14ari0SSbh98989910"; - /** * Constructs a new {@code MSHSWriteEvent} {@code Object} * @param session The session. @@ -28,9 +25,9 @@ public final class MSHSWriteEvent extends IoWriteEvent { @Override public void write(IoSession session, Object context) { - ByteBuffer buffer = ByteBuffer.allocate(2 + PASSWORD.length()); + ByteBuffer buffer = ByteBuffer.allocate(2 + ServerConstants.MS_SECRET_KEY.length()); buffer.put((byte) 88); - ByteBufferUtils.putString(PASSWORD, buffer); + ByteBufferUtils.putString(ServerConstants.MS_SECRET_KEY, buffer); session.queue((ByteBuffer) buffer.flip()); } diff --git a/Server/src/main/java/core/net/packet/PacketRepository.java b/Server/src/main/java/core/net/packet/PacketRepository.java index 8d4433642..6cb4e3e60 100644 --- a/Server/src/main/java/core/net/packet/PacketRepository.java +++ b/Server/src/main/java/core/net/packet/PacketRepository.java @@ -77,6 +77,7 @@ public final class PacketRepository { OUTGOING_PACKETS.put(UpdateRandomFile.class, new UpdateRandomFile()); // OUTGOING_PACKETS.put(InstancedLocationUpdate.class, new InstancedLocationUpdate()); // OUTGOING_PACKETS.put(CSConfigPacket.class, new CSConfigPacket()); // + OUTGOING_PACKETS.put(Varbit.class, new Varbit()); INCOMING_PACKETS.put(22, new ClientFocusPacket()); INCOMING_PACKETS.put(93, new PingPacketHandler()); INCOMING_PACKETS.put(44, new CommandPacket()); diff --git a/Server/src/main/java/core/net/packet/context/VarbitContext.java b/Server/src/main/java/core/net/packet/context/VarbitContext.java new file mode 100644 index 000000000..5a551eed2 --- /dev/null +++ b/Server/src/main/java/core/net/packet/context/VarbitContext.java @@ -0,0 +1,22 @@ +package core.net.packet.context; + +import core.game.node.entity.player.Player; +import core.net.packet.Context; + +public class VarbitContext implements Context { + + Player player; + public int varbitId; + public int value; + + public VarbitContext(Player player, int varbitId, int value){ + this.player = player; + this.varbitId = varbitId; + this.value = value; + } + + @Override + public Player getPlayer() { + return player; + } +} diff --git a/Server/src/main/java/core/net/packet/in/InteractionPacket.java b/Server/src/main/java/core/net/packet/in/InteractionPacket.java index f61e5f1ec..9b93745f9 100644 --- a/Server/src/main/java/core/net/packet/in/InteractionPacket.java +++ b/Server/src/main/java/core/net/packet/in/InteractionPacket.java @@ -266,6 +266,7 @@ public final class InteractionPacket implements IncomingPacket { player.debug("dir=" + object.getDirection()); VarbitDefinition def = VarbitDefinition.forObjectID(SceneryDefinition.forId(objectId).getVarbitID()); player.debug("Varp ID=" + def.getConfigId() + " Offset=" + def.getBitShift() + " Size=" + def.getBitSize()); + player.debug("Varbit: " + def.getId()); if (option.getHandler() != null) { player.debug("Object handler: " + option.getHandler().getClass().getSimpleName()); } diff --git a/Server/src/main/java/core/net/packet/out/Varbit.java b/Server/src/main/java/core/net/packet/out/Varbit.java new file mode 100644 index 000000000..e8cfc6823 --- /dev/null +++ b/Server/src/main/java/core/net/packet/out/Varbit.java @@ -0,0 +1,21 @@ +package core.net.packet.out; + +import core.net.packet.IoBuffer; +import core.net.packet.OutgoingPacket; +import core.net.packet.context.VarbitContext; + +public class Varbit implements OutgoingPacket { + @Override + public void send(VarbitContext varbitContext) { + IoBuffer buffer; + if(varbitContext.value > 255){ + buffer = new IoBuffer(84); + buffer.putLEInt((128 | varbitContext.value) & 255); + } else { + buffer = new IoBuffer(37); + buffer.put((byte) 128 | varbitContext.value); + } + buffer.putLEShort(varbitContext.varbitId); + varbitContext.getPlayer().getSession().write(buffer); + } +} diff --git a/Server/src/main/kotlin/rs09/Server.kt b/Server/src/main/kotlin/rs09/Server.kt index 13285503f..684a7b039 100644 --- a/Server/src/main/kotlin/rs09/Server.kt +++ b/Server/src/main/kotlin/rs09/Server.kt @@ -16,10 +16,14 @@ import rs09.game.system.config.ServerConfigParser import rs09.game.world.GameWorld import rs09.game.world.repository.Repository import java.io.File +import java.io.FileWriter +import java.lang.management.ManagementFactory +import java.lang.management.ThreadMXBean import java.net.BindException import java.util.* import kotlin.system.exitProcess + /** * The main class, for those that are unable to read the class' name. * @author Emperor @@ -108,6 +112,13 @@ object Server { while(running){ if(System.currentTimeMillis() - lastHeartbeat > 1800 && running){ SystemLogger.logErr("Triggering reboot due to heartbeat timeout") + SystemLogger.logErr("Creating thread dump...") + val dump = threadDump(true, true) + FileWriter("latestdump.txt").use { + it.write(dump) + it.flush() + it.close() + } exitProcess(0) } delay(625) @@ -140,6 +151,15 @@ object Server { return startTime } + private fun threadDump(lockedMonitors: Boolean, lockedSynchronizers: Boolean): String? { + val threadDump = StringBuffer(System.lineSeparator()) + val threadMXBean: ThreadMXBean = ManagementFactory.getThreadMXBean() + for (threadInfo in threadMXBean.dumpAllThreads(lockedMonitors, lockedSynchronizers)) { + threadDump.append(threadInfo.toString()) + } + return threadDump.toString() + } + /** * Sets the bastartTime.ZZ * @param startTime the startTime to set. diff --git a/Server/src/main/kotlin/rs09/ServerConstants.kt b/Server/src/main/kotlin/rs09/ServerConstants.kt index 35c1d5c83..0c6109d1e 100644 --- a/Server/src/main/kotlin/rs09/ServerConstants.kt +++ b/Server/src/main/kotlin/rs09/ServerConstants.kt @@ -106,6 +106,9 @@ class ServerConstants { @JvmField var GE_AUTOSTOCK_ENABLED = false + @JvmField + var MS_SECRET_KEY = "" + //location names for the ::to command. val TELEPORT_DESTINATIONS = arrayOf( arrayOf(Location.create(2974, 4383, 2), "corp", "corporal", "corporeal"), @@ -218,6 +221,9 @@ class ServerConstants { if(data.containsKey("daily_restart")){ DAILY_RESTART = data["daily_restart"] as Boolean } + + if(data.containsKey("ms_secret_key")) MS_SECRET_KEY = data["ms_secret_key"].toString() + else MS_SECRET_KEY = "2009scape_development" } } } \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/ServerStore.kt b/Server/src/main/kotlin/rs09/ServerStore.kt index aa42288f1..926be761a 100644 --- a/Server/src/main/kotlin/rs09/ServerStore.kt +++ b/Server/src/main/kotlin/rs09/ServerStore.kt @@ -100,14 +100,17 @@ object ServerStore { } } + @JvmStatic fun JSONObject.getString(key: String): String { return this[key] as? String ?: "nothing" } + @JvmStatic fun JSONObject.getLong(key: String): Long { return this[key] as? Long ?: 0L } + @JvmStatic fun JSONObject.getBoolean(key: String): Boolean { return this[key] as? Boolean ?: false } diff --git a/Server/src/main/kotlin/rs09/game/VarpManager.kt b/Server/src/main/kotlin/rs09/game/VarpManager.kt index 982254b7d..51f295d6e 100644 --- a/Server/src/main/kotlin/rs09/game/VarpManager.kt +++ b/Server/src/main/kotlin/rs09/game/VarpManager.kt @@ -2,6 +2,8 @@ package rs09.game import core.cache.def.impl.VarbitDefinition import core.game.node.entity.player.Player +import core.net.packet.PacketRepository +import core.net.packet.context.VarbitContext import org.json.simple.JSONArray import org.json.simple.JSONObject import rs09.game.node.entity.skill.farming.FarmingPatch @@ -32,6 +34,10 @@ class VarpManager(val player: Player) { get(def.configId).setVarbit(def.bitShift,value).send(player) } + fun setVarbit(varbitIndex: Int, value: Int){ + PacketRepository.send(core.net.packet.out.Varbit::class.java, VarbitContext(player, varbitIndex, value)) + } + fun flagSave(index: Int){ get(index).save = true } diff --git a/Server/src/main/kotlin/rs09/game/content/ame/events/certer/CerterEventInterface.kt b/Server/src/main/kotlin/rs09/game/content/ame/events/certer/CerterEventInterface.kt index 1e21f8cc8..3dbadca5b 100644 --- a/Server/src/main/kotlin/rs09/game/content/ame/events/certer/CerterEventInterface.kt +++ b/Server/src/main/kotlin/rs09/game/content/ame/events/certer/CerterEventInterface.kt @@ -44,10 +44,10 @@ class CerterEventInterface : InterfaceListener() { player.packetDispatch.sendString(items[correct],CERTER_INTERFACE,optionFromIndex(correctIndex)) - val tempOptions = falseOptions + val tempOptions = falseOptions.toMutableList() val false1 = tempOptions.random() + tempOptions.remove(false1) var false2 = tempOptions.random() - while(false1 == false2) false2 = tempOptions.random() player.packetDispatch.sendString(false1,CERTER_INTERFACE,optionFromIndex(indexes[0])) player.packetDispatch.sendString(false2,CERTER_INTERFACE,optionFromIndex(indexes[1])) diff --git a/Server/src/main/kotlin/rs09/game/content/jobs/WorkForInteractionListener.kt b/Server/src/main/kotlin/rs09/game/content/jobs/WorkForInteractionListener.kt index bfacf46eb..22e638436 100644 --- a/Server/src/main/kotlin/rs09/game/content/jobs/WorkForInteractionListener.kt +++ b/Server/src/main/kotlin/rs09/game/content/jobs/WorkForInteractionListener.kt @@ -75,10 +75,7 @@ class WorkForInteractionListener : InteractionListener() { val type = typeMap[node.id] ?: return@on false jobId = if(type == 0) { - var job = gatheringMap[node.id]?.random() - while(!checkRequirement(player,job)){ - job = gatheringMap[node.id]?.random() - } + var job = gatheringMap[node.id]?.filter { checkRequirement(player, it) }?.random() amount = job?.getAmount() ?: 0 job?.ordinal ?: 0 } else { @@ -111,8 +108,7 @@ class WorkForInteractionListener : InteractionListener() { fun checkRequirement(player: Player, jobs: GatheringJobs?): Boolean{ jobs ?: return true - val requirement: Pair = Pair(jobs.lvlReq,jobs.skill) - if(player.skills.getLevel(requirement.second) < requirement.first){ + if(player.skills.getLevel(jobs.skill) < jobs.lvlReq){ return false } return true diff --git a/Server/src/main/kotlin/rs09/game/content/quest/free/dragonslayer/DSEquipListeners.kt b/Server/src/main/kotlin/rs09/game/content/quest/free/dragonslayer/DSEquipListeners.kt index 8c86f5482..89e5896fb 100644 --- a/Server/src/main/kotlin/rs09/game/content/quest/free/dragonslayer/DSEquipListeners.kt +++ b/Server/src/main/kotlin/rs09/game/content/quest/free/dragonslayer/DSEquipListeners.kt @@ -18,9 +18,6 @@ class DSEquipListeners : InteractionListener() { Items.SARADOMIN_PLATEBODY_2661, Items.GUTHIX_PLATEBODY_2669, Items.GREEN_DHIDE_BODY_1135, - Items.BLUE_DHIDE_BODY_2499, - Items.RED_DHIDE_BODY_2501, - Items.BLACK_DHIDE_BODY_2503, Items.DHIDE_BODYG_7370, Items.DHIDE_BODY_G_7374, Items.DHIDE_BODY_T_7372, diff --git a/Server/src/main/kotlin/rs09/game/content/zone/phasmatys/bonegrinder/BoneGrinderListener.kt b/Server/src/main/kotlin/rs09/game/content/zone/phasmatys/bonegrinder/BoneGrinderListener.kt index d4cdbe233..da53afcb1 100644 --- a/Server/src/main/kotlin/rs09/game/content/zone/phasmatys/bonegrinder/BoneGrinderListener.kt +++ b/Server/src/main/kotlin/rs09/game/content/zone/phasmatys/bonegrinder/BoneGrinderListener.kt @@ -216,14 +216,12 @@ class BoneGrinderListener : InteractionListener() { val bone = Bones.values()[player.getAttribute(LOADED_BONE_KEY,-1)] + player.lock() Pulser.submit(object : Pulse(){ var stage = 0 override fun pulse(): Boolean { when(stage++){ - 0 -> { - player.lock() - player.animator.animate(SCOOP_ANIM) - } + 0 -> player.animator.animate(SCOOP_ANIM) SCOOP_ANIM.duration -> { player.unlock() if(player.inventory.remove(Item(Items.EMPTY_POT_1931))){ diff --git a/Server/src/main/kotlin/rs09/game/interaction/object/EnchantedValleyListeners.kt b/Server/src/main/kotlin/rs09/game/interaction/object/EnchantedValleyListeners.kt index fb5986b4d..41beb3236 100644 --- a/Server/src/main/kotlin/rs09/game/interaction/object/EnchantedValleyListeners.kt +++ b/Server/src/main/kotlin/rs09/game/interaction/object/EnchantedValleyListeners.kt @@ -41,7 +41,7 @@ class EnchantedValleyListeners : InteractionListener() { fun getSpirit(player: Player): NPC { val level = player.properties.currentCombatLevel var index = Math.ceil(level / 20.0).toInt() - if(index > TREE_SPIRIT_IDS.size) index = TREE_SPIRIT_IDS.size + if(index >= TREE_SPIRIT_IDS.size) index = TREE_SPIRIT_IDS.size - 1 return NPC(TREE_SPIRIT_IDS[index]) } } \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/game/node/entity/skill/gather/fishing/barbfishing/SpotManager.kt b/Server/src/main/kotlin/rs09/game/node/entity/skill/gather/fishing/barbfishing/SpotManager.kt index b81234d45..695c02450 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/skill/gather/fishing/barbfishing/SpotManager.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/skill/gather/fishing/barbfishing/SpotManager.kt @@ -53,8 +53,9 @@ fun getNewTTL(): Int{ } fun getNewLoc(): Location { - var loc = locations.random() - while(usedLocations.contains(loc)) loc = locations.random() + val possibleLoc = locations.toTypedArray().toMutableList() + possibleLoc.removeAll(usedLocations) + val loc = possibleLoc.random() usedLocations.add(loc) return loc } diff --git a/Server/src/main/kotlin/rs09/game/system/command/oldsys/VisualCommand.kt b/Server/src/main/kotlin/rs09/game/system/command/oldsys/VisualCommand.kt index be2a5a0bb..7ee4bad1f 100644 --- a/Server/src/main/kotlin/rs09/game/system/command/oldsys/VisualCommand.kt +++ b/Server/src/main/kotlin/rs09/game/system/command/oldsys/VisualCommand.kt @@ -18,6 +18,9 @@ import core.game.world.map.Location import core.game.world.map.RegionManager import core.game.world.update.flag.context.Animation import core.game.world.update.flag.context.Graphics +import core.net.packet.PacketRepository +import core.net.packet.context.VarbitContext +import core.net.packet.out.Varbit import core.plugin.Initializable import core.plugin.Plugin import rs09.game.system.command.CommandPlugin @@ -221,14 +224,14 @@ class VisualCommand : CommandPlugin() { val cfg_index = (args.getOrNull(2)?.toString()?.toInt() ?: -1) if(cfg_index == -1){ ContentAPI.submitWorldPulse(object : Pulse(3, player){ - var pos = 0 + var pos = 32 var shift = 0 override fun pulse(): Boolean { for(i in 0..1999){ player?.configManager?.forceSet(i, pos shl shift, false) } - player?.sendMessage("$pos << $shift") - if(pos++ >= 32){ + player?.sendMessage("$pos shl $shift") + if(pos++ >= 63){ shift += 4 pos = 0 } @@ -246,6 +249,27 @@ class VisualCommand : CommandPlugin() { }) } } + "setbit" -> { + if (args!!.size < 2) { + player!!.debug("syntax error: bit value") + return true + } + var bit = toInteger(args[0]!!) + var value = toInteger(args[1]!!) + var val2 = toInteger(args[2]!!) + player!!.debug("$value $val2") + PacketRepository.send(Varbit::class.java, VarbitContext(player, value, val2)) + return true + } + "setbits" -> { + args ?: return false + val start = toInteger(args[1]!!) + val end = toInteger(args[2]!!) + val value = toInteger(args[3]!!) + for(i in start until end){ + player?.varpManager?.setVarbit(i, value) + } + } "loop_anim_on_i" -> { var anim = toInteger(args!![1]!!) ContentAPI.submitWorldPulse(object : Pulse(3){ diff --git a/Server/src/main/kotlin/rs09/worker/MajorUpdateWorker.kt b/Server/src/main/kotlin/rs09/worker/MajorUpdateWorker.kt index bedfce79a..b9042a7f9 100644 --- a/Server/src/main/kotlin/rs09/worker/MajorUpdateWorker.kt +++ b/Server/src/main/kotlin/rs09/worker/MajorUpdateWorker.kt @@ -32,9 +32,10 @@ class MajorUpdateWorker { var started = false val sequence = UpdateSequence() val sdf = SimpleDateFormat("HHmmss") - fun start() = GlobalScope.launch { + val worker = Thread { + Thread.currentThread().name = "Major Update Worker" started = true - delay(600L) + Thread.sleep(600L) while(true){ val start = System.currentTimeMillis() val rmlist = ArrayList() @@ -94,7 +95,12 @@ class MajorUpdateWorker { } val end = System.currentTimeMillis() - delay(max(600 - (end - start), 0)) + Thread.sleep(max(600 - (end - start), 0)) + } + } + fun start() { + if(!started){ + worker.start() } } } \ No newline at end of file diff --git a/Server/worldprops/default.json b/Server/worldprops/default.json index 8c0da7e38..2855b1a3e 100644 --- a/Server/worldprops/default.json +++ b/Server/worldprops/default.json @@ -43,7 +43,8 @@ "database_username": "root", "database_password": "", "database_address": "127.0.0.1", - "database_port": "3306" + "database_port": "3306", + "ms_secret_key": "2009scape_development" }, "PluginToggles": {