Compare commits

...

17 Commits

Author SHA1 Message Date
Ponk
d307eff71f Merge pull request #177 from LynxStar/patch/mini-dungeons #patch
Fix mini-dungeon portals for parties
2023-07-10 23:09:51 +02:00
Arthur Charlton
b935725096 Handle the potentially null portal based on the name.
Matches the behavior of warping a character to a named portal.
2023-07-10 17:01:48 -04:00
Ponk
12248acd7b Merge pull request #178 from LynxStar/patch/delivery-system #patch
Delivery System - Invalid Recipient Name Patch
2023-07-10 22:40:57 +02:00
Arthur Charlton
07eb0f5e8e Untangle nested control flow conditions. 2023-07-05 14:16:09 -04:00
Arthur Charlton
cfb5fc25c3 Calling code assumes the pair never null and uses -1 to signify not found. 2023-07-05 14:12:42 -04:00
Arthur Charlton
3816e1c5bd Add the warp party function that the scripts use 2023-07-03 18:25:14 -04:00
Ponk
c9d551cd39 Merge pull request #173 from MatthewHinds/gm-security #minor
GM security changes to prevent item/mesos abuse
2023-05-29 15:50:03 +02:00
Matthew Hinds
95bf0473f3 Adjusted based on feedback 2023-05-29 14:32:01 +12:00
Matthew Hinds
a9d92b78a2 Meso drop restricted by GM level 2023-05-29 12:57:01 +12:00
Ponk
b8ebace039 Merge pull request #174 from Favouris/master #patch
Rename Monster Carnival portal scripts
2023-05-15 12:00:44 +02:00
Favouris
9223957931 Rename MCRevive6.js to MCrevive6.js 2023-05-14 19:17:38 +08:00
Favouris
5cddb7f2b6 Rename MCRevive5.js to MCrevive5.js 2023-05-14 19:17:25 +08:00
Favouris
08e7a3af16 Rename MCRevive4.js to MCrevive4.js 2023-05-14 19:17:15 +08:00
Favouris
1416cd432d Rename MCRevive3.js to MCrevive3.js 2023-05-14 19:17:03 +08:00
Favouris
2d6cf07a65 Rename MCRevive2.js to MCrevive2.js 2023-05-14 19:16:51 +08:00
Favouris
0b73d6112a Rename MCRevive1.js to MCrevive1.js 2023-05-14 19:16:40 +08:00
Matthew Hinds
4546fd44ff 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. 2023-05-12 18:02:08 +12:00
14 changed files with 112 additions and 23 deletions

View File

@@ -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

View File

@@ -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;
}

View File

@@ -92,14 +92,15 @@ public class DueyProcessor {
}
private static Pair<Integer, Integer> getAccountCharacterIdFromCNAME(String name) {
Pair<Integer, Integer> ids = null;
Pair<Integer, Integer> ids = new Pair<>(-1, -1);
try (Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("SELECT id,accountid FROM characters WHERE name = ?")) {
ps.setString(1, name);
try (ResultSet rs = ps.executeQuery()) {
if (rs.next()) {
ids = new Pair<>(rs.getInt("accountid"), rs.getInt("id"));
ids.left = rs.getInt("accountid");
ids.right = rs.getInt("id");
}
}
} catch (SQLException e) {
@@ -284,6 +285,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.");
@@ -308,30 +316,25 @@ public class DueyProcessor {
return;
}
Pair<Integer, Integer> accIdCid;
if (c.getPlayer().getMeso() >= finalcost) {
accIdCid = getAccountCharacterIdFromCNAME(recipient);
int recipientAccId = accIdCid.getLeft();
if (recipientAccId != -1) {
if (recipientAccId == c.getAccID()) {
c.sendPacket(PacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_SAMEACC_ERROR.getCode()));
return;
}
} else {
c.sendPacket(PacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_NAME_DOES_NOT_EXIST.getCode()));
return;
}
} else {
if(c.getPlayer().getMeso() < finalcost) {
c.sendPacket(PacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_NOT_ENOUGH_MESOS.getCode()));
return;
}
int recipientCid = accIdCid.getRight();
if (recipientCid == -1) {
var accIdCid = getAccountCharacterIdFromCNAME(recipient);
var recipientAccId = accIdCid.getLeft();
var recipientCid = accIdCid.getRight();
if (recipientAccId == -1 || recipientCid == -1) {
c.sendPacket(PacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_NAME_DOES_NOT_EXIST.getCode()));
return;
}
if (recipientAccId == c.getAccID()) {
c.sendPacket(PacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_SAMEACC_ERROR.getCode()));
return;
}
if (quick) {
InventoryManipulator.removeById(c, InventoryType.CASH, ItemId.QUICK_DELIVERY_TICKET, (short) 1, false, false);
}

View File

@@ -50,6 +50,8 @@ public class StorageProcessor {
ItemInformationProvider ii = ItemInformationProvider.getInstance();
Character chr = c.getPlayer();
Storage storage = chr.getStorage();
String gmBlockedStorageMessage = "You cannot use the storage as a GM of this level.";
byte mode = p.readByte();
if (chr.getLevel() < 15) {
@@ -61,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
@@ -70,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));
@@ -107,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();
@@ -120,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;
@@ -173,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;
@@ -208,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;
}
@@ -217,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;
}
}

View File

@@ -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<String, String> NPCS_SCRIPTABLE = new HashMap<>();
}

View File

@@ -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) {

View File

@@ -133,6 +133,23 @@ public class AbstractPlayerInteraction {
warpParty(id, portalId, mapid, mapid);
}
public void warpParty(int map, String portalName) {
int mapid = getMapId();
var warpMap = c.getChannelServer().getMapFactory().getMap(map);
var portal = warpMap.getPortal(portalName);
if (portal == null) {
portal = warpMap.getPortal(0);
}
var portalId = portal.getId();
warpParty(map, portalId, mapid, mapid);
}
public void warpParty(int id, int fromMinId, int fromMaxId) {
warpParty(id, 0, fromMinId, fromMaxId);
}

View File

@@ -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.");