Compare commits

...

14 Commits

Author SHA1 Message Date
Ponk
ecd155f2bb Merge pull request #201 from peamy/master #patch
BugFix: can't give CASH items to player (prepareInventoryItemList)
2023-11-08 20:50:50 +01:00
remsus
d6147d5191 Fix preparation of invList (CASH was skipped) in prepareInventoryItemList (AbstractPlayerInteraction) 2023-11-08 11:26:55 +01:00
Ponk
7ef471f1e2 Merge pull request #197 from wangxiaobao0851/fix-mts #patch
Fix MTS sql syntax error and month error
2023-11-07 17:28:16 +01:00
王小宝
c3404d296a Fix MTS sql syntax error and month error 2023-10-13 21:16:40 +08:00
Ponk
c609bcf2ee Merge pull request #193 from P0nk/fix-192/playernpc #patch
Fix #192 - Unable to create PlayerNPC
2023-09-19 17:15:00 +02:00
P0nk
0aee9d7c3f Fix unable to create playernpc
The initialization of the running world counters depended on worlds already having been initialized, so I made that dependency more explicit.
2023-09-19 12:56:51 +02:00
P0nk
a49c1703ae Remove developer player npc 2023-09-18 23:26:37 +02:00
Ponk
38eecd0db7 Merge pull request #188 from leevccc/master #patch
fix: error flag after use karma
2023-09-09 07:56:33 +02:00
leevccc
e320bafa8b fix: error flag after use karma
setFalg() function is designed to take arguments of type short. Forcing the short type flag to be converted to the byte type causes some errors here.

For example, the equipment merge system will make the UNTRADEABLE flag become 520, combined with the Scissors of Karma 16, and finally become 536, this value is beyond the byte range, and the mandatory variable type will cause the flag error, the specific problem I encountered is that the MERGE_UNTRADEABLE flag is lost after using the Scissors of Karma.
2023-09-08 04:59:56 +08:00
Ponk
754e5e61f2 Merge pull request #185 from Arnuh/fix-client-local-address #patch
Fix masking of ip address when connecting locally
2023-08-20 18:26:59 +02:00
Ponk
afba85827a Merge pull request #186 from sashimi-yzh/fix-cats-eye-dropper #patch
fix the dropper of Cat's Eye
2023-08-20 18:21:20 +02:00
Zihao Yu
8cd5211b8b fix the dropper of Cat's Eye
* it was previously dropped from Scorpion, which is wrong
2023-08-20 22:55:43 +08:00
Arnah
2d7525f2b4 Fix cashshop exiting not using proper ip 2023-08-16 16:19:16 -06:00
Arnah
7adb25888f Stop masking ip address when connecting locally 2023-08-16 00:53:40 -06:00
13 changed files with 52 additions and 205 deletions

View File

@@ -19993,7 +19993,7 @@ USE `cosmic`;
(8220015, 1452015, 1, 1, 0, 22000),
(8220015, 1472031, 1, 1, 0, 22000),
(8220015, 1482010, 1, 1, 0, 22000),
(2110301, 4031568, 1, 1, 3911, 80000),
(2100108, 4031568, 1, 1, 3911, 80000),
(9300150, 4031774, 1, 1, 3361, 100000),
(9300150, 4031796, 1, 1, 3362, 100000),
(9300105, 4001118, 1, 1, 3814, 200000),

View File

@@ -39,7 +39,6 @@ import net.server.Server;
import net.server.channel.Channel;
import net.server.coordinator.login.LoginBypassCoordinator;
import net.server.coordinator.session.Hwid;
import net.server.coordinator.session.IpAddresses;
import net.server.coordinator.session.SessionCoordinator;
import net.server.coordinator.session.SessionCoordinator.AntiMulticlientResult;
import net.server.guild.Guild;
@@ -176,10 +175,7 @@ public class Client extends ChannelInboundHandlerAdapter {
private static String getRemoteAddress(io.netty.channel.Channel channel) {
String remoteAddress = "null";
try {
String hostAddress = ((InetSocketAddress) channel.remoteAddress()).getAddress().getHostAddress();
if (hostAddress != null) {
remoteAddress = IpAddresses.evaluateRemoteAddress(hostAddress); // thanks dyz for noticing Local/LAN/WAN connections not interacting properly
}
remoteAddress = ((InetSocketAddress) channel.remoteAddress()).getAddress().getHostAddress();
} catch (NullPointerException npe) {
log.warn("Unable to get remote address for client", npe);
}

View File

@@ -43,7 +43,7 @@ public class KarmaManipulator {
flag ^= karmaFlag;
flag |= ItemConstants.UNTRADEABLE;
item.setFlag((byte) flag);
item.setFlag(flag);
}
}
@@ -53,6 +53,6 @@ public class KarmaManipulator {
flag |= karmaFlag;
flag &= (0xFFFFFFFF ^ ItemConstants.UNTRADEABLE);
item.setFlag((byte) flag);
item.setFlag(flag);
}
}

