Switch to Maven file structure

This commit is contained in:
P0nk
2021-03-30 21:07:35 +02:00
parent 4acc5675d6
commit 813643036b
817 changed files with 16 additions and 0 deletions

View File

@@ -0,0 +1,420 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package server.expeditions;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ScheduledFuture;
import net.server.PlayerStorage;
import net.server.Server;
import server.TimerManager;
import server.life.MapleMonster;
import server.maps.MapleMap;
import tools.LogHelper;
import tools.MaplePacketCreator;
import client.MapleCharacter;
import java.util.Iterator;
import java.util.Properties;
import net.server.audit.locks.MonitoredLockType;
import net.server.audit.locks.MonitoredReentrantLock;
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
import net.server.channel.Channel;
/**
*
* @author Alan (SharpAceX)
*/
public class MapleExpedition {
private static final int [] EXPEDITION_BOSSES = {
8800000,// - Zakum's first body
8800001,// - Zakum's second body
8800002,// - Zakum's third body
8800003,// - Zakum's Arm 1
8800004,// - Zakum's Arm 2
8800005,// - Zakum's Arm 3
8800006,// - Zakum's Arm 4
8800007,// - Zakum's Arm 5
8800008,// - Zakum's Arm 6
8800009,// - Zakum's Arm 7
8800010,// - Zakum's Arm 8
8810000,// - Horntail's Left Head
8810001,// - Horntail's Right Head
8810002,// - Horntail's Head A
8810003,// - Horntail's Head B
8810004,// - Horntail's Head C
8810005,// - Horntail's Left Hand
8810006,// - Horntail's Right Hand
8810007,// - Horntail's Wings
8810008,// - Horntail's Legs
8810009,// - Horntail's Tails
9420546,// - Scarlion Boss
9420547,// - Scarlion Boss
9420548,// - Angry Scarlion Boss
9420549,// - Furious Scarlion Boss
9420541,// - Targa
9420542,// - Targa
9420543,// - Angry Targa
9420544,// - Furious Targa
};
private MapleCharacter leader;
private MapleExpeditionType type;
private boolean registering;
private MapleMap startMap;
private List<String> bossLogs;
private ScheduledFuture<?> schedule;
private Map<Integer, String> members = new ConcurrentHashMap<>();
private List<Integer> banned = new CopyOnWriteArrayList<>();
private long startTime;
private Properties props = new Properties();
private boolean silent;
private int minSize, maxSize;
private MonitoredReentrantLock pL = MonitoredReentrantLockFactory.createLock(MonitoredLockType.EIM_PARTY, true);
public MapleExpedition(MapleCharacter player, MapleExpeditionType met, boolean sil, int minPlayers, int maxPlayers) {
leader = player;
members.put(player.getId(), player.getName());
startMap = player.getMap();
type = met;
silent = sil;
minSize = (minPlayers != 0) ? minPlayers : type.getMinSize();
maxSize = (maxPlayers != 0) ? maxPlayers : type.getMaxSize();
bossLogs = new CopyOnWriteArrayList<>();
}
public int getMinSize() {
return minSize;
}
public int getMaxSize() {
return maxSize;
}
public void beginRegistration() {
registering = true;
leader.announce(MaplePacketCreator.getClock(type.getRegistrationTime() * 60));
if (!silent) {
startMap.broadcastMessage(leader, MaplePacketCreator.serverNotice(6, "[Expedition] " + leader.getName() + " has been declared the expedition captain. Please register for the expedition."), false);
leader.announce(MaplePacketCreator.serverNotice(6, "[Expedition] You have become the expedition captain. Gather enough people for your team then talk to the NPC to start."));
}
scheduleRegistrationEnd();
}
private void scheduleRegistrationEnd() {
final MapleExpedition exped = this;
startTime = System.currentTimeMillis() + type.getRegistrationTime() * 60 * 1000;
schedule = TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
if (registering){
exped.removeChannelExpedition(startMap.getChannelServer());
if (!silent) startMap.broadcastMessage(MaplePacketCreator.serverNotice(6, "[Expedition] The time limit has been reached. Expedition has been disbanded."));
dispose(false);
}
}
}, type.getRegistrationTime() * 60 * 1000);
}
public void dispose(boolean log){
broadcastExped(MaplePacketCreator.removeClock());
if (schedule != null){
schedule.cancel(false);
}
if (log && !registering){
LogHelper.logExpedition(this);
}
}
public void finishRegistration() {
registering = false;
}
public void start(){
finishRegistration();
registerExpeditionAttempt();
broadcastExped(MaplePacketCreator.removeClock());
if (!silent) broadcastExped(MaplePacketCreator.serverNotice(6, "[Expedition] The expedition has started! Good luck, brave heroes!"));
startTime = System.currentTimeMillis();
Server.getInstance().broadcastGMMessage(startMap.getWorld(), MaplePacketCreator.serverNotice(6, "[Expedition] " + type.toString() + " Expedition started with leader: " + leader.getName()));
}
public String addMember(MapleCharacter player) {
if (!registering){
return "Sorry, this expedition is already underway. Registration is closed!";
}
if (banned.contains(player.getId())){
return "Sorry, you've been banned from this expedition by #b" + leader.getName() + "#k.";
}
if (members.size() >= this.getMaxSize()){ //Would be a miracle if anybody ever saw this
return "Sorry, this expedition is full!";
}
int channel = this.getRecruitingMap().getChannelServer().getId();
if (!MapleExpeditionBossLog.attemptBoss(player.getId(), channel, this, false)) { // thanks Conrad, Cato for noticing some expeditions have entry limit
return "Sorry, you've already reached the quota of attempts for this expedition! Try again another day...";
}
members.put(player.getId(), player.getName());
player.announce(MaplePacketCreator.getClock((int)(startTime - System.currentTimeMillis()) / 1000));
if (!silent) broadcastExped(MaplePacketCreator.serverNotice(6, "[Expedition] " + player.getName() + " has joined the expedition!"));
return "You have registered for the expedition successfully!";
}
public int addMemberInt(MapleCharacter player) {
if (!registering) {
return 1; //"Sorry, this expedition is already underway. Registration is closed!";
}
if (banned.contains(player.getId())) {
return 2; //"Sorry, you've been banned from this expedition by #b" + leader.getName() + "#k.";
}
if (members.size() >= this.getMaxSize()) { //Would be a miracle if anybody ever saw this
return 3; //"Sorry, this expedition is full!";
}
members.put(player.getId(), player.getName());
player.announce(MaplePacketCreator.getClock((int) (startTime - System.currentTimeMillis()) / 1000));
if (!silent) broadcastExped(MaplePacketCreator.serverNotice(6, "[Expedition] " + player.getName() + " has joined the expedition!"));
return 0; //"You have registered for the expedition successfully!";
}
private void registerExpeditionAttempt(){
int channel = this.getRecruitingMap().getChannelServer().getId();
for (MapleCharacter chr : getActiveMembers()){
MapleExpeditionBossLog.attemptBoss(chr.getId(), channel, this, true);
}
}
private void broadcastExped(byte[] packet){
for (MapleCharacter chr : getActiveMembers()){
chr.announce(packet);
}
}
public boolean removeMember(MapleCharacter chr) {
if(members.remove(chr.getId()) != null) {
chr.announce(MaplePacketCreator.removeClock());
if (!silent) {
broadcastExped(MaplePacketCreator.serverNotice(6, "[Expedition] " + chr.getName() + " has left the expedition."));
chr.dropMessage(6, "[Expedition] You have left this expedition.");
}
return true;
}
return false;
}
public void ban(Entry<Integer, String> chr) {
int cid = chr.getKey();
if (!banned.contains(cid)) {
banned.add(cid);
members.remove(cid);
if (!silent) broadcastExped(MaplePacketCreator.serverNotice(6, "[Expedition] " + chr.getValue() + " has been banned from the expedition."));
MapleCharacter player = startMap.getWorldServer().getPlayerStorage().getCharacterById(cid);
if (player != null && player.isLoggedinWorld()) {
player.announce(MaplePacketCreator.removeClock());
if (!silent) player.dropMessage(6, "[Expedition] You have been banned from this expedition.");
if (MapleExpeditionType.ARIANT.equals(type) || MapleExpeditionType.ARIANT1.equals(type) || MapleExpeditionType.ARIANT2.equals(type)) {
player.changeMap(980010000);
}
}
}
}
public void monsterKilled(MapleCharacter chr, MapleMonster mob) {
for (int i = 0; i < EXPEDITION_BOSSES.length; i++) {
if (mob.getId() == EXPEDITION_BOSSES[i]) { //If the monster killed was a boss
String timeStamp = new SimpleDateFormat("HH:mm:ss").format(new Date());
bossLogs.add(">" + mob.getName() + " was killed after " + LogHelper.getTimeString(startTime) + " - " + timeStamp + "\r\n");
return;
}
}
}
public void setProperty(String key, String value) {
pL.lock();
try {
props.setProperty(key, value);
} finally {
pL.unlock();
}
}
public String getProperty(String key) {
pL.lock();
try {
return props.getProperty(key);
} finally {
pL.unlock();
}
}
public MapleExpeditionType getType() {
return type;
}
public List<MapleCharacter> getActiveMembers() { // thanks MedicOP for figuring out an issue with broadcasting packets to offline members
PlayerStorage ps = startMap.getWorldServer().getPlayerStorage();
List<MapleCharacter> activeMembers = new LinkedList<>();
for (Integer chrid : getMembers().keySet()){
MapleCharacter chr = ps.getCharacterById(chrid);
if (chr != null && chr.isLoggedinWorld()) {
activeMembers.add(chr);
}
}
return activeMembers;
}
public Map<Integer, String> getMembers() {
return new HashMap<>(members);
}
public List<Entry<Integer, String>> getMemberList() {
List<Entry<Integer, String>> memberList = new LinkedList<>();
Entry<Integer, String> leaderEntry = null;
for (Entry<Integer, String> e : getMembers().entrySet()) {
if (!isLeader(e.getKey())) {
memberList.add(e);
} else {
leaderEntry = e;
}
}
if (leaderEntry != null) {
memberList.add(0, leaderEntry);
}
return memberList;
}
public final boolean isExpeditionTeamTogether() {
List<MapleCharacter> chars = getActiveMembers();
if(chars.size() <= 1) return true;
Iterator<MapleCharacter> iterator = chars.iterator();
MapleCharacter mc = iterator.next();
int mapId = mc.getMapId();
for (; iterator.hasNext();) {
mc = iterator.next();
if(mc.getMapId() != mapId) return false;
}
return true;
}
public final void warpExpeditionTeam(int warpFrom, int warpTo) {
List<MapleCharacter> players = getActiveMembers();
for (MapleCharacter chr : players) {
if(chr.getMapId() == warpFrom)
chr.changeMap(warpTo);
}
}
public final void warpExpeditionTeam(int warpTo) {
List<MapleCharacter> players = getActiveMembers();
for (MapleCharacter chr : players) {
chr.changeMap(warpTo);
}
}
public final void warpExpeditionTeamToMapSpawnPoint(int warpFrom, int warpTo, int toSp) {
List<MapleCharacter> players = getActiveMembers();
for (MapleCharacter chr : players) {
if(chr.getMapId() == warpFrom)
chr.changeMap(warpTo, toSp);
}
}
public final void warpExpeditionTeamToMapSpawnPoint(int warpTo, int toSp) {
List<MapleCharacter> players = getActiveMembers();
for (MapleCharacter chr : players) {
chr.changeMap(warpTo, toSp);
}
}
public final boolean addChannelExpedition(Channel ch) {
return ch.addExpedition(this);
}
public final void removeChannelExpedition(Channel ch) {
ch.removeExpedition(this);
}
public MapleCharacter getLeader(){
return leader;
}
public MapleMap getRecruitingMap() {
return startMap;
}
public boolean contains(MapleCharacter player) {
return members.containsKey(player.getId()) || isLeader(player);
}
public boolean isLeader(MapleCharacter player) {
return isLeader(player.getId());
}
public boolean isLeader(int playerid) {
return leader.getId() == playerid;
}
public boolean isRegistering(){
return registering;
}
public boolean isInProgress(){
return !registering;
}
public long getStartTime(){
return startTime;
}
public List<String> getBossLogs(){
return bossLogs;
}
}

