From f1b95fe45e40ec0fee485a080b54e3596a8fe0e8 Mon Sep 17 00:00:00 2001 From: Sukishyou <90439522+Sukishyou@users.noreply.github.com> Date: Fri, 14 Apr 2023 19:43:51 -0500 Subject: [PATCH 01/14] Fix exploit with Duey Send Items --- src/main/java/client/processor/npc/DueyProcessor.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/client/processor/npc/DueyProcessor.java b/src/main/java/client/processor/npc/DueyProcessor.java index 8db12fc8cd..3682b3877f 100644 --- a/src/main/java/client/processor/npc/DueyProcessor.java +++ b/src/main/java/client/processor/npc/DueyProcessor.java @@ -285,6 +285,12 @@ public class DueyProcessor { if (c.tryacquireClient()) { try { int fee = Trade.getFee(sendMesos); + if (sendMessage.length() > 100) { + AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with Quick Delivery on duey."); + log.warn("Chr {} tried to use duey with too long of a text", c.getPlayer().getName()); + c.disconnect(true, false); + return; + } if (!quick) { fee += 5000; } else if (!c.getPlayer().haveItem(ItemId.QUICK_DELIVERY_TICKET)) { From 301f65ce16e5dc603c71bcc5508e0e01d450d1a5 Mon Sep 17 00:00:00 2001 From: Sukishyou <90439522+Sukishyou@users.noreply.github.com> Date: Sat, 15 Apr 2023 14:36:00 -0500 Subject: [PATCH 02/14] Add null check to duey packet edit check --- src/main/java/client/processor/npc/DueyProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/client/processor/npc/DueyProcessor.java b/src/main/java/client/processor/npc/DueyProcessor.java index 3682b3877f..1633e99b71 100644 --- a/src/main/java/client/processor/npc/DueyProcessor.java +++ b/src/main/java/client/processor/npc/DueyProcessor.java @@ -285,7 +285,7 @@ public class DueyProcessor { if (c.tryacquireClient()) { try { int fee = Trade.getFee(sendMesos); - if (sendMessage.length() > 100) { + if (sendMessage != null && sendMessage.length() > 100) { AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with Quick Delivery on duey."); log.warn("Chr {} tried to use duey with too long of a text", c.getPlayer().getName()); c.disconnect(true, false); From cbc0b2707e8e791197a05f26530a39ad447108b7 Mon Sep 17 00:00:00 2001 From: Shahar6 <79195545+Shahar6@users.noreply.github.com> Date: Fri, 21 Apr 2023 20:27:59 +0300 Subject: [PATCH 03/14] Fix dupe glitch with wedding PoC for the glitch: https://www.youtube.com/watch?v=EoVGQtMkJOA&ab_channel=ThirtyOneFifty --- src/main/java/net/server/channel/handlers/WeddingHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/server/channel/handlers/WeddingHandler.java b/src/main/java/net/server/channel/handlers/WeddingHandler.java index 1a31949e09..592d86cce4 100644 --- a/src/main/java/net/server/channel/handlers/WeddingHandler.java +++ b/src/main/java/net/server/channel/handlers/WeddingHandler.java @@ -69,7 +69,7 @@ public final class WeddingHandler extends AbstractPacketHandler { if (!item.isUntradeable()) { if (itemid == item.getItemId() && quantity <= item.getQuantity()) { newItem = item.copy(); - + newItem.setQuantity(quantity); marriage.addGiftItem(groomWishlist, newItem); InventoryManipulator.removeFromSlot(c, type, slot, quantity, false, false); @@ -161,4 +161,4 @@ public final class WeddingHandler extends AbstractPacketHandler { } } } -} \ No newline at end of file +} From 61f451694f3173d2a6a2a32fae01cf67e7471c24 Mon Sep 17 00:00:00 2001 From: srcyscrt <131414895+srcyscrt@users.noreply.github.com> Date: Sat, 22 Apr 2023 18:43:23 +0800 Subject: [PATCH 04/14] Use Eclipse Temurin images in the Dockerfile --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index d65c5576e8..261ce9e499 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ # # Cosmic JAR creation stage # -FROM maven:3.8.4-openjdk-17 AS jar +FROM maven:3.9.1-eclipse-temurin-17 AS jar # Build in a separated location which won't have permissions issues. WORKDIR /opt/cosmic @@ -21,7 +21,7 @@ RUN mvn -f ./pom.xml clean package -Dmaven.test.skip -T 1C # # Server creation stage # -FROM openjdk:17.0.2 +FROM eclipse-temurin:17.0.6_10-jre # Host the server in a location that won't have permissions issues. WORKDIR /opt/server From 216fa9341b9e9d995ed01af317992390dbdd7acb Mon Sep 17 00:00:00 2001 From: Matthew Hinds Date: Fri, 12 May 2023 14:47:18 +1200 Subject: [PATCH 05/14] Removed level up messages as it is non GMS like and a bit cringey --- src/main/java/client/Character.java | 89 ----------------------------- 1 file changed, 89 deletions(-) diff --git a/src/main/java/client/Character.java b/src/main/java/client/Character.java index 1ba4b60603..289abd8396 100644 --- a/src/main/java/client/Character.java +++ b/src/main/java/client/Character.java @@ -6482,7 +6482,6 @@ public class Character extends AbstractCharacterObject { ThreadManager.getInstance().newTask(r); } - levelUpMessages(); guildUpdate(); FamilyEntry familyEntry = getFamilyEntry(); @@ -6521,94 +6520,6 @@ public class Character extends AbstractCharacterObject { return false; } } - - private void levelUpMessages() { - if (level % 5 != 0) { //Performance FTW? - return; - } - if (level == 5) { - yellowMessage("Aww, you're level 5, how cute!"); - } else if (level == 10) { - yellowMessage("Henesys Party Quest is now open to you! Head over to Henesys, find some friends, and try it out!"); - } else if (level == 15) { - yellowMessage("Half-way to your 2nd job advancement, nice work!"); - } else if (level == 20) { - yellowMessage("You can almost Kerning Party Quest!"); - } else if (level == 25) { - yellowMessage("You seem to be improving, but you are still not ready to move on to the next step."); - } else if (level == 30) { - yellowMessage("You have finally reached level 30! Try job advancing, after that try the Mushroom Castle!"); - } else if (level == 35) { - yellowMessage("Hey did you hear about this mall that opened in Kerning? Try visiting the Kerning Mall."); - } else if (level == 40) { - yellowMessage("Do @rates to see what all your rates are!"); - } else if (level == 45) { - yellowMessage("I heard that a rock and roll artist died during the grand opening of the Kerning Mall. People are naming him the Spirit of Rock."); - } else if (level == 50) { - yellowMessage("You seem to be growing very fast, would you like to test your new found strength with the mighty Zakum?"); - } else if (level == 55) { - yellowMessage("You can now try out the Ludibrium Maze Party Quest!"); - } else if (level == 60) { - yellowMessage("Feels good to be near the end of 2nd job, doesn't it?"); - } else if (level == 65) { - yellowMessage("You're only 5 more levels away from 3rd job, not bad!"); - } else if (level == 70) { - yellowMessage("I see many people wearing a teddy bear helmet. I should ask someone where they got it from."); - } else if (level == 75) { - yellowMessage("You have reached level 3 quarters!"); - } else if (level == 80) { - yellowMessage("You think you are powerful enough? Try facing horntail!"); - } else if (level == 85) { - yellowMessage("Did you know? The majority of people who hit level 85 in Cosmic don't live to be 85 years old?"); - } else if (level == 90) { - yellowMessage("Hey do you like the amusement park? I heard Spooky World is the best theme park around. I heard they sell cute teddy-bears."); - } else if (level == 95) { - yellowMessage("100% of people who hit level 95 in Cosmic don't live to be 95 years old."); - } else if (level == 100) { - yellowMessage("Mid-journey so far... You just reached level 100! Now THAT's such a feat, however to manage the 200 you will need even more passion and determination than ever! Good hunting!"); - } else if (level == 105) { - yellowMessage("Have you ever been to leafre? I heard they have dragons!"); - } else if (level == 110) { - yellowMessage("I see many people wearing a teddy bear helmet. I should ask someone where they got it from."); - } else if (level == 115) { - yellowMessage("I bet all you can think of is level 120, huh? Level 115 gets no love."); - } else if (level == 120) { - yellowMessage("Are you ready to learn from the masters? Head over to your job instructor!"); - } else if (level == 125) { - yellowMessage("The struggle for mastery books has begun, huh?"); - } else if (level == 130) { - yellowMessage("You should try Temple of Time. It should be pretty decent EXP."); - } else if (level == 135) { - yellowMessage("I hope you're still not struggling for mastery books!"); - } else if (level == 140) { - yellowMessage("You're well into 4th job at this point, great work!"); - } else if (level == 145) { - yellowMessage("Level 145 is serious business!"); - } else if (level == 150) { - yellowMessage("You have becomed quite strong, but the journey is not yet over."); - } else if (level == 155) { - yellowMessage("At level 155, Zakum should be a joke to you. Nice job!"); - } else if (level == 160) { - yellowMessage("Level 160 is pretty impressive. Try taking a picture and putting it on Instagram."); - } else if (level == 165) { - yellowMessage("At this level, you should start looking into doing some boss runs."); - } else if (level == 170) { - yellowMessage("Level 170, huh? You have the heart of a champion."); - } else if (level == 175) { - yellowMessage("You came a long way from level 1. Amazing job so far."); - } else if (level == 180) { - yellowMessage("Have you ever tried taking a boss on by yourself? It is quite difficult."); - } else if (level == 185) { - yellowMessage("Legend has it that you're a legend."); - } else if (level == 190) { - yellowMessage("You only have 10 more levels to go until you hit 200!"); - } else if (level == 195) { - yellowMessage("Nothing is stopping you at this point, level 195!"); - } else if (level == 200) { - yellowMessage("Very nicely done! You have reached the so-long dreamed LEVEL 200!!! You are truly a hero among men, cheers upon you!"); - } - } - public void setPlayerRates() { this.expRate *= GameConstants.getPlayerBonusExpRate(this.level / 20); this.mesoRate *= GameConstants.getPlayerBonusMesoRate(this.level / 20); From 4546fd44ffb52724449a646342fb341ce59f3ff4 Mon Sep 17 00:00:00 2001 From: Matthew Hinds Date: Fri, 12 May 2023 18:02:08 +1200 Subject: [PATCH 06/14] To prevent abuse, GMs should be permission restricted (via GM level) to trade with other non GM players, use their storage (prevent transferring to their other characters), send via Duey and to drop items. GM level is configurable. --- config.yaml | 6 ++++++ .../manipulator/InventoryManipulator.java | 6 ++++++ .../java/client/processor/npc/DueyProcessor.java | 7 +++++++ .../client/processor/npc/StorageProcessor.java | 7 +++++++ src/main/java/config/ServerConfig.java | 6 ++++++ src/main/java/server/Trade.java | 14 ++++++++++++++ 6 files changed, 46 insertions(+) diff --git a/config.yaml b/config.yaml index 835fe88b93..3fae109d3c 100644 --- a/config.yaml +++ b/config.yaml @@ -461,6 +461,12 @@ server: #Event End Timestamp EVENT_END_TIMESTAMP: 1428897600000 + # GM Security Configuration + MINIMUM_GM_LEVEL_TO_TRADE: 4 + MINIMUM_GM_LEVEL_TO_USE_STORAGE: 4 + MINIMUM_GM_LEVEL_TO_USE_DUEY: 4 + MINIMUM_GM_LEVEL_TO_DROP: 4 + #Any NPC ids that should search for a js override script (useful if they already have wz entries since otherwise they're ignored). NPCS_SCRIPTABLE: #9200000: Talk to Cody # Cody diff --git a/src/main/java/client/inventory/manipulator/InventoryManipulator.java b/src/main/java/client/inventory/manipulator/InventoryManipulator.java index 98f6fc3f19..331a7061b0 100644 --- a/src/main/java/client/inventory/manipulator/InventoryManipulator.java +++ b/src/main/java/client/inventory/manipulator/InventoryManipulator.java @@ -706,6 +706,12 @@ public class InventoryManipulator { Inventory inv = chr.getInventory(type); Item source = inv.getItem(src); + if (chr.isGM() && chr.gmLevel() < YamlConfig.config.server.MINIMUM_GM_LEVEL_TO_DROP) { + chr.message("You cannot drop items at your GM level."); + log.info("GM %s tried to drop item id %d", chr.getName(), source.getItemId()); + return; + } + if (chr.getTrade() != null || chr.getMiniGame() != null || source == null) { //Only check needed would prob be merchants (to see if the player is in one) return; } diff --git a/src/main/java/client/processor/npc/DueyProcessor.java b/src/main/java/client/processor/npc/DueyProcessor.java index 1633e99b71..345c135c7a 100644 --- a/src/main/java/client/processor/npc/DueyProcessor.java +++ b/src/main/java/client/processor/npc/DueyProcessor.java @@ -284,6 +284,13 @@ public class DueyProcessor { public static void dueySendItem(Client c, byte invTypeId, short itemPos, short amount, int sendMesos, String sendMessage, String recipient, boolean quick) { if (c.tryacquireClient()) { try { + if (c.getPlayer().isGM() && c.getPlayer().gmLevel() < YamlConfig.config.server.MINIMUM_GM_LEVEL_TO_USE_DUEY) { + c.getPlayer().message("You cannot use Duey to send items at your GM level."); + log.info(String.format("GM %s tried to send a package to %s", c.getPlayer().getName(), recipient)); + c.sendPacket(PacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_INCORRECT_REQUEST.getCode())); + return; + } + int fee = Trade.getFee(sendMesos); if (sendMessage != null && sendMessage.length() > 100) { AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with Quick Delivery on duey."); diff --git a/src/main/java/client/processor/npc/StorageProcessor.java b/src/main/java/client/processor/npc/StorageProcessor.java index bd7f4333a0..6bfc55f001 100644 --- a/src/main/java/client/processor/npc/StorageProcessor.java +++ b/src/main/java/client/processor/npc/StorageProcessor.java @@ -52,6 +52,13 @@ public class StorageProcessor { Storage storage = chr.getStorage(); byte mode = p.readByte(); + if (chr.isGM() && chr.gmLevel() < YamlConfig.config.server.MINIMUM_GM_LEVEL_TO_USE_STORAGE) { + chr.dropMessage(1, "You cannot use the storage as a GM of this level."); + log.info(String.format("GM %s blocked from placing items in storage", chr.getName())); + c.sendPacket(PacketCreator.enableActions()); + return; + } + if (chr.getLevel() < 15) { chr.dropMessage(1, "You may only use the storage once you have reached level 15."); c.sendPacket(PacketCreator.enableActions()); diff --git a/src/main/java/config/ServerConfig.java b/src/main/java/config/ServerConfig.java index 064599729a..499ac738ef 100644 --- a/src/main/java/config/ServerConfig.java +++ b/src/main/java/config/ServerConfig.java @@ -309,6 +309,12 @@ public class ServerConfig { //Event End Timestamp public long EVENT_END_TIMESTAMP; + //GM Security Configuration + public int MINIMUM_GM_LEVEL_TO_TRADE; + public int MINIMUM_GM_LEVEL_TO_USE_STORAGE; + public int MINIMUM_GM_LEVEL_TO_USE_DUEY; + public int MINIMUM_GM_LEVEL_TO_DROP; + //Custom NPC overrides. List of NPC IDs. public Map NPCS_SCRIPTABLE = new HashMap<>(); } diff --git a/src/main/java/server/Trade.java b/src/main/java/server/Trade.java index 2f95cb9219..9233d57426 100644 --- a/src/main/java/server/Trade.java +++ b/src/main/java/server/Trade.java @@ -448,6 +448,20 @@ public class Trade { } public static void inviteTrade(Character c1, Character c2) { + + if ((c1.isGM() && !c2.isGM()) && c1.gmLevel() < YamlConfig.config.server.MINIMUM_GM_LEVEL_TO_TRADE) { + c1.message("You cannot trade with non-GM characters."); + log.info(String.format("GM %s blocked from trading with %s due to GM level.", c1.getName(), c2.getName())); + cancelTrade(c1, TradeResult.NO_RESPONSE); + return; + } + + if ((!c1.isGM() && c2.isGM()) && c2.gmLevel() < YamlConfig.config.server.MINIMUM_GM_LEVEL_TO_TRADE) { + c1.message("You cannot trade with this GM character."); + cancelTrade(c1, TradeResult.NO_RESPONSE); + return; + } + if (InviteCoordinator.hasInvite(InviteType.TRADE, c1.getId())) { if (hasTradeInviteBack(c1, c2)) { c1.message("You are already managing this player's trade invitation."); From 0b73d6112a8cfdbe762db5fed14946e72783a7a8 Mon Sep 17 00:00:00 2001 From: Favouris <131886201+Favouris@users.noreply.github.com> Date: Sun, 14 May 2023 19:16:40 +0800 Subject: [PATCH 07/14] Rename MCRevive1.js to MCrevive1.js --- scripts/portal/{MCRevive1.js => MCrevive1.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/portal/{MCRevive1.js => MCrevive1.js} (100%) diff --git a/scripts/portal/MCRevive1.js b/scripts/portal/MCrevive1.js similarity index 100% rename from scripts/portal/MCRevive1.js rename to scripts/portal/MCrevive1.js From 2d6cf07a65804ca756aaa9bd318957239e614341 Mon Sep 17 00:00:00 2001 From: Favouris <131886201+Favouris@users.noreply.github.com> Date: Sun, 14 May 2023 19:16:51 +0800 Subject: [PATCH 08/14] Rename MCRevive2.js to MCrevive2.js --- scripts/portal/{MCRevive2.js => MCrevive2.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/portal/{MCRevive2.js => MCrevive2.js} (100%) diff --git a/scripts/portal/MCRevive2.js b/scripts/portal/MCrevive2.js similarity index 100% rename from scripts/portal/MCRevive2.js rename to scripts/portal/MCrevive2.js From 1416cd432d0f6074cf5380f6331a7f1e10beb1e5 Mon Sep 17 00:00:00 2001 From: Favouris <131886201+Favouris@users.noreply.github.com> Date: Sun, 14 May 2023 19:17:03 +0800 Subject: [PATCH 09/14] Rename MCRevive3.js to MCrevive3.js --- scripts/portal/{MCRevive3.js => MCrevive3.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/portal/{MCRevive3.js => MCrevive3.js} (100%) diff --git a/scripts/portal/MCRevive3.js b/scripts/portal/MCrevive3.js similarity index 100% rename from scripts/portal/MCRevive3.js rename to scripts/portal/MCrevive3.js From 08e7a3af16343f481f77a3f7828610ca80dc5195 Mon Sep 17 00:00:00 2001 From: Favouris <131886201+Favouris@users.noreply.github.com> Date: Sun, 14 May 2023 19:17:15 +0800 Subject: [PATCH 10/14] Rename MCRevive4.js to MCrevive4.js --- scripts/portal/{MCRevive4.js => MCrevive4.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/portal/{MCRevive4.js => MCrevive4.js} (100%) diff --git a/scripts/portal/MCRevive4.js b/scripts/portal/MCrevive4.js similarity index 100% rename from scripts/portal/MCRevive4.js rename to scripts/portal/MCrevive4.js From 5cddb7f2b6cf9d28bc8296b5229675083aae9bdd Mon Sep 17 00:00:00 2001 From: Favouris <131886201+Favouris@users.noreply.github.com> Date: Sun, 14 May 2023 19:17:25 +0800 Subject: [PATCH 11/14] Rename MCRevive5.js to MCrevive5.js --- scripts/portal/{MCRevive5.js => MCrevive5.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/portal/{MCRevive5.js => MCrevive5.js} (100%) diff --git a/scripts/portal/MCRevive5.js b/scripts/portal/MCrevive5.js similarity index 100% rename from scripts/portal/MCRevive5.js rename to scripts/portal/MCrevive5.js From 92239579319b1481a10e890df686223351b33362 Mon Sep 17 00:00:00 2001 From: Favouris <131886201+Favouris@users.noreply.github.com> Date: Sun, 14 May 2023 19:17:38 +0800 Subject: [PATCH 12/14] Rename MCRevive6.js to MCrevive6.js --- scripts/portal/{MCRevive6.js => MCrevive6.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/portal/{MCRevive6.js => MCrevive6.js} (100%) diff --git a/scripts/portal/MCRevive6.js b/scripts/portal/MCrevive6.js similarity index 100% rename from scripts/portal/MCRevive6.js rename to scripts/portal/MCrevive6.js From a9d92b78a271436872408241b22bf04d135642f2 Mon Sep 17 00:00:00 2001 From: Matthew Hinds Date: Mon, 29 May 2023 12:57:01 +1200 Subject: [PATCH 13/14] Meso drop restricted by GM level --- .../java/net/server/channel/handlers/MesoDropHandler.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/net/server/channel/handlers/MesoDropHandler.java b/src/main/java/net/server/channel/handlers/MesoDropHandler.java index 2c8254aed7..f99c7edbee 100644 --- a/src/main/java/net/server/channel/handlers/MesoDropHandler.java +++ b/src/main/java/net/server/channel/handlers/MesoDropHandler.java @@ -23,6 +23,7 @@ package net.server.channel.handlers; import client.Character; import client.Client; +import config.YamlConfig; import net.AbstractPacketHandler; import net.packet.InPacket; import tools.PacketCreator; @@ -42,6 +43,11 @@ public final class MesoDropHandler extends AbstractPacketHandler { p.skip(4); int meso = p.readInt(); + if (player.isGM() && player.gmLevel() < YamlConfig.config.server.MINIMUM_GM_LEVEL_TO_DROP) { + player.message("You cannot drop mesos at your GM level."); + return; + } + if (c.tryacquireClient()) { // thanks imbee for noticing players not being able to throw mesos too fast try { if (meso <= player.getMeso() && meso > 9 && meso < 50001) { From 95bf0473f3f2fafcb8c26fb7c242ea552b437247 Mon Sep 17 00:00:00 2001 From: Matthew Hinds Date: Mon, 29 May 2023 14:32:01 +1200 Subject: [PATCH 14/14] Adjusted based on feedback --- .../processor/npc/StorageProcessor.java | 48 ++++++++++++++----- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/src/main/java/client/processor/npc/StorageProcessor.java b/src/main/java/client/processor/npc/StorageProcessor.java index 6bfc55f001..6fa24a7399 100644 --- a/src/main/java/client/processor/npc/StorageProcessor.java +++ b/src/main/java/client/processor/npc/StorageProcessor.java @@ -50,14 +50,9 @@ public class StorageProcessor { ItemInformationProvider ii = ItemInformationProvider.getInstance(); Character chr = c.getPlayer(); Storage storage = chr.getStorage(); - byte mode = p.readByte(); + String gmBlockedStorageMessage = "You cannot use the storage as a GM of this level."; - if (chr.isGM() && chr.gmLevel() < YamlConfig.config.server.MINIMUM_GM_LEVEL_TO_USE_STORAGE) { - chr.dropMessage(1, "You cannot use the storage as a GM of this level."); - log.info(String.format("GM %s blocked from placing items in storage", chr.getName())); - c.sendPacket(PacketCreator.enableActions()); - return; - } + byte mode = p.readByte(); if (chr.getLevel() < 15) { chr.dropMessage(1, "You may only use the storage once you have reached level 15."); @@ -68,7 +63,7 @@ public class StorageProcessor { if (c.tryacquireClient()) { try { switch (mode) { - case 4: { // take out + case 4: { // Take out byte type = p.readByte(); byte slot = p.readByte(); if (slot < 0 || slot > storage.getSlots()) { // removal starts at zero @@ -77,8 +72,17 @@ public class StorageProcessor { c.disconnect(true, false); return; } + slot = storage.getSlot(InventoryType.getByType(type), slot); Item item = storage.getItem(slot); + + if (hasGMRestrictions(chr)) { + chr.dropMessage(1, gmBlockedStorageMessage); + log.info(String.format("GM %s blocked from using storage", chr.getName())); + chr.sendPacket(PacketCreator.enableActions()); + return; + } + if (item != null) { if (ii.isPickupRestricted(item.getItemId()) && chr.haveItemWithId(item.getItemId(), true)) { c.sendPacket(PacketCreator.getStorageError((byte) 0x0C)); @@ -114,7 +118,7 @@ public class StorageProcessor { } break; } - case 5: { // store + case 5: { // Store short slot = p.readShort(); int itemId = p.readInt(); short quantity = p.readShort(); @@ -127,6 +131,14 @@ public class StorageProcessor { c.disconnect(true, false); return; } + + if (hasGMRestrictions(chr)) { + chr.dropMessage(1, gmBlockedStorageMessage); + log.info(String.format("GM %s blocked from using storage", chr.getName())); + chr.sendPacket(PacketCreator.enableActions()); + return; + } + if (quantity < 1) { c.sendPacket(PacketCreator.enableActions()); return; @@ -180,16 +192,24 @@ public class StorageProcessor { } break; } - case 6: // arrange items + case 6: // Arrange items if (YamlConfig.config.server.USE_STORAGE_ITEM_SORT) { storage.arrangeItems(c); } c.sendPacket(PacketCreator.enableActions()); break; - case 7: { // meso + case 7: { // Mesos int meso = p.readInt(); int storageMesos = storage.getMeso(); int playerMesos = chr.getMeso(); + + if (hasGMRestrictions(chr)) { + chr.dropMessage(1, gmBlockedStorageMessage); + log.info(String.format("GM %s blocked from using storage", chr.getName())); + chr.sendPacket(PacketCreator.enableActions()); + return; + } + if ((meso > 0 && storageMesos >= meso) || (meso < 0 && playerMesos >= -meso)) { if (meso < 0 && (storageMesos - meso) < 0) { meso = Integer.MIN_VALUE + storageMesos; @@ -215,7 +235,7 @@ public class StorageProcessor { } break; } - case 8: // close... unless the player decides to enter cash shop! + case 8: // Close (unless the player decides to enter cash shop) storage.close(); break; } @@ -224,4 +244,8 @@ public class StorageProcessor { } } } + + private static boolean hasGMRestrictions(Character character) { + return character.isGM() && character.gmLevel() < YamlConfig.config.server.MINIMUM_GM_LEVEL_TO_USE_STORAGE; + } }