View File

@@ -15,7 +15,6 @@ import net.encryption.InitializationVector;
import net.encryption.PacketCodec;
import net.packet.logging.InPacketLogger;
import net.packet.logging.OutPacketLogger;
import net.server.coordinator.session.IpAddresses;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tools.PacketCreator;
@@ -35,10 +34,7 @@ public abstract class ServerChannelInitializer extends ChannelInitializer<Socket
String getRemoteAddress(Channel channel) {
String remoteAddress = "null";
try {
String hostAddress = ((InetSocketAddress) channel.remoteAddress()).getAddress().getHostAddress();
if (hostAddress != null) {
remoteAddress = IpAddresses.evaluateRemoteAddress(hostAddress); // thanks dyz for noticing Local/LAN/WAN connections not interacting properly
}
remoteAddress = ((InetSocketAddress) channel.remoteAddress()).getAddress().getHostAddress();
} catch (NullPointerException npe) {
log.warn("Unable to get remote address from netty Channel: {}", channel, npe);
}

View File

@@ -57,7 +57,7 @@ import server.SkillbookInformationProvider;
import server.ThreadManager;
import server.TimerManager;
import server.expeditions.ExpeditionBossLog;
import server.life.PlayerNPCFactory;
import server.life.PlayerNPC;
import server.quest.Quest;
import service.NoteService;
import tools.DatabaseConnection;
@@ -849,15 +849,15 @@ public class Server {
final ExecutorService initExecutor = Executors.newFixedThreadPool(10);
// Run slow operations asynchronously to make startup faster
final List<Future<?>> futures = new ArrayList<>();
futures.add(initExecutor.submit(() -> SkillFactory.loadAllSkills()));
futures.add(initExecutor.submit(() -> CashItemFactory.loadAllCashItems()));
futures.add(initExecutor.submit(() -> Quest.loadAllQuests()));
futures.add(initExecutor.submit(() -> SkillbookInformationProvider.loadAllSkillbookInformation()));
futures.add(initExecutor.submit(() -> PlayerNPCFactory.loadFactoryMetadata()));
futures.add(initExecutor.submit(SkillFactory::loadAllSkills));
futures.add(initExecutor.submit(CashItemFactory::loadAllCashItems));
futures.add(initExecutor.submit(Quest::loadAllQuests));
futures.add(initExecutor.submit(SkillbookInformationProvider::loadAllSkillbookInformation));
initExecutor.shutdown();
TimeZone.setDefault(TimeZone.getTimeZone(YamlConfig.config.server.TIMEZONE));
final int worldCount = Math.min(GameConstants.WORLD_NAMES.length, YamlConfig.config.server.WORLDS);
try (Connection con = DatabaseConnection.getConnection()) {
setAllLoggedOut(con);
setAllMerchantsInactive(con);
@@ -868,6 +868,7 @@ public class Server {
CashIdGenerator.loadExistentCashIdsFromDb(con);
applyAllNameChanges(con); // -- name changes can be missed by INSTANT_NAME_CHANGE --
applyAllWorldTransfers(con);
PlayerNPC.loadRunningRankData(con, worldCount);
} catch (SQLException sqle) {
log.error("Failed to run all startup-bound database tasks", sqle);
throw new IllegalStateException(sqle);
@@ -877,8 +878,6 @@ public class Server {
initializeTimelyTasks(channelDependencies); // aggregated method for timely tasks thanks to lxconan
try {
int worldCount = Math.min(GameConstants.WORLD_NAMES.length, YamlConfig.config.server.WORLDS);
for (int i = 0; i < worldCount; i++) {
initWorld();
}

View File

@@ -29,6 +29,7 @@ import constants.id.ItemId;
import constants.id.MapId;
import net.AbstractPacketHandler;
import net.packet.InPacket;
import net.server.Server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import server.Trade;
@@ -181,7 +182,11 @@ public final class ChangeMapHandler extends AbstractPacketHandler {
c.disconnect(false, false);
return;
}
String[] socket = c.getChannelServer().getIP().split(":");
String[] socket = Server.getInstance().getInetSocket(c, c.getWorld(), c.getChannel());
if (socket == null) {
c.enableCSActions();
return;
}
chr.getCashShop().open(false);
chr.setSessionTransitionState();

View File

@@ -45,6 +45,8 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
@@ -122,40 +124,12 @@ public final class MTSHandler extends AbstractPacketHandler {
return;
}
}
Calendar calendar = Calendar.getInstance();
int year;
int month;
int day;
int oldmax = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
int oldday = calendar.get(Calendar.DAY_OF_MONTH) + 7;
if (oldmax < oldday) {
if (calendar.get(Calendar.MONTH) + 2 > 12) {
year = calendar.get(Calendar.YEAR) + 1;
month = 1;
calendar.set(year, month, 1);
day = oldday - oldmax;
} else {
month = calendar.get(Calendar.MONTH) + 2;
year = calendar.get(Calendar.YEAR);
calendar.set(year, month, 1);
day = oldday - oldmax;
}
} else {
day = calendar.get(Calendar.DAY_OF_MONTH) + 7;
month = calendar.get(Calendar.MONTH);
year = calendar.get(Calendar.YEAR);
}
String date = year + "-";
if (month < 10) {
date += "0" + month + "-";
} else {
date += month + "-";
}
if (day < 10) {
date += "0" + day;
} else {
date += day + "";
}
LocalDate now = LocalDate.now();
LocalDate sellEnd = now.plusDays(7);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String date = sellEnd.format(formatter);
if (!i.getInventoryType().equals(InventoryType.EQUIP)) {
Item item = i;
try (PreparedStatement pse = con.prepareStatement("INSERT INTO mts_items (tab, type, itemid, quantity, expiration, giftFrom, seller, price, owner, sellername, sell_ends) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")) {
@@ -761,7 +735,7 @@ public final class MTSHandler extends AbstractPacketHandler {
}
}
}
try (PreparedStatement ps = con.prepareStatement("SELECT COUNT(*) FROM mts_items WHERE tab = ? " + (type != 0 ? "AND type = ?" : "") + "AND transfer = 0")) {
try (PreparedStatement ps = con.prepareStatement("SELECT COUNT(*) FROM mts_items WHERE tab = ? " + (type != 0 ? "AND type = ?" : "") + " AND transfer = 0")) {
ps.setInt(1, tab);
if (type != 0) {
ps.setInt(2, type);

View File

@@ -1,7 +1,5 @@
package net.server.coordinator.session;
import config.YamlConfig;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -16,14 +14,6 @@ public class IpAddresses {
.collect(Collectors.toList());
}
public static String evaluateRemoteAddress(String inetAddress) {
if (isLocalAddress(inetAddress) || isLanAddress(inetAddress)) {
return YamlConfig.config.server.HOST;
} else {
return inetAddress;
}
}
public static boolean isLocalAddress(String inetAddress) {
return inetAddress.startsWith("127.");
}

View File

@@ -291,7 +291,7 @@ public class AbstractPlayerInteraction {
int size = Math.min(itemids.size(), quantity.size());
List<List<Pair<Integer, Integer>>> invList = new ArrayList<>(6);
for (int i = InventoryType.UNDEFINED.getType(); i < InventoryType.CASH.getType(); i++) {
for (int i = InventoryType.UNDEFINED.getType(); i <= InventoryType.CASH.getType(); i++) {
invList.add(new LinkedList<>());
}

View File

@@ -23,6 +23,8 @@ package server;
import client.inventory.Item;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
/**
@@ -38,13 +40,16 @@ public class MTSItemInfo {
private int day = 1;
public MTSItemInfo(Item item, int price, int id, int cid, String seller, String date) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate sellEnd = LocalDate.parse(date, formatter);
this.item = item;
this.price = price;
this.seller = seller;
this.id = id;
this.year = Integer.parseInt(date.substring(0, 4));
this.month = Integer.parseInt(date.substring(5, 7));
this.day = Integer.parseInt(date.substring(8, 10));
this.year = sellEnd.getYear();
this.month = sellEnd.getMonthValue();
this.day = sellEnd.getDayOfMonth();
}
public Item getItem() {

View File

@@ -53,6 +53,8 @@ import java.util.concurrent.atomic.AtomicInteger;
* @author XoticStory
* @author Ronan
*/
// TODO: remove dependency on custom Npc.wz. All NPCs with id 9901910 and above are custom additions for player npcs.
// In summary: NPCs 9901910-9906599 and 9977777 are custom additions to HeavenMS that should be removed.
public class PlayerNPC extends AbstractMapObject {
private static final Logger log = LoggerFactory.getLogger(PlayerNPC.class);
private static final Map<Byte, List<Integer>> availablePlayerNpcScriptIds = new HashMap<>();
@@ -67,10 +69,6 @@ public class PlayerNPC extends AbstractMapObject {
private int dir, FH, RX0, RX1, CY;
private int worldRank, overallRank, worldJobRank, overallJobRank;
static {
getRunningMetadata();
}
public PlayerNPC(String name, int scriptId, int face, int hair, int gender, byte skin, Map<Short, Integer> equips, int dir, int FH, int RX0, int RX1, int CX, int CY, int oid) {
this.equips = equips;
this.scriptId = scriptId;
@@ -128,6 +126,12 @@ public class PlayerNPC extends AbstractMapObject {
}
}
public static void loadRunningRankData(Connection con, int worlds) throws SQLException {
getRunningOverallRanks(con);
getRunningWorldRanks(con, worlds);
getRunningWorldJobRanks(con);
}
public Map<Short, Integer> getEquips() {
return equips;
}
@@ -213,16 +217,6 @@ public class PlayerNPC extends AbstractMapObject {
client.sendPacket(PacketCreator.removePlayerNPC(this.getObjectId()));
}
private static void getRunningMetadata() {
try (Connection con = DatabaseConnection.getConnection()) {
getRunningOverallRanks(con);
getRunningWorldRanks(con);
getRunningWorldJobRanks(con);
} catch (SQLException e) {
e.printStackTrace();
}
}
private static void getRunningOverallRanks(Connection con) throws SQLException {
try (PreparedStatement ps = con.prepareStatement("SELECT max(overallrank) FROM playernpcs");
ResultSet rs = ps.executeQuery()) {
@@ -235,9 +229,8 @@ public class PlayerNPC extends AbstractMapObject {
}
}
private static void getRunningWorldRanks(Connection con) throws SQLException {
int numWorlds = Server.getInstance().getWorldsSize();
for (int i = 0; i < numWorlds; i++) {
private static void getRunningWorldRanks(Connection con, int worlds) throws SQLException {
for (int i = 0; i < worlds; i++) {
runningWorldRank.add(new AtomicInteger(1));
}
@@ -246,7 +239,7 @@ public class PlayerNPC extends AbstractMapObject {
while (rs.next()) {
int wid = rs.getInt(1);
if (wid < numWorlds) {
if (wid < worlds) {
runningWorldRank.get(wid).set(rs.getInt(2) + 1);
}
}
@@ -649,4 +642,4 @@ public class PlayerNPC extends AbstractMapObject {
e.printStackTrace();
}
}
}
}

View File

@@ -19,124 +19,17 @@
*/
package server.life;
import constants.id.ItemId;
import constants.id.MapId;
import constants.id.NpcId;
import net.server.Server;
import provider.Data;
import provider.DataProvider;
import provider.DataProviderFactory;
import provider.DataTool;
import provider.wz.WZFiles;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* @author RonanLana
*/
public class PlayerNPCFactory {
private static final DataProvider npcData = DataProviderFactory.getDataProvider(WZFiles.NPC);
private static final Map<Integer, List<PlayerNPC>> dnpcMaps = new HashMap<>();
private static Integer runningDeveloperOid = 2147483000; // 647 slots, long enough
public synchronized static boolean isExistentScriptid(int scriptid) {
return npcData.getData(scriptid + ".img") != null;
}
private static void loadDeveloperRoomMetadata(DataProvider npc) {
Data thisData = npc.getData(NpcId.CUSTOM_DEV + ".img");
if (thisData != null) {
DataProvider map = DataProviderFactory.getDataProvider(WZFiles.MAP);
thisData = map.getData("Map/Map7/" + MapId.DEVELOPERS_HQ + ".img");
if (thisData != null) {
DataProvider sound = DataProviderFactory.getDataProvider(WZFiles.SOUND);
thisData = sound.getData("Field.img");
if (thisData != null) {
Data md = thisData.getChildByPath("anthem/brazil");
if (md != null) {
Server.getInstance().setAvailableDeveloperRoom();
}
}
}
}
}
public synchronized static void loadFactoryMetadata() {
DataProvider npc = npcData;
loadDeveloperRoomMetadata(npc);
DataProvider etc = DataProviderFactory.getDataProvider(WZFiles.ETC);
Data dnpcData = etc.getData("DeveloperNpc.img");
if (dnpcData != null) {
for (Data data : dnpcData.getChildren()) {
int scriptId = Integer.parseInt(data.getName());
String name = DataTool.getString("name", data, "");
int face = DataTool.getIntConvert("face", data, 20000);
int hair = DataTool.getIntConvert("hair", data, 30000);
int gender = DataTool.getIntConvert("gender", data, 0);
byte skin = (byte) DataTool.getIntConvert("skin", data, 0);
int dir = DataTool.getIntConvert("dir", data, 0);
int mapid = DataTool.getIntConvert("map", data, 0);
int FH = DataTool.getIntConvert("fh", data, 0);
int RX0 = DataTool.getIntConvert("rx0", data, 0);
int RX1 = DataTool.getIntConvert("rx1", data, 0);
int CX = DataTool.getIntConvert("cx", data, 0);
int CY = DataTool.getIntConvert("cy", data, 0);
Map<Short, Integer> equips = new HashMap<>();
for (Data edata : data.getChildByPath("equips").getChildren()) {
short equippos = (short) DataTool.getIntConvert("pos", edata);
int equipid = DataTool.getIntConvert("itemid", edata);
equips.put(equippos, equipid);
}
List<PlayerNPC> dnpcSet = dnpcMaps.get(mapid);
if (dnpcSet == null) {
dnpcSet = new LinkedList<>();
dnpcMaps.put(mapid, dnpcSet);
}
dnpcSet.add(new PlayerNPC(name, scriptId, face, hair, gender, skin, equips, dir, FH, RX0, RX1, CX, CY, runningDeveloperOid));
runningDeveloperOid++;
}
} else {
Data thisData = npc.getData(NpcId.CUSTOM_DEV + ".img");
if (thisData != null) {
byte[] encData = {0x52, 0x6F, 0x6E, 0x61, 0x6E};
String name = new String(encData);
int face = 20104, hair = 30215, gender = 0, skin = 0, dir = 0, mapid = MapId.DEVELOPERS_HQ;
int FH = 4, RX0 = -143, RX1 = -243, CX = -193, CY = 117, scriptId = NpcId.CUSTOM_DEV;
Map<Short, Integer> equips = new HashMap<>();
equips.put((short) -1, ItemId.GREEN_HEADBAND);
equips.put((short) -11, ItemId.TIMELESS_NIBLEHEIM);
equips.put((short) -8, ItemId.BLUE_KORBEN);
equips.put((short) -6, ItemId.MITHRIL_PLATINE_PANTS);
equips.put((short) -7, ItemId.BLUE_CARZEN_BOOTS);
equips.put((short) -5, ItemId.MITHRIL_PLATINE);
List<PlayerNPC> dnpcSet = dnpcMaps.get(mapid);
if (dnpcSet == null) {
dnpcSet = new LinkedList<>();
dnpcMaps.put(mapid, dnpcSet);
}
dnpcSet.add(new PlayerNPC(name, scriptId, face, hair, gender, (byte) skin, equips, dir, FH, RX0, RX1, CX, CY, runningDeveloperOid));
runningDeveloperOid++;
}
}
}
public synchronized static List<PlayerNPC> getDeveloperNpcsFromMapid(int mapid) {
return dnpcMaps.get(mapid);
}
}

View File

@@ -28,7 +28,10 @@ import provider.DataProviderFactory;
import provider.DataTool;
import provider.wz.WZFiles;
import scripting.event.EventInstanceManager;
import server.life.*;
import server.life.AbstractLoadedLife;
import server.life.LifeFactory;
import server.life.Monster;
import server.life.PlayerNPC;
import server.partyquest.GuardianSpawnPoint;
import tools.DatabaseConnection;
import tools.StringUtil;
@@ -249,13 +252,6 @@ public class MapFactory {
} catch (SQLException e) {
e.printStackTrace();
}
List<PlayerNPC> dnpcs = PlayerNPCFactory.getDeveloperNpcsFromMapid(mapid);
if (dnpcs != null) {
for (PlayerNPC dnpc : dnpcs) {
map.addPlayerNPCMapObject(dnpc);
}
}
}
loadLifeFromWz(map, mapData);