From b80e9a3310694450756ae6e1b824b5e14e1d2f7f Mon Sep 17 00:00:00 2001 From: remsus Date: Fri, 10 Nov 2023 00:20:52 +0100 Subject: [PATCH 01/11] Bugfix: unable to complete scipted quests remotely --- src/main/java/scripting/quest/QuestScriptManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/scripting/quest/QuestScriptManager.java b/src/main/java/scripting/quest/QuestScriptManager.java index 6813525473..9d5c915f23 100644 --- a/src/main/java/scripting/quest/QuestScriptManager.java +++ b/src/main/java/scripting/quest/QuestScriptManager.java @@ -107,7 +107,7 @@ public class QuestScriptManager extends AbstractScriptManager { public void end(Client c, short questid, int npc) { Quest quest = Quest.getInstance(questid); - if (!c.getPlayer().getQuest(quest).getStatus().equals(QuestStatus.Status.STARTED) || !c.getPlayer().getMap().containsNPC(npc)) { + if (!c.getPlayer().getQuest(quest).getStatus().equals(QuestStatus.Status.STARTED) || (!c.getPlayer().getMap().containsNPC(npc) && !quest.isAutoComplete())) { dispose(c); return; } From db8666fc716795a3f8de947176c1090be94cb6b7 Mon Sep 17 00:00:00 2001 From: yuzumika Date: Fri, 24 Nov 2023 01:38:34 -0800 Subject: [PATCH 02/11] use isFace and isHair in ItemInformationProvider.getStringData --- src/main/java/server/ItemInformationProvider.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/server/ItemInformationProvider.java b/src/main/java/server/ItemInformationProvider.java index c2a04457f5..a06dab11cb 100644 --- a/src/main/java/server/ItemInformationProvider.java +++ b/src/main/java/server/ItemInformationProvider.java @@ -204,13 +204,13 @@ public class ItemInformationProvider { } else if (itemId >= 1040000 && itemId < 1050000) { theData = eqpStringData; cat = "Eqp/Coat"; - } else if (itemId >= 20000 && itemId < 22000) { + } else if (ItemConstants.isFace(itemId)) { theData = eqpStringData; cat = "Eqp/Face"; } else if (itemId >= 1080000 && itemId < 1090000) { theData = eqpStringData; cat = "Eqp/Glove"; - } else if (itemId >= 30000 && itemId < 35000) { + } else if (ItemConstants.isHair(itemId)) { theData = eqpStringData; cat = "Eqp/Hair"; } else if (itemId >= 1050000 && itemId < 1060000) { From 64bbff462d696645a9848759dade47483c9b6a1d Mon Sep 17 00:00:00 2001 From: yuzumika Date: Wed, 27 Dec 2023 14:54:10 -0800 Subject: [PATCH 03/11] minigame npc: dispose after creating a set of match cards --- scripts/npc/1012008.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/npc/1012008.js b/scripts/npc/1012008.js index 2b70d808e6..c6ae6b5f8c 100644 --- a/scripts/npc/1012008.js +++ b/scripts/npc/1012008.js @@ -57,6 +57,7 @@ function action(mode, type, selection) { if (cm.haveItem(4030012, 15)) { cm.gainItem(4030012, -15); cm.gainItem(4080100, 1); + cm.dispose(); } else { cm.sendNext("You want #bA set of Match Cards#k? Hmm...to make A set of Match Cards, you'll need some #bMonster Cards#k. Monster Card can be obtained by taking out the monsters all around the island. Collect 15 Monster Cards and you can make a set of A set of Match Cards."); //Lmfao a set of A set xD cm.dispose(); From ee8cb545e1a3a047dd7942c774c7cc05f29dce66 Mon Sep 17 00:00:00 2001 From: yuzumika Date: Wed, 27 Dec 2023 15:18:22 -0800 Subject: [PATCH 04/11] minigame npc: use omokamount constant consistently; tiny text tweak to make it more GMS-like --- scripts/npc/1012008.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/npc/1012008.js b/scripts/npc/1012008.js index c6ae6b5f8c..197fe3c182 100644 --- a/scripts/npc/1012008.js +++ b/scripts/npc/1012008.js @@ -31,7 +31,7 @@ function action(mode, type, selection) { } if (status == 0) { - cm.sendSimple("Hey, you look like you need a breather. You should be enjoying the life, just like I am. Well, if you have a couple of items, I can trade you for an item you can play minigames with. Now... what can I do for you?#b\r\n#L0#Create a minigame item#l\r\n#L1#Explain to me what the minigames are about#l#k"); + cm.sendSimple("Hey, you look like you need a breather from all that hunting. You should be enjoying the life, just like I am. Well, if you have a couple of items, I can trade you for an item you can play minigames with. Now... what can I do for you?#b\r\n#L0#Create a minigame item#l\r\n#L1#Explain to me what the minigames are about#l#k"); } else if (status == 1) { if (selection == 0) { @@ -82,7 +82,7 @@ function action(mode, type, selection) { if (current == 1 || current == 2) { cm.sendNextPrev("Enter the room, and when you're ready to play, click on #bReady#k.\r\nOnce the visitor clicks on #bReady#k, the room owner can press #bStart#k to begin the game. If an unwanted visitor walks in, and you don't want to play with that person, the room owner has the right to kick the visitor out of the room. There will be a square box with x written on the right of that person. Click on that for a cold goodbye, okay?"); //Oh yeah, because people WALK in Omok Rooms. } else if (current == 3) { - if (cm.haveItem(omok1piece[selection], 99) && cm.haveItem(omok2piece[selection], 99) && cm.haveItem(4030009, 1)) { + if (cm.haveItem(omok1piece[selection], omokamount) && cm.haveItem(omok2piece[selection], omokamount) && cm.haveItem(4030009, 1)) { cm.gainItem(omok1piece[selection], -omokamount); cm.gainItem(omok2piece[selection], -omokamount); cm.gainItem(4030009, -1); From 9c54f3a8eaf645e2fc82490a5d06aeac931dc609 Mon Sep 17 00:00:00 2001 From: yuzumika Date: Wed, 27 Dec 2023 15:35:45 -0800 Subject: [PATCH 05/11] minigame npc: add more disposes, fix typo --- scripts/npc/1012008.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/npc/1012008.js b/scripts/npc/1012008.js index 197fe3c182..94b42f2f3c 100644 --- a/scripts/npc/1012008.js +++ b/scripts/npc/1012008.js @@ -96,7 +96,7 @@ function action(mode, type, selection) { } else if (status == 5) { if (current == 1) { - cm.sendNextPrev("When the first fame starts, #bthe room owner goes first#k. Beward that you'll be given a time limit, and you may lose your turn if you don't make your move on time. Normally, 3 x 3 is not allowed, but if there comes a point that it's absolutely necessary to put your piece there or face ending the game, then you can put it there. 3 x 3 is allowed as the last line of defense! Oh, and it won't count if it's #r6 or 7 straight#k. Only 5!"); + cm.sendNextPrev("When the first game starts, #bthe room owner goes first#k. Beward that you'll be given a time limit, and you may lose your turn if you don't make your move on time. Normally, 3 x 3 is not allowed, but if there comes a point that it's absolutely necessary to put your piece there or face ending the game, then you can put it there. 3 x 3 is allowed as the last line of defense! Oh, and it won't count if it's #r6 or 7 straight#k. Only 5!"); } else if (current == 2) { cm.sendNextPrev("Oh, and unlike Omok, when you create the game room for Match Cards, you'll need to set your game on the number of cards you'll use for the game. There are 3 modes avaliable, 3x4, 4x5, and 5x6, which will require 12, 20, and 30 cards respectively. Remember that you won't beable to change it up once the room is open, so if you really wish to change it up, you may have to close the room and open another one."); } @@ -111,12 +111,14 @@ function action(mode, type, selection) { } else if (status == 7) { if (current == 1) { cm.sendPrev("When the next game starts, the loser will go first. Also, no one is allowed to leave in the middle of a game. If you do, you may need to request either a #bforfeit or tie#k. (Of course, if you request a forfeit, you'll lose the game.) And if you click on 'Leave' in the middle of the game and call to leave after the game, you'll leave the room right after the game is over. This will be a much more useful way to leave."); + cm.dispose(); } else if (current == 2) { cm.sendNextPrev("If you and your opponent have the same number of matched pairs, then whoever had a longer streak of matched pairs will win. If you ever feel the need to go to the bathroom, or take an extended break, you can request a #btie#k. The game will end in a tie if the opponent accepts the request. Tip: this may be a good way to keep your friendships in tact."); } } else if (status == 8) { if (current == 2) { cm.sendPrev("When the next game starts, the loser will go first. Also, no one is allowed to leave in the middle of a game. If you do, you may need to request either a #bforfeit or tie#k. (Of course, if you request a forfeit, you'll lose the game.) And if you click on 'Leave' in the middle of the game and call to leave after the game, you'll leave the room right after the game is over. This will be a much more useful way to leave."); + cm.dispose(); } } } \ No newline at end of file From cb0320a471bf3dd8c482ba3a8fe41b55a13266dd Mon Sep 17 00:00:00 2001 From: yuzumika Date: Wed, 3 Jan 2024 16:10:23 -0800 Subject: [PATCH 06/11] NPCMoreTalkHandler: don't underflow selection --- .../java/net/server/channel/handlers/NPCMoreTalkHandler.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/net/server/channel/handlers/NPCMoreTalkHandler.java b/src/main/java/net/server/channel/handlers/NPCMoreTalkHandler.java index 0dc04cd8a0..fa7c0a09e7 100644 --- a/src/main/java/net/server/channel/handlers/NPCMoreTalkHandler.java +++ b/src/main/java/net/server/channel/handlers/NPCMoreTalkHandler.java @@ -60,6 +60,11 @@ public final class NPCMoreTalkHandler extends AbstractPacketHandler { selection = p.readInt(); } else if (p.available() > 0) { selection = p.readByte(); + // If there are more than 127 choices, don't underflow to -128. + // This is useful if you want to have more than 127 hairs/faces at a stylist NPC. + if (selection < 0) { + selection += 256; + } } if (c.getQM() != null) { if (c.getQM().isStart()) { From 5a4200cc8e45181250e39ff6dc7f0f762c1efa68 Mon Sep 17 00:00:00 2001 From: yuzumika Date: Thu, 4 Jan 2024 10:55:07 -0800 Subject: [PATCH 07/11] implement ByteBufInPacket.readUnsignedByte --- src/main/java/net/packet/ByteBufInPacket.java | 2 ++ src/main/java/net/packet/InPacket.java | 1 + .../net/server/channel/handlers/NPCMoreTalkHandler.java | 7 +------ 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/packet/ByteBufInPacket.java b/src/main/java/net/packet/ByteBufInPacket.java index 19dfdfffc0..e79326f7c6 100644 --- a/src/main/java/net/packet/ByteBufInPacket.java +++ b/src/main/java/net/packet/ByteBufInPacket.java @@ -22,6 +22,8 @@ public class ByteBufInPacket implements InPacket { public byte readByte() { return byteBuf.readByte(); } + @Override + public short readUnsignedByte() { return byteBuf.readUnsignedByte(); } @Override public short readShort() { diff --git a/src/main/java/net/packet/InPacket.java b/src/main/java/net/packet/InPacket.java index 37e5280899..e21e15a44a 100644 --- a/src/main/java/net/packet/InPacket.java +++ b/src/main/java/net/packet/InPacket.java @@ -4,6 +4,7 @@ import java.awt.*; public interface InPacket extends Packet { byte readByte(); + short readUnsignedByte(); short readShort(); int readInt(); long readLong(); diff --git a/src/main/java/net/server/channel/handlers/NPCMoreTalkHandler.java b/src/main/java/net/server/channel/handlers/NPCMoreTalkHandler.java index fa7c0a09e7..e39b1676e4 100644 --- a/src/main/java/net/server/channel/handlers/NPCMoreTalkHandler.java +++ b/src/main/java/net/server/channel/handlers/NPCMoreTalkHandler.java @@ -59,12 +59,7 @@ public final class NPCMoreTalkHandler extends AbstractPacketHandler { if (p.available() >= 4) { selection = p.readInt(); } else if (p.available() > 0) { - selection = p.readByte(); - // If there are more than 127 choices, don't underflow to -128. - // This is useful if you want to have more than 127 hairs/faces at a stylist NPC. - if (selection < 0) { - selection += 256; - } + selection = p.readUnsignedByte(); } if (c.getQM() != null) { if (c.getQM().isStart()) { From 738e1b24e620c6be326414ed2a10a6679c1970a4 Mon Sep 17 00:00:00 2001 From: yuzumika Date: Thu, 4 Jan 2024 13:42:20 -0800 Subject: [PATCH 08/11] add unit tests for ByteBufInPacketTest.readUnsignedByte --- .../java/net/packet/ByteBufInPacketTest.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/test/java/net/packet/ByteBufInPacketTest.java b/src/test/java/net/packet/ByteBufInPacketTest.java index 3a27dd795a..6837ecfe1c 100644 --- a/src/test/java/net/packet/ByteBufInPacketTest.java +++ b/src/test/java/net/packet/ByteBufInPacketTest.java @@ -38,6 +38,36 @@ class ByteBufInPacketTest { assertEquals(writtenByte, readByte); } + @Test + void readUnsignedByte() { + final byte writtenByte = Byte.MAX_VALUE; + byteBuf.writeByte(writtenByte); + + short readUnsignedByte = inPacket.readUnsignedByte(); + + assertEquals(writtenByte, readUnsignedByte); + } + + @Test + void readUnsignedByte_shouldBeNonnegative() { + final byte writtenByte = Byte.MIN_VALUE; + byteBuf.writeByte(writtenByte); + + short readUnsignedByte = inPacket.readUnsignedByte(); + + assertEquals((short)writtenByte + 256, readUnsignedByte); + } + + @Test + void readUnsignedByte_shouldBeNonnegative2() { + final byte writtenByte = -1; + byteBuf.writeByte(writtenByte); + + short readUnsignedByte = inPacket.readUnsignedByte(); + + assertEquals((short)writtenByte + 256, readUnsignedByte); + } + @Test void readShort() { final short writtenShort = 12_345; From 7004de6e7107a72bf3e599cae75aa287b087b449 Mon Sep 17 00:00:00 2001 From: yuzumika Date: Thu, 4 Jan 2024 14:30:59 -0800 Subject: [PATCH 09/11] ppq: fix bug where non-party leader can get stuck in an npc dialogue loop --- scripts/npc/2094002.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/npc/2094002.js b/scripts/npc/2094002.js index cc3ada4d87..34c3f0ceae 100644 --- a/scripts/npc/2094002.js +++ b/scripts/npc/2094002.js @@ -23,7 +23,12 @@ function action(mode, type, selection) { } if (!cm.isEventLeader()) { - cm.sendYesNo("I wish for your leader to talk to me. Alternatively, you may be wanting to quit. Are you going to abandon this campaign?"); + // Player chose "No" or "End Chat" + if (mode <= 0) { + cm.dispose(); + } else { + cm.sendYesNo("I wish for your leader to talk to me. Alternatively, you may be wanting to quit. Are you going to abandon this campaign?"); + } } else { var eim = cm.getEventInstance(); if (eim == null) { From 8b254a294eb8d912eee897c0a929c9a9e9443a8b Mon Sep 17 00:00:00 2001 From: leevccc <94272011+leevccc@users.noreply.github.com> Date: Sun, 14 Jan 2024 18:15:48 +0800 Subject: [PATCH 10/11] fix: item lock cant extend lock time --- .../java/net/server/channel/handlers/UseCashItemHandler.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/server/channel/handlers/UseCashItemHandler.java b/src/main/java/net/server/channel/handlers/UseCashItemHandler.java index 1040376772..01b2fa10b5 100644 --- a/src/main/java/net/server/channel/handlers/UseCashItemHandler.java +++ b/src/main/java/net/server/channel/handlers/UseCashItemHandler.java @@ -229,7 +229,7 @@ public final class UseCashItemHandler extends AbstractPacketHandler { } short flag = eq.getFlag(); flag |= ItemConstants.LOCK; - if (eq.getExpiration() > -1) { + if (eq.getExpiration() > -1 && (eq.getFlag() & ItemConstants.LOCK) != ItemConstants.LOCK) { return; //No perma items pls } eq.setFlag(flag); @@ -246,7 +246,8 @@ public final class UseCashItemHandler extends AbstractPacketHandler { } if (period > 0) { - eq.setExpiration(currentServerTime() + DAYS.toMillis(period)); + long expiration = eq.getExpiration() > -1 ? eq.getExpiration() : currentServerTime(); + eq.setExpiration(expiration + DAYS.toMillis(period)); } // double-remove found thanks to BHB From 08b089d9be9a1e4c259ea891dab51c437d4e3ae5 Mon Sep 17 00:00:00 2001 From: leevccc <94272011+leevccc@users.noreply.github.com> Date: Sun, 14 Jan 2024 22:13:16 +0800 Subject: [PATCH 11/11] fix: seal lock cant extend lock time --- .../java/net/server/channel/handlers/UseCashItemHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/server/channel/handlers/UseCashItemHandler.java b/src/main/java/net/server/channel/handlers/UseCashItemHandler.java index 01b2fa10b5..56b6b02a3c 100644 --- a/src/main/java/net/server/channel/handlers/UseCashItemHandler.java +++ b/src/main/java/net/server/channel/handlers/UseCashItemHandler.java @@ -228,10 +228,10 @@ public final class UseCashItemHandler extends AbstractPacketHandler { return; } short flag = eq.getFlag(); - flag |= ItemConstants.LOCK; if (eq.getExpiration() > -1 && (eq.getFlag() & ItemConstants.LOCK) != ItemConstants.LOCK) { return; //No perma items pls } + flag |= ItemConstants.LOCK; eq.setFlag(flag); long period = 0;