View File

@@ -0,0 +1,208 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package server.expeditions;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.List;
import config.YamlConfig;
import tools.DatabaseConnection;
import tools.Pair;
/**
*
* @author Conrad
* @author Ronan
*/
public class MapleExpeditionBossLog {
public enum BossLogEntry {
ZAKUM(2, 1, false),
HORNTAIL(2, 1, false),
PINKBEAN(1, 1, false),
SCARGA(1, 1, false),
PAPULATUS(2, 1, false);
private int entries;
private int timeLength;
private int minChannel, maxChannel;
private boolean week;
private BossLogEntry(int entries, int timeLength, boolean week) {
this(entries, 0, Integer.MAX_VALUE, timeLength, week);
}
private BossLogEntry(int entries, int minChannel, int maxChannel, int timeLength, boolean week) {
this.entries = entries;
this.minChannel = minChannel;
this.maxChannel = maxChannel;
this.timeLength = timeLength;
this.week = week;
}
private static List<Pair<Timestamp, BossLogEntry>> getBossLogResetTimestamps(Calendar timeNow, boolean week) {
List<Pair<Timestamp, BossLogEntry>> resetTimestamps = new LinkedList<>();
Timestamp ts = new Timestamp(timeNow.getTime().getTime()); // reset all table entries actually, thanks Conrad
for (BossLogEntry b : BossLogEntry.values()) {
if (b.week == week) {
resetTimestamps.add(new Pair<>(ts, b));
}
}
return resetTimestamps;
}
private static BossLogEntry getBossEntryByName(String name) {
for (BossLogEntry b : BossLogEntry.values()) {
if (name.contentEquals(b.name())) {
return b;
}
}
return null;
}
}
public static void resetBossLogTable() {
/*
Boss logs resets 12am, weekly thursday 12AM - thanks Smitty Werbenjagermanjensen (superadlez) - https://www.reddit.com/r/Maplestory/comments/61tiup/about_reset_time/
*/
Calendar thursday = Calendar.getInstance();
thursday.set(Calendar.DAY_OF_WEEK, Calendar.THURSDAY);
thursday.set(Calendar.HOUR, 0);
thursday.set(Calendar.MINUTE, 0);
thursday.set(Calendar.SECOND, 0);
Calendar now = Calendar.getInstance();
long weekLength = 7 * 24 * 60 * 60 * 1000;
long halfDayLength = 12 * 60 * 60 * 1000;
long deltaTime = now.getTime().getTime() - thursday.getTime().getTime(); // 2x time: get Date into millis
deltaTime += halfDayLength;
deltaTime %= weekLength;
deltaTime -= halfDayLength;
if (deltaTime < halfDayLength) {
MapleExpeditionBossLog.resetBossLogTable(true, thursday);
}
now.set(Calendar.HOUR, 0);
now.set(Calendar.MINUTE, 0);
now.set(Calendar.SECOND, 0);
MapleExpeditionBossLog.resetBossLogTable(false, now);
}
private static void resetBossLogTable(boolean week, Calendar c) {
List<Pair<Timestamp, BossLogEntry>> resetTimestamps = BossLogEntry.getBossLogResetTimestamps(c, week);
try {
Connection con = DatabaseConnection.getConnection();
for (Pair<Timestamp, BossLogEntry> p : resetTimestamps) {
PreparedStatement ps = con.prepareStatement("DELETE FROM " + getBossLogTable(week) + " WHERE attempttime <= ? AND bosstype LIKE ?");
ps.setTimestamp(1, p.getLeft());
ps.setString(2, p.getRight().name());
ps.executeUpdate();
ps.close();
}
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
private static String getBossLogTable(boolean week) {
return week ? "bosslog_weekly" : "bosslog_daily";
}
private static int countPlayerEntries(int cid, BossLogEntry boss) {
int ret_count = 0;
try {
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps;
ps = con.prepareStatement("SELECT COUNT(*) FROM " + getBossLogTable(boss.week) + " WHERE characterid = ? AND bosstype LIKE ?");
ps.setInt(1, cid);
ps.setString(2, boss.name());
ResultSet rs = ps.executeQuery();
if (rs.next()) {
ret_count = rs.getInt(1);
} else {
ret_count = -1;
}
rs.close();
ps.close();
con.close();
return ret_count;
} catch (SQLException e) {
e.printStackTrace();
return -1;
}
}
private static void insertPlayerEntry(int cid, BossLogEntry boss) {
try {
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("INSERT INTO " + getBossLogTable(boss.week) + " (characterid, bosstype) VALUES (?,?)");
ps.setInt(1, cid);
ps.setString(2, boss.name());
ps.executeUpdate();
ps.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static boolean attemptBoss(int cid, int channel, MapleExpedition exped, boolean log) {
if (!YamlConfig.config.server.USE_ENABLE_DAILY_EXPEDITIONS) {
return true;
}
BossLogEntry boss = BossLogEntry.getBossEntryByName(exped.getType().name());
if (boss == null) {
return true;
}
if (channel < boss.minChannel || channel > boss.maxChannel) {
return false;
}
if (countPlayerEntries(cid, boss) >= boss.entries) {
return false;
}
if (log) {
insertPlayerEntry(cid, boss);
}
return true;
}
}

View File

@@ -0,0 +1,81 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package server.expeditions;
import config.YamlConfig;
/**
*
* @author Alan (SharpAceX)
*/
public enum MapleExpeditionType {
BALROG_EASY(3, 30, 50, 255, 5),
BALROG_NORMAL(6, 30, 50, 255, 5),
SCARGA(6, 30, 100, 255, 5),
SHOWA(3, 30, 100, 255, 5),
ZAKUM(6, 30, 50, 255, 5),
HORNTAIL(6, 30, 100, 255, 5),
CHAOS_ZAKUM(6, 30, 120, 255, 5),
CHAOS_HORNTAIL(6, 30, 120, 255, 5),
ARIANT(2, 7, 20, 30, 5),
ARIANT1(2, 7, 20, 30, 5),
ARIANT2(2, 7, 20, 30, 5),
PINKBEAN(6, 30, 120, 255, 5),
CWKPQ(6, 30, 90, 255, 5); // CWKPQ min-level 90, found thanks to Cato
private int minSize;
private int maxSize;
private int minLevel;
private int maxLevel;
private int registrationTime;
private MapleExpeditionType(int minSize, int maxSize, int minLevel, int maxLevel, int minutes) {
this.minSize = minSize;
this.maxSize = maxSize;
this.minLevel = minLevel;
this.maxLevel = maxLevel;
this.registrationTime = minutes;
}
public int getMinSize() {
return !YamlConfig.config.server.USE_ENABLE_SOLO_EXPEDITIONS ? minSize : 1;
}
public int getMaxSize() {
return maxSize;
}
public int getMinLevel() {
return minLevel;
}
public int getMaxLevel() {
return maxLevel;
}
public int getRegistrationTime(){
return registrationTime;
}
}