svn -> git Migration

This commit is contained in:
KimLS
2013-02-16 16:14:39 -08:00
parent 88c9715fb0
commit da7347f76f
1174 changed files with 445622 additions and 0 deletions
+438
View File
@@ -0,0 +1,438 @@
#include "../common/debug.h"
#include "../common/servertalk.h"
#include "../common/extprofile.h"
#include "../common/rulesys.h"
#include "../common/MiscFunctions.h"
#include "Adventure.h"
#include "AdventureManager.h"
#include "worlddb.h"
#include "zonelist.h"
#include "clientlist.h"
#include "cliententry.h"
extern ZSList zoneserver_list;
extern ClientList client_list;
extern AdventureManager adventure_manager;
Adventure::Adventure(AdventureTemplate *t)
{
adventure_template = t;
status = AS_WaitingForZoneIn;
current_timer = new Timer(1000 * t->zone_in_time);
count = 0;
assassination_count = 0;
instance_id = 0;
}
Adventure::Adventure(AdventureTemplate *t, int count, int assassination_count, AdventureStatus status, uint16 instance_id, uint32 time_left)
{
adventure_template = t;
this->count = count;
this->assassination_count = assassination_count;
this->status = status;
this->instance_id = instance_id;
if(status == AS_Finished)
{
database.SetInstanceDuration(instance_id, time_left);
}
else
{
database.SetInstanceDuration(instance_id, time_left + 60);
}
current_timer = new Timer(1000 * time_left);
}
Adventure::~Adventure()
{
safe_delete(current_timer);
}
void Adventure::AddPlayer(string character_name, bool add_client_to_instance)
{
if(!PlayerExists(character_name))
{
int client_id = database.GetCharacterID(character_name.c_str());
if(add_client_to_instance)
{
database.AddClientToInstance(instance_id, client_id);
}
players.push_back(character_name);
}
}
void Adventure::RemovePlayer(string character_name)
{
list<string>::iterator iter = players.begin();
while(iter != players.end())
{
if((*iter).compare(character_name) == 0)
{
database.RemoveClientFromInstance(instance_id, database.GetCharacterID(character_name.c_str()));
players.erase(iter);
return;
}
iter++;
}
}
bool Adventure::PlayerExists(string character_name)
{
list<string>::iterator iter = players.begin();
while(iter != players.end())
{
if(character_name.compare((*iter)) == 0)
{
return true;
}
iter++;
}
return false;
}
bool Adventure::IsActive()
{
return (status != AS_Finished);
}
bool Adventure::Process()
{
if(players.size() == 0)
{
return false;
}
if(current_timer->Check())
{
//Timer wore out while waiting for zone in.
if(status == AS_WaitingForZoneIn)
{
MoveCorpsesToGraveyard();
database.DeleteInstance(instance_id);
return false;
}
else if(status == AS_WaitingForPrimaryEndTime)
{
//Do partial failure: send a message to the clients that they can only get a certain amount of points.
SendAdventureMessage(13, "You failed to complete your adventure in time. Complete your adventure goal within 30 minutes to "
"receive a lesser reward. This adventure will end in 30 minutes and your party will be ejected from the dungeon.");
SetStatus(AS_WaitingForSecondaryEndTime);
}
else
{
if(count < GetTemplate()->type_count)
{
Finished(AWS_Lose);
}
MoveCorpsesToGraveyard();
database.DeleteInstance(instance_id);
return false;
}
}
return true;
}
bool Adventure::CreateInstance()
{
uint32 zone_id = database.GetZoneID(adventure_template->zone);
if(!zone_id)
{
return false;
}
uint16 id = 0;
if(!database.GetUnusedInstanceID(id))
{
return false;
}
if(!database.CreateInstance(id, zone_id, adventure_template->zone_version, adventure_template->zone_in_time + 60))
{
return false;
}
instance_id = id;
return true;
}
void Adventure::SetStatus(AdventureStatus new_status)
{
if(new_status == AS_WaitingForPrimaryEndTime)
{
status = new_status;
safe_delete(current_timer);
current_timer = new Timer(adventure_template->duration * 1000);
database.SetInstanceDuration(instance_id, adventure_template->duration + 60);
ServerPacket *pack = new ServerPacket(ServerOP_InstanceUpdateTime, sizeof(ServerInstanceUpdateTime_Struct));
ServerInstanceUpdateTime_Struct *ut = (ServerInstanceUpdateTime_Struct*)pack->pBuffer;
ut->instance_id = instance_id;
ut->new_duration = adventure_template->duration + 60;
pack->Deflate();
zoneserver_list.SendPacket(0, instance_id, pack);
safe_delete(pack);
}
else if(new_status == AS_WaitingForSecondaryEndTime)
{
status = new_status;
safe_delete(current_timer);
current_timer = new Timer(1800000);
database.SetInstanceDuration(instance_id, 1860);
ServerPacket *pack = new ServerPacket(ServerOP_InstanceUpdateTime, sizeof(ServerInstanceUpdateTime_Struct));
ServerInstanceUpdateTime_Struct *ut = (ServerInstanceUpdateTime_Struct*)pack->pBuffer;
ut->instance_id = instance_id;
ut->new_duration = 1860;
pack->Deflate();
zoneserver_list.SendPacket(0, instance_id, pack);
safe_delete(pack);
}
else if(new_status == AS_Finished)
{
status = new_status;
safe_delete(current_timer);
current_timer = new Timer(1800000);
database.SetInstanceDuration(instance_id, 1800);
ServerPacket *pack = new ServerPacket(ServerOP_InstanceUpdateTime, sizeof(ServerInstanceUpdateTime_Struct));
ServerInstanceUpdateTime_Struct *ut = (ServerInstanceUpdateTime_Struct*)pack->pBuffer;
ut->instance_id = instance_id;
ut->new_duration = 1860;
pack->Deflate();
zoneserver_list.SendPacket(0, instance_id, pack);
safe_delete(pack);
}
else
{
return;
}
list<string>::iterator iter = players.begin();
while(iter != players.end())
{
adventure_manager.GetAdventureData((*iter).c_str());
iter++;
}
}
void Adventure::SendAdventureMessage(uint32 type, const char *msg)
{
ServerPacket *pack = new ServerPacket(ServerOP_EmoteMessage, sizeof(ServerEmoteMessage_Struct) + strlen(msg) + 1);
ServerEmoteMessage_Struct *sms = (ServerEmoteMessage_Struct*)pack->pBuffer;
sms->type = type;
strcpy(sms->message, msg);
list<string>::iterator iter = players.begin();
while(iter != players.end())
{
ClientListEntry *current = client_list.FindCharacter((*iter).c_str());
if(current)
{
strcpy(sms->to, (*iter).c_str());
zoneserver_list.SendPacket(current->zone(), current->instance(), pack);
}
iter++;
}
delete pack;
}
void Adventure::IncrementCount()
{
const AdventureTemplate *at = GetTemplate();
if(count >= at->type_count)
{
return;
}
if(status == AS_WaitingForPrimaryEndTime)
{
count++;
if(count == at->type_count)
{
SetStatus(AS_Finished);
Finished(AWS_Win);
}
}
else if(status == AS_WaitingForSecondaryEndTime)
{
count++;
if(count == at->type_count)
{
SetStatus(AS_Finished);
Finished(AWS_SecondPlace);
}
}
}
void Adventure::IncrementAssassinationCount()
{
if(count >= RuleI(Adventure, NumberKillsForBossSpawn))
{
return;
}
assassination_count++;
}
void Adventure::Finished(AdventureWinStatus ws)
{
list<string>::iterator iter = players.begin();
while(iter != players.end())
{
ClientListEntry *current = client_list.FindCharacter((*iter).c_str());
if(current)
{
if(current->Online() == CLE_Status_InZone)
{
//We can send our packets only.
ServerPacket *pack = new ServerPacket(ServerOP_AdventureFinish, sizeof(ServerAdventureFinish_Struct));
ServerAdventureFinish_Struct *af = (ServerAdventureFinish_Struct*)pack->pBuffer;
strcpy(af->player, (*iter).c_str());
af->theme = GetTemplate()->theme;
if(ws == AWS_Win)
{
af->win = true;
af->points = GetTemplate()->win_points;
}
else if(ws == AWS_SecondPlace)
{
af->win = true;
af->points = GetTemplate()->lose_points;
}
else
{
af->win = false;
af->points = 0;
}
pack->Deflate();
zoneserver_list.SendPacket(current->zone(), current->instance(), pack);
database.UpdateAdventureStatsEntry(database.GetCharacterID((*iter).c_str()), GetTemplate()->theme, (ws != AWS_Lose) ? true : false);
delete pack;
}
else
{
AdventureFinishEvent afe;
afe.name = (*iter);
if(ws == AWS_Win)
{
afe.theme = GetTemplate()->theme;
afe.points = GetTemplate()->win_points;
afe.win = true;
}
else if(ws == AWS_SecondPlace)
{
afe.theme = GetTemplate()->theme;
afe.points = GetTemplate()->lose_points;
afe.win = true;
}
else
{
afe.win = false;
afe.points = 0;
}
adventure_manager.AddFinishedEvent(afe);
database.UpdateAdventureStatsEntry(database.GetCharacterID((*iter).c_str()), GetTemplate()->theme, (ws != AWS_Lose) ? true : false);
}
}
else
{
AdventureFinishEvent afe;
afe.name = (*iter);
if(ws == AWS_Win)
{
afe.theme = GetTemplate()->theme;
afe.points = GetTemplate()->win_points;
afe.win = true;
}
else if(ws == AWS_SecondPlace)
{
afe.theme = GetTemplate()->theme;
afe.points = GetTemplate()->lose_points;
afe.win = true;
}
else
{
afe.win = false;
afe.points = 0;
}
adventure_manager.AddFinishedEvent(afe);
database.UpdateAdventureStatsEntry(database.GetCharacterID((*iter).c_str()), GetTemplate()->theme, (ws != AWS_Lose) ? true : false);
}
iter++;
}
adventure_manager.GetAdventureData(this);
}
void Adventure::MoveCorpsesToGraveyard()
{
if(GetTemplate()->graveyard_zone_id == 0)
{
return;
}
list<uint32> dbid_list;
list<uint32> charid_list;
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if(database.RunQuery(query,MakeAnyLenString(&query,"SELECT id, charid FROM player_corpses WHERE instanceid=%d", GetInstanceID()), errbuf, &result))
{
while((row = mysql_fetch_row(result)))
{
dbid_list.push_back(atoi(row[0]));
charid_list.push_back(atoi(row[1]));
}
mysql_free_result(result);
safe_delete_array(query);
}
else
{
LogFile->write(EQEMuLog::Error, "Error in AdventureManager:::MoveCorpsesToGraveyard: %s (%s)", query, errbuf);
safe_delete_array(query);
}
list<uint32>::iterator iter = dbid_list.begin();
while(iter != dbid_list.end())
{
float x = GetTemplate()->graveyard_x + MakeRandomFloat(-GetTemplate()->graveyard_radius, GetTemplate()->graveyard_radius);
float y = GetTemplate()->graveyard_y + MakeRandomFloat(-GetTemplate()->graveyard_radius, GetTemplate()->graveyard_radius);
float z = GetTemplate()->graveyard_z;
if(database.RunQuery(query,MakeAnyLenString(&query, "UPDATE player_corpses SET zoneid=%d, instanceid=0, x=%f, y=%f, z=%f WHERE instanceid=%d",
GetTemplate()->graveyard_zone_id, x, y, z, GetInstanceID()), errbuf))
{
safe_delete_array(query);
}
else
{
LogFile->write(EQEMuLog::Error, "Error in AdventureManager:::MoveCorpsesToGraveyard: %s (%s)", query, errbuf);
safe_delete_array(query);
}
iter++;
}
iter = dbid_list.begin();
list<uint32>::iterator c_iter = charid_list.begin();
while(iter != dbid_list.end())
{
ServerPacket* pack = new ServerPacket(ServerOP_DepopAllPlayersCorpses, sizeof(ServerDepopAllPlayersCorpses_Struct));
ServerDepopAllPlayersCorpses_Struct *dpc = (ServerDepopAllPlayersCorpses_Struct*)pack->pBuffer;
dpc->CharacterID = (*c_iter);
dpc->InstanceID = 0;
dpc->ZoneID = GetTemplate()->graveyard_zone_id;
zoneserver_list.SendPacket(0, GetInstanceID(), pack);
delete pack;
pack = new ServerPacket(ServerOP_SpawnPlayerCorpse, sizeof(SpawnPlayerCorpse_Struct));
SpawnPlayerCorpse_Struct* spc = (SpawnPlayerCorpse_Struct*)pack->pBuffer;
spc->player_corpse_id = (*iter);
spc->zone_id = GetTemplate()->graveyard_zone_id;
zoneserver_list.SendPacket(spc->zone_id, 0, pack);
delete pack;
iter++;
c_iter++;
}
}
+103
View File
@@ -0,0 +1,103 @@
#ifndef ADVENTURE_H
#define ADVENTURE_H
#include "../common/debug.h"
#include "../common/types.h"
#include "../common/timer.h"
#include "AdventureTemplate.h"
#include <list>
#include <string>
#include <stdlib.h>
using namespace std;
enum AdventureStatus
{
AS_WaitingForZoneIn,
AS_WaitingForPrimaryEndTime,
AS_WaitingForSecondaryEndTime,
AS_Finished,
};
enum AdventureWinStatus
{
AWS_Win,
AWS_SecondPlace,
AWS_Lose
};
struct AdventureZones
{
string zone;
int version;
};
struct AdventureZoneIn
{
int zone_id;
int door_id;
};
struct AdventureFinishEvent
{
string name;
bool win;
int points;
int theme;
};
struct LeaderboardInfo
{
string name;
uint32 wins;
uint32 guk_wins;
uint32 mir_wins;
uint32 mmc_wins;
uint32 ruj_wins;
uint32 tak_wins;
uint32 losses;
uint32 guk_losses;
uint32 mir_losses;
uint32 mmc_losses;
uint32 ruj_losses;
uint32 tak_losses;
};
class Adventure
{
public:
Adventure(AdventureTemplate *t);
Adventure(AdventureTemplate *t, int count, int assassination_count, AdventureStatus status, uint16 instance_id, uint32 time_left);
~Adventure();
bool Process();
bool IsActive();
void AddPlayer(string character_name, bool add_client_to_instance = true);
void RemovePlayer(string character_name);
bool PlayerExists(string character_name);
bool CreateInstance();
void IncrementCount();
void IncrementAssassinationCount();
void Finished(AdventureWinStatus ws);
void SetStatus(AdventureStatus new_status);
void SendAdventureMessage(uint32 type, const char *msg);
void MoveCorpsesToGraveyard();
uint16 GetInstanceID() const { return instance_id; }
const AdventureTemplate *GetTemplate() const { return adventure_template; }
AdventureStatus GetStatus() const { return status; }
list<string> GetPlayers() { return players; }
int GetCount() const { return count; }
int GetAssassinationCount() const { return assassination_count; }
uint32 GetRemainingTime() const { if(current_timer) { return (current_timer->GetRemainingTime() / 1000); } else { return 0; } }
protected:
int id;
int count;
int assassination_count;
AdventureTemplate *adventure_template;
AdventureStatus status;
list<string> players;
Timer *current_timer;
int instance_id;
};
#endif
File diff suppressed because it is too large Load Diff
+95
View File
@@ -0,0 +1,95 @@
#ifndef ADVENTURE_MANAGER_H
#define ADVENTURE_MANAGER_H
#include "../common/debug.h"
#include "../common/types.h"
#include "../common/timer.h"
#include "Adventure.h"
#include "AdventureTemplate.h"
#include <map>
#include <list>
using namespace std;
class AdventureManager
{
public:
AdventureManager();
~AdventureManager();
void Process();
bool LoadAdventureTemplates();
bool LoadAdventureEntries();
void LoadLeaderboardInfo();
void CalculateAdventureRequestReply(const char *data);
void PlayerClickedDoor(const char *player, int zone_id, int door_id);
void TryAdventureCreate(const char *data);
void GetAdventureData(Adventure *adv);
void GetAdventureData(const char *name);
void LeaveAdventure(const char *name);
void IncrementCount(uint16 instance_id);
void IncrementAssassinationCount(uint16 instance_id);
void DoLeaderboardRequest(const char* player, uint8 type);
void SendAdventureFinish(AdventureFinishEvent fe);
void AddFinishedEvent(AdventureFinishEvent fe) { finished_list.push_back(fe); Save(); }
bool PopFinishedEvent(const char *name, AdventureFinishEvent &fe);
void Save();
void Load();
Adventure **GetFinishedAdventures(const char *player, int &count);
Adventure *GetActiveAdventure(const char *player);
AdventureTemplate *GetAdventureTemplate(int theme, int id);
AdventureTemplate *GetAdventureTemplate(int id);
void GetZoneData(uint16 instance_id);
protected:
bool IsInExcludedZoneList(list<AdventureZones> excluded_zones, string zone_name, int version);
bool IsInExcludedZoneInList(list<AdventureZoneIn> excluded_zone_ins, int zone_id, int door_object);
void DoLeaderboardRequestWins(const char* player);
void DoLeaderboardRequestPercentage(const char* player);
void DoLeaderboardRequestWinsGuk(const char* player);
void DoLeaderboardRequestPercentageGuk(const char* player);
void DoLeaderboardRequestWinsMir(const char* player);
void DoLeaderboardRequestPercentageMir(const char* player);
void DoLeaderboardRequestWinsMmc(const char* player);
void DoLeaderboardRequestPercentageMmc(const char* player);
void DoLeaderboardRequestWinsRuj(const char* player);
void DoLeaderboardRequestPercentageRuj(const char* player);
void DoLeaderboardRequestWinsTak(const char* player);
void DoLeaderboardRequestPercentageTak(const char* player);
map<uint32, AdventureTemplate*> adventure_templates;
map<uint32, list<AdventureTemplate*> > adventure_entries;
list<Adventure*> adventure_list;
list<AdventureFinishEvent> finished_list;
list<LeaderboardInfo> leaderboard_info_wins;
list<LeaderboardInfo> leaderboard_info_percentage;
list<LeaderboardInfo> leaderboard_info_wins_guk;
list<LeaderboardInfo> leaderboard_info_percentage_guk;
list<LeaderboardInfo> leaderboard_info_wins_mir;
list<LeaderboardInfo> leaderboard_info_percentage_mir;
list<LeaderboardInfo> leaderboard_info_wins_mmc;
list<LeaderboardInfo> leaderboard_info_percentage_mmc;
list<LeaderboardInfo> leaderboard_info_wins_ruj;
list<LeaderboardInfo> leaderboard_info_percentage_ruj;
list<LeaderboardInfo> leaderboard_info_wins_tak;
list<LeaderboardInfo> leaderboard_info_percentage_tak;
bool leaderboard_sorted_wins;
bool leaderboard_sorted_percentage;
bool leaderboard_sorted_wins_guk;
bool leaderboard_sorted_percentage_guk;
bool leaderboard_sorted_wins_mir;
bool leaderboard_sorted_percentage_mir;
bool leaderboard_sorted_wins_mmc;
bool leaderboard_sorted_percentage_mmc;
bool leaderboard_sorted_wins_ruj;
bool leaderboard_sorted_percentage_ruj;
bool leaderboard_sorted_wins_tak;
bool leaderboard_sorted_percentage_tak;
Timer *process_timer;
Timer *save_timer;
Timer *leaderboard_info_timer;
};
#endif
+47
View File
@@ -0,0 +1,47 @@
#ifndef ADVENTURE_TEMPLATE_H
#define ADVENTURE_TEMPLATE_H
#include "../common/debug.h"
#include "../common/types.h"
#pragma pack(1)
struct AdventureTemplate
{
uint32 id;
char zone[64];
uint32 zone_version;
bool is_hard;
int32 min_level;
int32 max_level;
uint8 type;
uint32 type_data;
uint16 type_count;
float assa_x;
float assa_y;
float assa_z;
float assa_h;
char text[1024];
uint32 duration;
uint32 zone_in_time;
int32 win_points;
int32 lose_points;
uint8 theme;
uint16 zone_in_zone_id;
float zone_in_x;
float zone_in_y;
uint16 zone_in_object_id;
float dest_x;
float dest_y;
float dest_z;
float dest_h;
int graveyard_zone_id;
float graveyard_x;
float graveyard_y;
float graveyard_z;
float graveyard_radius;
};
#pragma pack()
#endif
+91
View File
@@ -0,0 +1,91 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
SET(world_sources
Adventure.cpp
AdventureManager.cpp
client.cpp
cliententry.cpp
clientlist.cpp
CMakeLists.txt
console.cpp
EQLConfig.cpp
EQW.cpp
EQWHTTPHandler.cpp
EQWParser.cpp
HTTPRequest.cpp
LauncherLink.cpp
LauncherList.cpp
lfplist.cpp
LoginServer.cpp
LoginServerList.cpp
net.cpp
perl_EQLConfig.cpp
perl_EQW.cpp
perl_HTTPRequest.cpp
queryserv.cpp
ucs.cpp
wguild_mgr.cpp
world_logsys.cpp
WorldConfig.cpp
worlddb.cpp
zonelist.cpp
zoneserver.cpp
)
SET(world_headers
Adventure.h
AdventureManager.h
AdventureTemplate.h
client.h
cliententry.h
clientlist.h
CMakeLists.txt
console.h
EQLConfig.h
EQW.h
EQWHTTPHandler.h
EQWParser.h
HTTPRequest.h
LauncherLink.h
LauncherList.h
lfplist.h
LoginServer.h
LoginServerList.h
net.h
queryserv.h
SoFCharCreateData.h
ucs.h
wguild_mgr.h
WorldConfig.h
worlddb.h
WorldTCPConnection.h
zonelist.h
zoneserver.h
)
ADD_EXECUTABLE(world ${world_sources} ${world_headers})
ADD_DEFINITIONS(-DWORLD)
TARGET_LINK_LIBRARIES(world Common ${PERL_LIBRARY} debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE})
IF(MSVC)
SET_TARGET_PROPERTIES(world PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF")
TARGET_LINK_LIBRARIES(world "Ws2_32.lib")
ENDIF(MSVC)
IF(MINGW)
TARGET_LINK_LIBRARIES(world "WS2_32")
ENDIF(MINGW)
IF(UNIX)
TARGET_LINK_LIBRARIES(world "dl")
TARGET_LINK_LIBRARIES(world "z")
TARGET_LINK_LIBRARIES(world "m")
TARGET_LINK_LIBRARIES(world "rt")
TARGET_LINK_LIBRARIES(world "pthread")
ADD_DEFINITIONS(-fPIC)
ENDIF(UNIX)
SET(EXECUTABLE_OUTPUT_PATH ../Bin)
+384
View File
@@ -0,0 +1,384 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "EQLConfig.h"
#include "worlddb.h"
#include "LauncherLink.h"
#include "LauncherList.h"
#include "../common/MiscFunctions.h"
#include <cstdlib>
#include <cstring>
extern LauncherList launcher_list;
EQLConfig::EQLConfig(const char *launcher_name)
: m_name(launcher_name)
{
LoadSettings();
}
void EQLConfig::LoadSettings() {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
LauncherZone tmp;
char namebuf[128];
database.DoEscapeString(namebuf, m_name.c_str(), m_name.length()&0x3F); //limit len to 64
namebuf[127] = '\0';
if (database.RunQuery(query, MakeAnyLenString(&query,
"SELECT dynamics FROM launcher WHERE name='%s'",
namebuf)
, errbuf, &result))
{
while ((row = mysql_fetch_row(result))) {
m_dynamics = atoi(row[0]);
}
mysql_free_result(result);
} else {
LogFile->write(EQEMuLog::Error, "EQLConfig::LoadSettings: %s", errbuf);
}
safe_delete_array(query);
if (database.RunQuery(query, MakeAnyLenString(&query,
"SELECT zone,port FROM launcher_zones WHERE launcher='%s'",
namebuf)
, errbuf, &result))
{
LauncherZone zs;
while ((row = mysql_fetch_row(result))) {
zs.name = row[0];
zs.port = atoi(row[1]);
m_zones[zs.name] = zs;
}
mysql_free_result(result);
} else {
LogFile->write(EQEMuLog::Error, "EQLConfig::LoadSettings: %s", errbuf);
}
safe_delete_array(query);
}
EQLConfig *EQLConfig::CreateLauncher(const char *name, uint8 dynamic_count) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
char namebuf[128];
database.DoEscapeString(namebuf, name, strlen(name)&0x3F); //limit len to 64
namebuf[127] = '\0';
if (!database.RunQuery(query, MakeAnyLenString(&query,
"INSERT INTO launcher (name,dynamics) VALUES('%s', %d)",
namebuf, dynamic_count), errbuf)) {
LogFile->write(EQEMuLog::Error, "Error in CreateLauncher query: %s", errbuf);
safe_delete_array(query);
return false;
}
safe_delete_array(query);
return(new EQLConfig(name));
}
void EQLConfig::GetZones(std::vector<LauncherZone> &result) {
map<string, LauncherZone>::iterator cur, end;
cur = m_zones.begin();
end = m_zones.end();
for(; cur != end; cur++) {
result.push_back(cur->second);
}
}
vector<string> EQLConfig::ListZones() {
LauncherLink *ll = launcher_list.Get(m_name.c_str());
vector<string> res;
if(ll == NULL) {
//if the launcher isnt connected, use the list from the database.
map<string, LauncherZone>::iterator cur, end;
cur = m_zones.begin();
end = m_zones.end();
for(; cur != end; cur++) {
res.push_back(cur->first);
}
} else {
//otherwise, use the zone list from the launcher link.
ll->GetZoneList(res);
}
return(res);
}
void EQLConfig::DeleteLauncher() {
launcher_list.Remove(m_name.c_str());
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
char namebuf[128];
database.DoEscapeString(namebuf, m_name.c_str(), m_name.length()&0x3F); //limit len to 64
namebuf[127] = '\0';
if (!database.RunQuery(query, MakeAnyLenString(&query,
"DELETE FROM launcher WHERE name='%s'",
namebuf), errbuf)) {
LogFile->write(EQEMuLog::Error, "Error in DeleteLauncher 1 query: %s", errbuf);
safe_delete_array(query);
return;
}
safe_delete_array(query);
if (!database.RunQuery(query, MakeAnyLenString(&query,
"DELETE FROM launcher_zones WHERE launcher='%s'",
namebuf), errbuf)) {
LogFile->write(EQEMuLog::Error, "Error in DeleteLauncher 2 query: %s", errbuf);
safe_delete_array(query);
return;
}
safe_delete_array(query);
}
bool EQLConfig::IsConnected() const {
LauncherLink *ll = launcher_list.Get(m_name.c_str());
return(ll != NULL);
}
void EQLConfig::RestartZone(Const_char *zone_ref) {
LauncherLink *ll = launcher_list.Get(m_name.c_str());
if(ll == NULL)
return;
ll->RestartZone(zone_ref);
}
void EQLConfig::StopZone(Const_char *zone_ref) {
LauncherLink *ll = launcher_list.Get(m_name.c_str());
if(ll == NULL)
return;
ll->StopZone(zone_ref);
}
void EQLConfig::StartZone(Const_char *zone_ref) {
LauncherLink *ll = launcher_list.Get(m_name.c_str());
if(ll == NULL)
return;
ll->StartZone(zone_ref);
}
bool EQLConfig::BootStaticZone(Const_char *short_name, uint16 port) {
//make sure the short name is valid.
if(database.GetZoneID(short_name) == 0)
return(false);
//database update
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
char namebuf[128];
database.DoEscapeString(namebuf, m_name.c_str(), m_name.length()&0x3F); //limit len to 64
namebuf[127] = '\0';
char zonebuf[32];
database.DoEscapeString(zonebuf, short_name, strlen(short_name)&0xF); //limit len to 16
zonebuf[31] = '\0';
if (!database.RunQuery(query, MakeAnyLenString(&query,
"INSERT INTO launcher_zones (launcher,zone,port) VALUES('%s', '%s', %d)",
namebuf, zonebuf, port), errbuf)) {
LogFile->write(EQEMuLog::Error, "Error in BootStaticZone query: %s", errbuf);
safe_delete_array(query);
return false;
}
safe_delete_array(query);
//update our internal state.
LauncherZone lz;
lz.name = short_name;
lz.port = port;
m_zones[lz.name] = lz;
//if the launcher is connected, update it.
LauncherLink *ll = launcher_list.Get(m_name.c_str());
if(ll != NULL) {
ll->BootZone(short_name, port);
}
return(true);
}
bool EQLConfig::ChangeStaticZone(Const_char *short_name, uint16 port) {
//make sure the short name is valid.
if(database.GetZoneID(short_name) == 0)
return(false);
//check internal state
map<string, LauncherZone>::iterator res;
res = m_zones.find(short_name);
if(res == m_zones.end()) {
//not found.
LogFile->write(EQEMuLog::Error, "Update for unknown zone %s", short_name);
return(false);
}
//database update
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
char namebuf[128];
database.DoEscapeString(namebuf, m_name.c_str(), m_name.length()&0x3F); //limit len to 64
namebuf[127] = '\0';
char zonebuf[32];
database.DoEscapeString(zonebuf, short_name, strlen(short_name)&0xF); //limit len to 16
zonebuf[31] = '\0';
if (!database.RunQuery(query, MakeAnyLenString(&query,
"UPDATE launcher_zones SET port=%d WHERE launcher='%s' AND zone='%s'",
port, namebuf, zonebuf), errbuf)) {
LogFile->write(EQEMuLog::Error, "Error in ChangeStaticZone query: %s", errbuf);
safe_delete_array(query);
return false;
}
safe_delete_array(query);
//update internal state
res->second.port = port;
//if the launcher is connected, update it.
LauncherLink *ll = launcher_list.Get(m_name.c_str());
if(ll != NULL) {
ll->RestartZone(short_name);
}
return(true);
}
bool EQLConfig::DeleteStaticZone(Const_char *short_name) {
//check internal state
map<string, LauncherZone>::iterator res;
res = m_zones.find(short_name);
if(res == m_zones.end()) {
//not found.
LogFile->write(EQEMuLog::Error, "Update for unknown zone %s", short_name);
return(false);
}
//database update
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
char namebuf[128];
database.DoEscapeString(namebuf, m_name.c_str(), m_name.length()&0x3F); //limit len to 64
namebuf[127] = '\0';
char zonebuf[32];
database.DoEscapeString(zonebuf, short_name, strlen(short_name)&0xF); //limit len to 16
zonebuf[31] = '\0';
if (!database.RunQuery(query, MakeAnyLenString(&query,
"DELETE FROM launcher_zones WHERE launcher='%s' AND zone='%s'",
namebuf, zonebuf), errbuf)) {
LogFile->write(EQEMuLog::Error, "Error in DeleteStaticZone query: %s", errbuf);
safe_delete_array(query);
return false;
}
safe_delete_array(query);
//internal update.
m_zones.erase(res);
//if the launcher is connected, update it.
LauncherLink *ll = launcher_list.Get(m_name.c_str());
if(ll != NULL) {
ll->StopZone(short_name);
}
return true;
}
bool EQLConfig::SetDynamicCount(int count) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
char namebuf[128];
database.DoEscapeString(namebuf, m_name.c_str(), m_name.length()&0x3F); //limit len to 64
namebuf[127] = '\0';
if (!database.RunQuery(query, MakeAnyLenString(&query,
"UPDATE launcher SET dynamics=%d WHERE name='%s'",
count, namebuf), errbuf)) {
LogFile->write(EQEMuLog::Error, "Error in SetDynamicCount query: %s", errbuf);
safe_delete_array(query);
return false;
}
safe_delete_array(query);
//update in-memory version.
m_dynamics = count;
//if the launcher is connected, update it.
LauncherLink *ll = launcher_list.Get(m_name.c_str());
if(ll != NULL) {
ll->BootDynamics(count);
}
return(false);
}
int EQLConfig::GetDynamicCount() const {
return(m_dynamics);
}
map<string,string> EQLConfig::GetZoneDetails(Const_char *zone_ref) {
map<string,string> res;
LauncherLink *ll = launcher_list.Get(m_name.c_str());
if(ll == NULL) {
res["name"] = zone_ref;
res["up"] = "0";
res["starts"] = "0";
res["port"] = "0";
} else {
ll->GetZoneDetails(zone_ref, res);
}
return(res);
}
+82
View File
@@ -0,0 +1,82 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef EQLCONFIG_H_
#define EQLCONFIG_H_
#include "../common/types.h"
#include "worlddb.h"
#include <map>
#include <string>
using namespace std;
class LauncherLink;
typedef struct {
std::string name;
uint16 port;
} LauncherZone;
//a class exported to perl representing a launcher's in-DB config
class EQLConfig {
public:
EQLConfig(const char *launcher_name);
void LoadSettings();
static EQLConfig *CreateLauncher(const char *name, uint8 dynamic_count);
void GetZones(std::vector<LauncherZone> &result);
//BEGIN PERL EXPORT
Const_char * GetName() const { return(m_name.c_str()); }
int GetStaticCount() const { return(m_zones.size()); }
bool IsConnected() const; //is this launcher connected to world
void DeleteLauncher(); //kill this launcher and all its zones.
void RestartZone(Const_char *zone_ref);
void StopZone(Const_char *zone_ref);
void StartZone(Const_char *zone_ref);
bool BootStaticZone(Const_char *short_name, uint16 port);
bool ChangeStaticZone(Const_char *short_name, uint16 port);
bool DeleteStaticZone(Const_char *short_name);
bool SetDynamicCount(int count);
int GetDynamicCount() const;
vector<string> ListZones(); //returns an array of zone refs
map<string,string> GetZoneDetails(Const_char *zone_ref);
//END PERL EXPORT
protected:
const string m_name;
uint8 m_dynamics;
map<string, LauncherZone> m_zones; //static zones.
};
#endif /*EQLCONFIG_H_*/
+474
View File
@@ -0,0 +1,474 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef EMBPERL
#include "../common/debug.h"
#include "EQW.h"
#include "EQWParser.h"
#include "WorldConfig.h"
#include "../common/races.h"
#include "../common/classes.h"
#include "../common/misc.h"
#include "../common/MiscFunctions.h"
#include "zoneserver.h"
#include "zonelist.h"
#include "clientlist.h"
#include "cliententry.h"
#include "LoginServer.h"
#include "LoginServerList.h"
#include "worlddb.h"
#include "client.h"
#include "LauncherList.h"
#include "LauncherLink.h"
#include "wguild_mgr.h"
#include <algorithm>
using namespace std;
extern ZSList zoneserver_list;
extern ClientList client_list;
extern uint32 numzones;
extern LoginServerList loginserverlist;
extern LauncherList launcher_list;
extern volatile bool RunLoops;
EQW EQW::s_EQW;
//IO Capture routine
XS(XS_EQWIO_PRINT); /* prototype to pass -Wmissing-prototypes */
XS(XS_EQWIO_PRINT)
{
dXSARGS;
if (items < 2)
return;
int r;
for(r = 1; r < items; r++) {
char *str = SvPV_nolen(ST(r));
EQW::Singleton()->AppendOutput(str);
}
XSRETURN_EMPTY;
}
EQW::EQW() {
}
void EQW::AppendOutput(const char *str) {
m_outputBuffer += str;
// _log(WORLD__EQW, "Append %d chars, yeilding result of length %d", strlen(str), m_outputBuffer.length());
}
const std::string &EQW::GetOutput() const {
// _log(WORLD__EQW, "Getting, length %d", m_outputBuffer.length());
return(m_outputBuffer);
}
void EQW::LockWorld() {
WorldConfig::LockWorld();
if (loginserverlist.Connected()) {
loginserverlist.SendStatus();
}
}
void EQW::UnlockWorld() {
WorldConfig::UnlockWorld();
if (loginserverlist.Connected()) {
loginserverlist.SendStatus();
}
}
Const_char *EQW::GetConfig(Const_char *var_name) {
m_returnBuffer = WorldConfig::get()->GetByName(var_name);
return(m_returnBuffer.c_str());
}
bool EQW::LSConnected() {
return(loginserverlist.Connected());
}
int EQW::CountZones() {
return(zoneserver_list.GetZoneCount());
}
//returns an array of zone_refs (opaque)
vector<string> EQW::ListBootedZones() {
vector<string> res;
vector<uint32> zones;
zoneserver_list.GetZoneIDList(zones);
vector<uint32>::iterator cur, end;
cur = zones.begin();
end = zones.end();
for(; cur != end; cur++) {
res.push_back(itoa(*cur));
}
return(res);
}
map<string,string> EQW::GetZoneDetails(Const_char *zone_ref) {
map<string,string> res;
ZoneServer *zs = zoneserver_list.FindByID(atoi(zone_ref));
if(zs == NULL) {
res["error"] = "Invalid zone.";
return(res);
}
res["type"] = zs->IsStaticZone()?"static":"dynamic";
res["zone_id"] = itoa(zs->GetZoneID());
res["launch_name"] = zs->GetLaunchName();
res["launched_name"] = zs->GetLaunchedName();
res["short_name"] = zs->GetZoneName();
res["long_name"] = zs->GetZoneLongName();
res["port"] = itoa(zs->GetCPort());
res["player_count"] = itoa(zs->NumPlayers());
//this isnt gunna work for dynamic zones...
res["launcher"] = "";
if(zs->GetZoneID() != 0) {
LauncherLink *ll = launcher_list.FindByZone(zs->GetLaunchName());
if(ll != NULL)
res["launcher"] = ll->GetName();
}
return(res);
}
int EQW::CountPlayers() {
return(client_list.GetClientCount());
}
//returns an array of character names in the zone (empty=all zones)
vector<string> EQW::ListPlayers(Const_char *zone_name) {
vector<string> res;
vector<ClientListEntry *> list;
client_list.GetClients(zone_name, list);
vector<ClientListEntry *>::iterator cur, end;
cur = list.begin();
end = list.end();
for(; cur != end; cur++) {
res.push_back((*cur)->name());
}
return(res);
}
map<string,string> EQW::GetPlayerDetails(Const_char *char_name) {
map<string,string> res;
ClientListEntry *cle = client_list.FindCharacter(char_name);
if(cle == NULL) {
res["error"] = "1";
return(res);
}
res["character"] = cle->name();
res["account"] = cle->AccountName();
res["account_id"] = itoa(cle->AccountID());
res["location_short"] = cle->zone()?database.GetZoneName(cle->zone()):"No Zone";
res["location_long"] = res["location_short"];
res["location_id"] = itoa(cle->zone());
res["ip"] = long2ip(cle->GetIP());
res["level"] = itoa(cle->level());
res["race"] = GetRaceName(cle->race());
res["race_id"] = itoa(cle->race());
res["class"] = GetEQClassName(cle->class_());
res["class_id"] = itoa(cle->class_());
res["guild_id"] = itoa(cle->GuildID());
res["guild"] = guild_mgr.GetGuildName(cle->GuildID());
res["status"] = itoa(cle->Admin());
// res["patch"] = cle->DescribePatch();
return(res);
}
int EQW::CountLaunchers(bool active_only) {
if(active_only)
return(launcher_list.GetLauncherCount());
vector<string> it(EQW::ListLaunchers());
return(it.size());
}
/*
vector<string> EQW::ListActiveLaunchers() {
vector<string> launchers;
launcher_list.GetLauncherNameList(launchers);
return(launchers);
}*/
vector<string> EQW::ListLaunchers() {
// vector<string> list;
// database.GetLauncherList(list);
vector<string> launchers;
launcher_list.GetLauncherNameList(launchers);
return(launchers);
/* if(list.empty()) {
return(launchers);
} else if(launchers.empty()) {
return(list);
}
//union the two lists.
vector<string>::iterator curo, endo, curi, endi;
curo = list.begin();
endo = list.end();
for(; curo != endo; curo++) {
bool found = false;
curi = launchers.begin();
endi = launchers.end();
for(; curi != endi; curi++) {
if(*curo == *curi) {
found = true;
break;
}
}
if(found)
break;
launchers.push_back(*curo);
}
return(launchers);*/
}
EQLConfig * EQW::GetLauncher(Const_char *launcher_name) {
return(launcher_list.GetConfig(launcher_name));
}
void EQW::CreateLauncher(Const_char *launcher_name, int dynamic_count) {
launcher_list.CreateLauncher(launcher_name, dynamic_count);
}
void EQW::LSReconnect() {
#ifdef _WINDOWS
_beginthread(AutoInitLoginServer, 0, NULL);
#else
pthread_t thread;
pthread_create(&thread, NULL, &AutoInitLoginServer, NULL);
#endif
RunLoops = true;
_log(WORLD__CONSOLE,"Login Server Reconnect manually restarted by Web Tool");
}
/*EQLConfig * EQW::FindLauncher(Const_char *zone_ref) {
return(NULL);
}*/
/*
map<string,string> EQW::GetLaunchersDetails(Const_char *launcher_name) {
map<string,string> res;
LauncherLink *ll = launcher_list.Get(launcher_name);
if(ll == NULL) {
res["name"] = launcher_name;
res["ip"] = "Not Connected";
res["id"] = "0";
res["zone_count"] = "0";
res["connected"] = "no";
return(res);
} else {
res["name"] = ll->GetName();
res["ip"] = long2ip(ll->GetIP());
res["id"] = itoa(ll->GetID());
res["zone_count"] = itoa(ll->CountZones());
res["connected"] = "yes";
}
return(res);
}
vector<string> EQW::ListLauncherZones(Const_char *launcher_name) {
vector<string> list;
LauncherLink *ll = launcher_list.Get(launcher_name);
if(ll != NULL) {
ll->GetZoneList(list);
}
return(list);
}
map<string,string> EQW::GetLauncherZoneDetails(Const_char *launcher_name, Const_char *zone_ref) {
map<string,string> res;
LauncherLink *ll = launcher_list.Get(launcher_name);
if(ll != NULL) {
ll->GetZoneDetails(zone_ref, res);
} else {
res["error"] = "Launcher Not Found";
}
return(res);
}
void EQW::CreateLauncher(Const_char *launcher_name, int dynamic_count) {
}
bool EQW::BootStaticZone(Const_char *launcher_name, Const_char *short_name) {
return(false);
}
bool EQW::DeleteStaticZone(Const_char *launcher_name, Const_char *short_name) {
return(false);
}
bool EQW::SetDynamicCount(Const_char *launcher_name, int count) {
return(false);
}
int EQW::GetDynamicCount(Const_char *launcher_name) {
return(0);
}
*/
uint32 EQW::CreateGuild(const char* name, uint32 leader_char_id) {
uint32 id = guild_mgr.CreateGuild(name, leader_char_id);
if(id != GUILD_NONE)
client_list.UpdateClientGuild(leader_char_id, id);
return(id);
}
bool EQW::DeleteGuild(uint32 guild_id) {
return(guild_mgr.DeleteGuild(guild_id));
}
bool EQW::RenameGuild(uint32 guild_id, const char* name) {
return(guild_mgr.RenameGuild(guild_id, name));
}
bool EQW::SetGuildMOTD(uint32 guild_id, const char* motd, const char *setter) {
return(guild_mgr.SetGuildMOTD(guild_id, motd, setter));
}
bool EQW::SetGuildLeader(uint32 guild_id, uint32 leader_char_id) {
return(guild_mgr.SetGuildLeader(guild_id, leader_char_id));
}
bool EQW::SetGuild(uint32 charid, uint32 guild_id, uint8 rank) {
client_list.UpdateClientGuild(charid, guild_id);
return(guild_mgr.SetGuild(charid, guild_id, rank));
}
bool EQW::SetGuildRank(uint32 charid, uint8 rank) {
return(guild_mgr.SetGuildRank(charid, rank));
}
bool EQW::SetBankerFlag(uint32 charid, bool is_banker) {
return(guild_mgr.SetBankerFlag(charid, is_banker));
}
bool EQW::SetTributeFlag(uint32 charid, bool enabled) {
return(guild_mgr.SetTributeFlag(charid, enabled));
}
bool EQW::SetPublicNote(uint32 charid, const char *note) {
return(guild_mgr.SetPublicNote(charid, note));
}
int EQW::CountBugs() {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if(database.RunQuery(query, MakeAnyLenString(&query, "SELECT count(*) FROM bugs where status = 0"), errbuf, &result)) {
safe_delete_array(query);
if((row = mysql_fetch_row(result))) {
int count = atoi(row[0]);
mysql_free_result(result);
return count;
}
mysql_free_result(result);
}
safe_delete_array(query);
return 0;
}
vector<string> EQW::ListBugs(uint32 offset) {
vector<string> res;
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if(database.RunQuery(query, MakeAnyLenString(&query, "SELECT id FROM bugs WHERE status = 0 limit %d, 30", offset), errbuf, &result)) {
safe_delete_array(query);
while((row = mysql_fetch_row(result))) {
res.push_back(row[0]);
}
mysql_free_result(result);
}
safe_delete_array(query);
return res;
}
map<string,string> EQW::GetBugDetails(Const_char *id) {
map<string,string> res;
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if(database.RunQuery(query, MakeAnyLenString(&query, "select name, zone, x, y, z, target, bug from bugs where id = %s", id), errbuf, &result)) {
safe_delete_array(query);
while((row = mysql_fetch_row(result))) {
res["name"] = row[0];
res["zone"] = row[1];
res["x"] = row[2];
res["y"] = row[3];
res["z"] = row[4];
res["target"] = row[5];
res["bug"] = row[6];
res["id"] = id;
}
mysql_free_result(result);
}
safe_delete_array(query);
return res;
}
void EQW::ResolveBug(const char *id) {
vector<string> res;
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_ROW row;
if(database.RunQuery(query, MakeAnyLenString(&query, "UPDATE bugs SET status=1 WHERE id=%s", id), errbuf)) {
safe_delete_array(query);
}
safe_delete_array(query);
}
#endif //EMBPERL
+93
View File
@@ -0,0 +1,93 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef EQW_H_
#define EQW_H_
#include <string>
#include <vector>
#include <map>
#include "../common/types.h"
using namespace std;
class EQLConfig;
//this is the main object exported to perl.
class EQW {
EQW();
public:
static EQW *Singleton() { return(&s_EQW); }
void AppendOutput(const char *str);
const std::string &GetOutput() const;
void ClearOutput() { m_outputBuffer = ""; }
//BEGIN PERL EXPORT
//NOTE: you must have a space after the * of a return value
Const_char * GetConfig(Const_char *var_name);
void LockWorld();
void UnlockWorld();
bool LSConnected();
void LSReconnect();
int CountZones();
vector<string> ListBootedZones(); //returns an array of zone_refs (opaque)
map<string,string> GetZoneDetails(Const_char *zone_ref); //returns a hash ref of details
int CountPlayers();
vector<string> ListPlayers(Const_char *zone_name = ""); //returns an array of player refs (opaque)
map<string,string> GetPlayerDetails(Const_char *player_ref); //returns a hash ref of details
int CountLaunchers(bool active_only);
// vector<string> ListActiveLaunchers(); //returns an array of launcher names
vector<string> ListLaunchers(); //returns an array of launcher names
EQLConfig * GetLauncher(Const_char *launcher_name); //returns the EQLConfig object for the specified launcher.
void CreateLauncher(Const_char *launcher_name, int dynamic_count);
// EQLConfig * FindLauncher(Const_char *zone_ref);
//Guild routines, mostly wrappers around guild_mgr
uint32 CreateGuild(const char* name, uint32 leader_char_id);
bool DeleteGuild(uint32 guild_id);
bool RenameGuild(uint32 guild_id, const char* name);
bool SetGuildMOTD(uint32 guild_id, const char* motd, const char *setter);
bool SetGuildLeader(uint32 guild_id, uint32 leader_char_id);
bool SetGuild(uint32 charid, uint32 guild_id, uint8 rank);
bool SetGuildRank(uint32 charid, uint8 rank);
bool SetBankerFlag(uint32 charid, bool is_banker);
bool SetTributeFlag(uint32 charid, bool enabled);
bool SetPublicNote(uint32 charid, const char *note);
//bugs
int CountBugs();
vector<string> ListBugs(uint32 offset); //returns an array of zone_refs (opaque)
map<string,string> GetBugDetails(const char *id);
void ResolveBug(const char *id);
//END PERL EXPORT
protected:
std::string m_outputBuffer;
std::string m_returnBuffer;
bool m_worldLocked;
private:
static EQW s_EQW;
};
#endif /*EQW_H_*/
+340
View File
@@ -0,0 +1,340 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "EQWHTTPHandler.h"
#include "../common/SocketLib/Base64.h"
#include "EQWParser.h"
#include "EQW.h"
#include "HTTPRequest.h"
#include "../common/logsys.h"
#include "worlddb.h"
#include "console.h"
using namespace std;
Mime EQWHTTPHandler::s_mime;
#ifdef EMBPERL
EQWParser *EQWHTTPHandler::s_parser = NULL;
#endif
const int EQWHTTPHandler::READ_BUFFER_LEN = 1024; //for page IO, was a static const member, but VC6 got mad.
EQWHTTPHandler::EQWHTTPHandler(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort)
: HttpdSocket(ID,in_socket,irIP,irPort),
m_closeOnFinish(false)
{
}
EQWHTTPHandler::~EQWHTTPHandler() {
}
#ifdef EMBPERL
EQWParser *EQWHTTPHandler::GetParser() {
if(s_parser == NULL) {
EQW::Singleton()->ClearOutput();
s_parser = new EQWParser();
const string &res = EQW::Singleton()->GetOutput();
if(!res.empty()) {
printf("EQWParser Init output:\n%s\n\n", res.c_str());
EQW::Singleton()->ClearOutput();
}
}
return(s_parser);
}
#endif
/*void EQWHTTPHandler::OnWrite() {
HttpdSocket::OnWrite();
if(m_closeOnFinish && GetOutputLength() == 0) {
// printf("CLOSING\n");
Close();
}
}*/
void EQWHTTPHandler::Exec() {
m_sentHeaders = false;
m_responseCode = "200";
// printf("Request: %s, %s, %s, %s.\n", GetMethod().c_str(), GetUrl().c_str(), GetUri().c_str(), GetQueryString().c_str());
SetHttpVersion("HTTP/1.0");
AddResponseHeader("Connection", "close");
if(GetUri().find("..") != string::npos) {
SendResponse("403", "Forbidden");
printf("%s is forbidden.\n", GetUri().c_str());
return;
}
if(!CheckAuth()) {
AddResponseHeader("Content-type", "text/plain");
AddResponseHeader("WWW-Authenticate", "Basic realm=\"EQEmulator\"");
SendResponse("401", "Authorization Required");
SendString("Gotta Authenticate.");
} else {
string::size_type start = GetUri().find_first_not_of('/');
string page;
if(start != string::npos)
page = GetUri().substr(start);
else
page = "index.html";
SendPage(page);
}
/* if (!Detach()) {
printf("Unable to detach...\n");
}
if(GetOutputLength() > 0) {
//we cannot close yet
m_closeOnFinish = true;
} else {
Close();
}*/
Free(); //the "app" side (us) is done with this connection too...
Disconnect();
}
void EQWHTTPHandler::OnHeader(const std::string& key,const std::string& value) {
HttpdSocket::OnHeader(key, value);
if (!strcasecmp(key.c_str(),"Authorization")) {
if(strncasecmp(value.c_str(), "Basic ", 6)) {
printf("Invalid auth type. Expected Basic: %s\n", value.c_str());
return;
}
std::string dec;
Base64::decode(value.c_str() + 6, dec);
std::string::size_type cpos;
cpos = dec.find_first_of(':');
if(cpos == string::npos) {
printf("Invalid auth string: %s\n", dec.c_str());
return;
}
m_username = dec.substr(0, cpos);
m_password = dec.substr(cpos+1);
}
}
//we should prolly cache login info here... if we load a fresh page, we could be checking
//their auth dozens of times rather quickly...
bool EQWHTTPHandler::CheckAuth() const {
if(m_username.length() < 1)
return(false);
int16 status = 0;
uint32 acctid = database.CheckLogin(m_username.c_str(), m_password.c_str(), &status);
if(acctid == 0) {
_log(WORLD__HTTP_ERR, "Login autentication failed for %s with '%s'", m_username.c_str(), m_password.c_str());
return(false);
}
if(status < httpLoginStatus) {
_log(WORLD__HTTP_ERR, "Login of %s failed: status too low.", m_username.c_str());
return(false);
}
return(true);
}
void EQWHTTPHandler::SendPage(const std::string &file) {
string path = "templates/";
path += file;
FILE *f = fopen(path.c_str(), "rb");
if(f == NULL) {
SendResponse("404", "Not Found");
SendString("Not found.");
printf("%s not found.\n", file.c_str());
return;
}
string type = s_mime.GetMimeFromFilename(file);
AddResponseHeader("Content-type", type);
bool process = false;
#ifdef EMBPERL
if(type == "text/html")
process = true;
else {
//not processing, send headers right away
#endif
SendResponse("200", "OK");
#ifdef EMBPERL
}
#endif
char *buffer = new char[READ_BUFFER_LEN+1];
size_t len;
string to_process;
while((len = fread(buffer, 1, READ_BUFFER_LEN, f)) > 0) {
buffer[len] = '\0';
if(process)
to_process += buffer;
else
SendBuf(buffer, len);
}
delete[] buffer;
fclose(f);
#ifdef EMBPERL
if(process) {
//convert the base form into a useful perl exportable form
HTTPRequest req(this, GetHttpForm());
GetParser()->SetHTTPRequest("testing", &req);
//parse out the page and potentially pass some stuff on to perl.
ProcessAndSend(to_process);
//clear out the form, just in case (since it gets destroyed next)
GetParser()->SetHTTPRequest("testing", NULL);
}
#endif
}
bool EQWHTTPHandler::LoadMimeTypes(const char *filename) {
return(s_mime.LoadMimeFile(filename));
}
#ifdef EMBPERL
void EQWHTTPHandler::ProcessAndSend(const string &str) {
string::size_type len = str.length();
string::size_type start = 0;
string::size_type pos, end;
while((pos = str.find("<?", start)) != string::npos) {
//send all the crap leading up to the script block
if(pos != start) {
ProcessText(str.c_str() + start, pos-start);
}
//look for the end of this script block...
end = str.find("?>", pos+2);
if(end == string::npos) {
//terminal ?> not found... should issue a warning or something...
string scriptBody = str.substr(pos+2);
ProcessScript(scriptBody);
start = len;
break;
} else {
//script only consumes some of this buffer...
string scriptBody = str.substr(pos+2, end-pos-2);
ProcessScript(scriptBody);
start = end + 2;
}
}
//send whatever is left over
if(start != len)
ProcessText(str.c_str() + start, len-start);
}
void EQWHTTPHandler::ProcessScript(const std::string &script_body) {
const char *script = script_body.c_str();
if(strcmp("perl", script) == 0)
script += 4; //allow <?perl
// printf("Script: ''''%s''''\n\n", script_body.c_str());
GetParser()->EQW_eval("testing", script_body.c_str());
const string &res = EQW::Singleton()->GetOutput();
if(!res.empty()) {
ProcessText(res.c_str(), res.length());
EQW::Singleton()->ClearOutput();
}
}
void EQWHTTPHandler::ProcessText(const char *txt, int len) {
if(!m_sentHeaders) {
SendResponse(m_responseCode, "OK");
m_sentHeaders = true;
}
SendBuf(txt, len);
}
#endif
EQWHTTPServer::EQWHTTPServer()
: m_port(0)
{
}
void EQWHTTPServer::CreateNewConnection(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort) {
EQWHTTPHandler *conn = new EQWHTTPHandler(ID, in_socket, irIP, irPort);
AddConnection(conn);
}
void EQWHTTPServer::Stop() {
_log(WORLD__HTTP, "Requesting that HTTP Service stop.");
m_running = false;
Close();
}
bool EQWHTTPServer::Start(uint16 port, const char *mime_file) {
if(m_running) {
_log(WORLD__HTTP_ERR, "HTTP Service is already running on port %d", m_port);
return(false);
}
//load up our nice mime types
if(!EQWHTTPHandler::LoadMimeTypes(mime_file)) {
_log(WORLD__HTTP_ERR, "Failed to load mime types from '%s'", mime_file);
return(false);
} else {
_log(WORLD__HTTP, "Loaded mime types from %s", mime_file);
}
//fire up the server thread
char errbuf[TCPServer_ErrorBufferSize];
if(!Open(port, errbuf)) {
_log(WORLD__HTTP_ERR, "Unable to bind to port %d for HTTP service: %s", port, errbuf);
return(false);
}
m_running = true;
m_port = port;
/*
#ifdef _WINDOWS
_beginthread(ThreadProc, 0, this);
#else
pthread_create(&m_thread, NULL, ThreadProc, this);
#endif*/
return(true);
}
/*
void EQWHTTPServer::Run() {
_log(WORLD__HTTP, "HTTP Processing thread started on port %d", m_port);
do {
#warning DELETE THIS IF YOU DONT USE IT
Sleep(10);
} while(m_running);
_log(WORLD__HTTP, "HTTP Processing thread terminating on port %d", m_port);
}
ThreadReturnType EQWHTTPServer::ThreadProc(void *data) {
((EQWHTTPServer *) data)->Run();
THREAD_RETURN(NULL);
}*/
+101
View File
@@ -0,0 +1,101 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef EQWHTTPHandler_H
#define EQWHTTPHandler_H
#include "../common/TCPServer.h"
#include "../common/TCPConnection.h"
#include "../common/SocketLib/HttpdSocket.h"
#include "../common/SocketLib/Mime.h"
#include "../common/types.h"
class EQWParser;
class EQWHTTPHandler : public HttpdSocket {
static const int READ_BUFFER_LEN;
public:
EQWHTTPHandler(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort);
virtual ~EQWHTTPHandler();
void SetResponseCode(const char *code) { m_responseCode = code; }
//HttpdSocket interface:
virtual void Exec();
virtual void OnHeader(const std::string& key,const std::string& value);
static bool LoadMimeTypes(const char *filename);
protected:
bool CheckAuth() const;
void SendPage(const std::string &file);
//credentials
std::string m_username;
std::string m_password;
bool m_closeOnFinish;
std::string m_responseCode;
bool m_sentHeaders;
//our mime type manager
static Mime s_mime;
#ifdef EMBPERL
void ProcessAndSend(const std::string &entire_html_page);
void ProcessScript(const std::string &script_body);
void ProcessText(const char *txt, int len);
static EQWParser *GetParser();
private:
static EQWParser *s_parser;
#endif
};
class EQWHTTPServer : protected TCPServer<EQWHTTPHandler> {
public:
EQWHTTPServer();
bool Start(uint16 port, const char *mime_file);
void Stop();
protected:
volatile bool m_running;
uint16 m_port;
virtual void CreateNewConnection(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort);
/* //I decided to put this into its own thread so that the HTTP pages
//cannot block the main world server's operation.
static ThreadReturnType ThreadProc(void* tmp);
void Run();
#ifndef WIN32
pthread_t m_thread;
#endif*/
};
#endif
+352
View File
@@ -0,0 +1,352 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//a lot of this is copied from embperl.cpp, but I didnt feel like factoring the common stuff out
#ifdef EMBPERL
#include "../common/debug.h"
#include "EQWParser.h"
#include "EQW.h"
#include "../common/EQDB.h"
#include "../common/logsys.h"
#include "worlddb.h"
using namespace std;
#ifndef GvCV_set
#define GvCV_set(gv,cv) (GvCV(gv) = (cv))
#endif
XS(XS_EQWIO_PRINT);
//so embedded scripts can use xs extensions (ala 'use socket;')
EXTERN_C void boot_DynaLoader(pTHX_ CV* cv);
EXTERN_C XS(boot_EQW);
EXTERN_C XS(boot_EQDB);
EXTERN_C XS(boot_EQDBRes);
EXTERN_C XS(boot_HTTPRequest);
EXTERN_C XS(boot_EQLConfig);
EXTERN_C void xs_init(pTHX)
{
char file[256];
strncpy(file, __FILE__, 256);
file[255] = '\0';
char buf[128]; //shouldent have any function names longer than this.
//add the strcpy stuff to get rid of const warnings....
newXS(strcpy(buf, "DynaLoader::boot_DynaLoader"), boot_DynaLoader, file);
newXS(strcpy(buf, "EQW::boot_EQW"), boot_EQW, file);
newXS(strcpy(buf, "EQDB::boot_EQDB"), boot_EQDB, file);
newXS(strcpy(buf, "EQDBRes::boot_EQDBRes"), boot_EQDBRes, file);
newXS(strcpy(buf, "HTTPRequest::boot_HTTPRequest"), boot_HTTPRequest, file);
newXS(strcpy(buf, "EQLConfig::boot_EQLConfig"), boot_EQLConfig, file);
newXS(strcpy(buf, "EQWIO::PRINT"), XS_EQWIO_PRINT, file);
}
EQWParser::EQWParser() {
//setup perl...
my_perl = perl_alloc();
_empty_sv = newSV(0);
if(!my_perl)
_log(WORLD__PERL_ERR, "Error: perl_alloc failed!");
else
DoInit();
}
void EQWParser::DoInit() {
const char *argv_eqemu[] = { "",
"-w", "-W",
"-e", "0;", NULL };
int argc = 5;
char **argv = (char **)argv_eqemu;
char **env = { NULL };
PL_perl_destruct_level = 1;
perl_construct(my_perl);
PERL_SYS_INIT3(&argc, &argv, &env);
perl_parse(my_perl, xs_init, argc, argv, env);
perl_run(my_perl);
//a little routine we use a lot.
eval_pv("sub my_eval {eval $_[0];}", TRUE); //dies on error
//ruin the perl exit and command:
eval_pv("sub my_exit {}",TRUE);
eval_pv("sub my_sleep {}",TRUE);
if(gv_stashpv("CORE::GLOBAL", FALSE)) {
GV *exitgp = gv_fetchpv("CORE::GLOBAL::exit", TRUE, SVt_PVCV);
GvCV_set(exitgp, perl_get_cv("my_exit", TRUE)); //dies on error
GvIMPORTED_CV_on(exitgp);
GV *sleepgp = gv_fetchpv("CORE::GLOBAL::sleep", TRUE, SVt_PVCV);
GvCV_set(sleepgp, perl_get_cv("my_sleep", TRUE)); //dies on error
GvIMPORTED_CV_on(sleepgp);
}
//setup eval_file
eval_pv(
"our %Cache;"
"use Symbol qw(delete_package);"
"sub eval_file {"
"my($package, $filename) = @_;"
"$filename=~s/\'//g;"
"if(! -r $filename) { print \"Unable to read perl file '$filename'\\n\"; return; }"
"my $mtime = -M $filename;"
"if(defined $Cache{$package}{mtime}&&$Cache{$package}{mtime} <= $mtime && !($package eq 'plugin')){"
" return;"
"} else {"
//we 'my' $filename,$mtime,$package,$sub to prevent them from changing our state up here.
" eval(\"package $package; my(\\$filename,\\$mtime,\\$package,\\$sub); \\$isloaded = 1; require '$filename'; \");"
"}"
"}"
,FALSE);
//make a tie-able class to capture IO and get it where it needs to go
eval_pv(
"package EQWIO; "
// "&boot_EQEmuIO;"
"sub TIEHANDLE { my $me = bless {}, $_[0]; $me->PRINT('Creating '.$me); return($me); } "
"sub WRITE { } "
"sub PRINTF { my $me = shift; my $fmt = shift; $me->PRINT(sprintf($fmt, @_)); } "
"sub CLOSE { my $me = shift; $me->PRINT('Closing '.$me); } "
"sub DESTROY { my $me = shift; $me->PRINT('Destroying '.$me); } "
//this ties us for all packages
"package MAIN;"
" if(tied *STDOUT) { untie(*STDOUT); }"
" if(tied *STDERR) { untie(*STDERR); }"
" tie *STDOUT, 'EQWIO';"
" tie *STDERR, 'EQWIO';"
,FALSE);
eval_pv(
"package world; "
,FALSE
);
//make sure the EQW pointer is set up in this package
EQW *curc = EQW::Singleton();
SV *l = get_sv("world::EQW", true);
if(curc != NULL) {
sv_setref_pv(l, "EQW", curc);
} else {
//clear out the value, mainly to get rid of blessedness
sv_setsv(l, _empty_sv);
}
//make sure the EQDB pointer is set up in this package
EQDB::SetMySQL(database.getMySQL());
EQDB *curc_db = EQDB::Singleton();
SV *l_db = get_sv("world::EQDB", true);
if(curc_db != NULL) {
sv_setref_pv(l_db, "EQDB", curc_db);
} else {
//clear out the value, mainly to get rid of blessedness
sv_setsv(l_db, _empty_sv);
}
//load up EQW
eval_pv(
"package EQW;"
"&boot_EQW;" //load our EQW XS
"package EQDB;"
"&boot_EQDB;" //load our EQW XS
"package EQDBRes;"
"&boot_EQDBRes;" //load our EQW XS
"package HTTPRequest;"
"&boot_HTTPRequest;" //load our HTTPRequest XS
"package EQLConfig;"
"&boot_EQLConfig;" //load our EQLConfig XS
, FALSE );
#ifdef EMBPERL_PLUGIN
_log(WORLD__PERL, "Loading worldui perl plugins.");
string err;
if(!eval_file("world", "worldui.pl", err)) {
_log(WORLD__PERL_ERR, "Warning - world.pl: %s", err.c_str());
}
eval_pv(
"package world; "
"if(opendir(D,'worldui')) { "
" my @d = readdir(D);"
" closedir(D);"
" foreach(@d){ "
" next unless(/\\.pl$); "
" require 'templates/'.$_;"
" }"
"}"
,FALSE);
#endif //EMBPERL_PLUGIN
}
EQWParser::~EQWParser() {
//removed to try to stop perl from exploding on reload, we'll see
/* eval_pv(
"package quest;"
" untie *STDOUT;"
" untie *STDERR;"
,FALSE);
*/
perl_free(my_perl);
}
bool EQWParser::eval_file(const char * packagename, const char * filename, std::string &error)
{
std::vector<std::string> args;
args.push_back(packagename);
args.push_back(filename);
return(dosub("eval_file", args, error));
}
bool EQWParser::dosub(const char * subname, const std::vector<std::string> &args, string &error, int mode) {
bool err = false;
dSP; /* initialize stack pointer */
ENTER; /* everything created after here */
SAVETMPS; /* ...is a temporary variable. */
PUSHMARK(SP); /* remember the stack pointer */
if(args.size() > 0)
{
for(std::vector<std::string>::const_iterator i = args.begin(); i != args.end(); ++i)
{/* push the arguments onto the perl stack */
XPUSHs(sv_2mortal(newSVpv(i->c_str(), i->length())));
}
}
PUTBACK; /* make local stack pointer global */
call_pv(subname, mode); /*eval our code*/
SPAGAIN; /* refresh stack pointer */
if(SvTRUE(ERRSV)) {
err = true;
}
FREETMPS; /* free temp values */
LEAVE; /* ...and the XPUSHed "mortal" args.*/
if(err) {
error = "Perl runtime error: ";
error += SvPVX(ERRSV);
return(false);
}
return(true);
}
bool EQWParser::eval(const char * code, string &error) {
std::vector<std::string> arg;
arg.push_back(code);
return(dosub("my_eval", arg, error, G_SCALAR|G_DISCARD|G_EVAL|G_KEEPERR));
}
void EQWParser::EQW_eval(const char *pkg, const char *code) {
char namebuf[64];
snprintf(namebuf, 64, "package %s;", pkg);
eval_pv(namebuf, FALSE);
//make sure the EQW pointer is set up
EQW *curc = EQW::Singleton();
snprintf(namebuf, 64, "EQW");
// snprintf(namebuf, 64, "%s::EQW", pkg);
SV *l = get_sv(namebuf, true);
if(curc != NULL) {
sv_setref_pv(l, "EQW", curc);
} else {
//clear out the value, mainly to get rid of blessedness
sv_setsv(l, _empty_sv);
}
//make sure the EQDB pointer is set up
EQDB *curc_db = EQDB::Singleton();
snprintf(namebuf, 64, "EQDB");
// snprintf(namebuf, 64, "%s::EQW", pkg);
SV *l_db = get_sv(namebuf, true);
if(curc_db != NULL) {
sv_setref_pv(l_db, "EQDB", curc_db);
} else {
//clear out the value, mainly to get rid of blessedness
sv_setsv(l_db, _empty_sv);
}
string err;
if(!eval(code, err)) {
EQW::Singleton()->AppendOutput(err.c_str());
}
}
void EQWParser::SetHTTPRequest(const char *pkg, HTTPRequest *it) {
char namebuf[64];
snprintf(namebuf, 64, "package %s;", pkg);
eval_pv(namebuf, FALSE);
snprintf(namebuf, 64, "request");
// snprintf(namebuf, 64, "%s::EQW", pkg);
SV *l = get_sv(namebuf, true);
if(it != NULL) {
sv_setref_pv(l, "HTTPRequest", it);
} else {
//clear out the value, mainly to get rid of blessedness
sv_setsv(l, _empty_sv);
}
}
/*
$editors = array();
$editors["merchant"] = new MerchantEditor();
#... for other editors
if(defined($editors[$editor])) {
$edit = $editors[$editor];
$edit->dispatch($action);
}
class MerchantEditor extends BaseEditor {
MerchantEditor() {
$this->RegisterAction(0, "get_merchantlist", "merchant/merchant.tmpl.php", "no");
$this->RegisterAction(1, "get_merchantlist", "merchant/merchant.edit.tmpl.php", "no");
}
}
function dispatch() {
my $dispatcher = $this->_dispatchers[$action];
$body = new Template($dispatcher["template"]);
my $proc = $dispatcher["proc"];
$vars = $this->$proc();
if($dispatcher["guestmode"] == "no") {
check_authorization();
}
if ($vars) {
foreach ($vars as $key=>$value) {
$body->set($key, $value);
}
}
}
*/
#endif //EMBPERL
+79
View File
@@ -0,0 +1,79 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef EQWPARSER_H_
#define EQWPARSER_H_
#ifdef EMBPERL
#include <string>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <string>
#include "../common/useperl.h"
class HTTPRequest;
class EQWParser {
public:
EQWParser();
~EQWParser();
void EQW_eval(const char *pkg, const char *code);
void SetHTTPRequest(const char *pkg, HTTPRequest *it);
//put an integer into a perl varable
void seti(const char *varname, int val) const {
SV *t = get_sv(varname, true);
sv_setiv(t, val);
}
//put a real into a perl varable
void setd(const char *varname, float val) const {
SV *t = get_sv(varname, true);
sv_setnv(t, val);
}
//put a string into a perl varable
void setstr(const char *varname, const char *val) const {
SV *t = get_sv(varname, true);
sv_setpv(t, val);
}
protected:
void DoInit();
bool eval(const char * code, std::string &error);
bool dosub(const char * subname, const std::vector<std::string> &args, std::string &error, int mode = G_SCALAR|G_DISCARD|G_EVAL);
bool eval_file(const char * packagename, const char * filename, std::string &error);
//the embedded interpreter
PerlInterpreter * my_perl;
SV *_empty_sv;
};
#endif //EMBPERL
#endif /*EQWPARSER_H_*/
+93
View File
@@ -0,0 +1,93 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "HTTPRequest.h"
#include "EQWHTTPHandler.h"
#include "../common/EQDB.h"
#include "../common/SocketLib/HttpdForm.h"
#include <cstdlib>
using namespace std;
HTTPRequest::HTTPRequest(EQWHTTPHandler *h, HttpdForm *form)
: m_handler(h)
{
string name, value;
if(form->getfirst(name, value)) {
m_values[name] = value;
while(form->getnext(name, value))
m_values[name] = value;
}
}
const char *HTTPRequest::getEscaped(const char *name, const char *default_value) const {
return(EQDB::Singleton()->escape_string(get(name, default_value)));
}
const char *HTTPRequest::get(const char *name, const char *default_value) const {
std::map<std::string, std::string>::const_iterator res;
res = m_values.find(name);
if(res == m_values.end())
return(default_value);
return(res->second.c_str());
}
map<string,string> HTTPRequest::get_all() const {
return m_values;
}
int HTTPRequest::getInt(const char *name, int default_value) const {
std::map<std::string, std::string>::const_iterator res;
res = m_values.find(name);
if(res == m_values.end())
return(default_value);
return(atoi(res->second.c_str()));
}
float HTTPRequest::getFloat(const char *name, float default_value) const {
std::map<std::string, std::string>::const_iterator res;
res = m_values.find(name);
if(res == m_values.end())
return(default_value);
return(atof(res->second.c_str()));
}
void HTTPRequest::header(Const_char *name, Const_char *value) {
m_handler->AddResponseHeader(name, value);
}
void HTTPRequest::SetResponseCode(Const_char *code) {
m_handler->SetResponseCode(code);
}
void HTTPRequest::redirect(Const_char *URL) {
header("Location", URL);
SetResponseCode("302");
}
+64
View File
@@ -0,0 +1,64 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef HTTPREQUEST_H_
#define HTTPREQUEST_H_
#include "../common/types.h"
#include <map>
#include <string>
//this object acts as a friendlier interface to the HttpdForm object (perl exportable)
//which does more effecient lookups
class HttpdForm;
class EQWHTTPHandler;
using namespace std;
class HTTPRequest {
public:
HTTPRequest(EQWHTTPHandler *h, HttpdForm *form);
//BEGIN PERL EXPORT
Const_char * get(Const_char *name, Const_char *default_value = "") const;
int getInt(Const_char *name, int default_value = 0) const;
float getFloat(Const_char *name, float default_value = 0.0) const;
//returns a database-safe string
Const_char * getEscaped(Const_char *name, Const_char *default_value = "") const;
map<string,string> get_all() const;
void redirect(Const_char *URL);
void SetResponseCode(Const_char *code);
void header(Const_char *name, Const_char *value);
//END PERL EXPORT
protected:
EQWHTTPHandler *const m_handler;
std::map<std::string, std::string> m_values;
};
#endif /*HTTPREQUEST_H_*/
+368
View File
@@ -0,0 +1,368 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "LauncherLink.h"
#include "LauncherList.h"
#include "WorldConfig.h"
#include "../common/logsys.h"
#include "../common/md5.h"
#include "../common/packet_dump.h"
#include "../common/servertalk.h"
#include "../common/EmuTCPConnection.h"
#include "worlddb.h"
#include "EQLConfig.h"
#include <vector>
#include <string>
using namespace std;
extern LauncherList launcher_list;
LauncherLink::LauncherLink(int id, EmuTCPConnection *c)
: ID(id),
tcpc(c),
authenticated(false),
m_name(""),
m_bootTimer(2000)
{
m_dynamicCount = 0;
m_bootTimer.Disable();
}
LauncherLink::~LauncherLink() {
tcpc->Free();
}
bool LauncherLink::Process() {
if (!tcpc->Connected())
return false;
if(m_bootTimer.Check(false)) {
//force a boot on any zone which isnt running.
std::map<std::string, ZoneState>::iterator cur, end;
cur = m_states.begin();
end = m_states.end();
for(; cur != end; cur++) {
if(!cur->second.up) {
StartZone(cur->first.c_str());
}
}
m_bootTimer.Disable();
}
ServerPacket *pack = 0;
while((pack = tcpc->PopPacket())) {
_hex(WORLD__ZONE_TRACE,pack->pBuffer,pack->size);
if (!authenticated) {
if (WorldConfig::get()->SharedKey.length() > 0) {
if (pack->opcode == ServerOP_ZAAuth && pack->size == 16) {
uint8 tmppass[16];
MD5::Generate((const uchar*) WorldConfig::get()->SharedKey.c_str(), WorldConfig::get()->SharedKey.length(), tmppass);
if (memcmp(pack->pBuffer, tmppass, 16) == 0)
authenticated = true;
else {
struct in_addr in;
in.s_addr = GetIP();
_log(WORLD__LAUNCH_ERR, "Launcher authorization failed.");
ServerPacket* pack = new ServerPacket(ServerOP_ZAAuthFailed);
SendPacket(pack);
delete pack;
Disconnect();
return false;
}
}
else {
struct in_addr in;
in.s_addr = GetIP();
_log(WORLD__LAUNCH_ERR, "Launcher authorization failed.");
ServerPacket* pack = new ServerPacket(ServerOP_ZAAuthFailed);
SendPacket(pack);
delete pack;
Disconnect();
return false;
}
}
else
{
_log(WORLD__LAUNCH,"**WARNING** You have not configured a world shared key in your config file. You should add a <key>STRING</key> element to your <world> element to prevent unauthroized zone access.");
authenticated = true;
}
delete pack;
continue;
}
switch(pack->opcode) {
case 0:
break;
case ServerOP_KeepAlive: {
// ignore this
break;
}
case ServerOP_ZAAuth: {
_log(WORLD__LAUNCH, "Got authentication from %s when they are already authenticated.", m_name.c_str());
break;
}
case ServerOP_LauncherConnectInfo: {
const LauncherConnectInfo *it = (const LauncherConnectInfo *) pack->pBuffer;
if(HasName()) {
_log(WORLD__LAUNCH_ERR, "Launcher '%s' received an additional connect packet with name '%s'. Ignoring.", m_name.c_str(), it->name);
break;
}
m_name = it->name;
EQLConfig *config = launcher_list.GetConfig(m_name.c_str());
if(config == NULL) {
_log(WORLD__LAUNCH, "Unknown launcher '%s' connected. Disconnecting.", it->name);
Disconnect();
break;
}
_log(WORLD__LAUNCH, "Launcher Identified itself as '%s'. Loading zone list.", it->name);
std::vector<LauncherZone> result;
//database.GetLauncherZones(it->name, result);
config->GetZones(result);
std::vector<LauncherZone>::iterator cur, end;
cur = result.begin();
end = result.end();
ZoneState zs;
for(; cur != end; cur++) {
zs.port = cur->port;
zs.up = false;
zs.starts = 0;
_log(WORLD__LAUNCH_TRACE, "%s: Loaded zone '%s' on port %d", m_name.c_str(), cur->name.c_str(), zs.port);
m_states[cur->name] = zs;
}
//now we add all the dynamics.
BootDynamics(config->GetDynamicCount());
m_bootTimer.Start();
break;
}
case ServerOP_LauncherZoneStatus: {
const LauncherZoneStatus *it = (const LauncherZoneStatus *) pack->pBuffer;
std::map<std::string, ZoneState>::iterator res;
res = m_states.find(it->short_name);
if(res == m_states.end()) {
_log(WORLD__LAUNCH_ERR, "%s: reported state for zone %s which it does not have.", m_name.c_str(), it->short_name);
break;
}
_log(WORLD__LAUNCH, "%s: %s reported state %s (%d starts)", m_name.c_str(), it->short_name, it->running?"STARTED":"STOPPED", it->start_count);
res->second.up = it->running;
res->second.starts = it->start_count;
break;
}
default:
{
_log(WORLD__LAUNCH_ERR, "Unknown ServerOPcode from launcher 0x%04x, size %d",pack->opcode,pack->size);
DumpPacket(pack->pBuffer, pack->size);
break;
}
}
delete pack;
}
return(true);
}
bool LauncherLink::ContainsZone(const char *short_name) const {
return(m_states.find(short_name) != m_states.end());
/*
* std::map<std::string, bool>::const_iterator cur, end;
cur = m_states.begin();
end = m_states.end();
for(; cur != end; cur++) {
if(
}*/
}
void LauncherLink::BootZone(const char *short_name, uint16 port) {
ZoneState zs;
zs.port = port;
zs.up = false;
zs.starts = 0;
_log(WORLD__LAUNCH_TRACE, "%s: Loaded zone '%s' on port %d", m_name.c_str(), short_name, zs.port);
m_states[short_name] = zs;
StartZone(short_name);
}
void LauncherLink::StartZone(const char *short_name) {
ServerPacket* pack = new ServerPacket(ServerOP_LauncherZoneRequest, sizeof(LauncherZoneRequest));
LauncherZoneRequest* s = (LauncherZoneRequest *) pack->pBuffer;
strn0cpy(s->short_name, short_name, 32);
s->command = ZR_Start;
SendPacket(pack);
delete pack;
}
void LauncherLink::RestartZone(const char *short_name) {
ServerPacket* pack = new ServerPacket(ServerOP_LauncherZoneRequest, sizeof(LauncherZoneRequest));
LauncherZoneRequest* s = (LauncherZoneRequest *) pack->pBuffer;
strn0cpy(s->short_name, short_name, 32);
s->command = ZR_Restart;
SendPacket(pack);
delete pack;
}
void LauncherLink::StopZone(const char *short_name) {
ServerPacket* pack = new ServerPacket(ServerOP_LauncherZoneRequest, sizeof(LauncherZoneRequest));
LauncherZoneRequest* s = (LauncherZoneRequest *) pack->pBuffer;
strn0cpy(s->short_name, short_name, 32);
s->command = ZR_Stop;
SendPacket(pack);
delete pack;
}
void LauncherLink::BootDynamics(uint8 new_count) {
if(m_dynamicCount == new_count)
return;
ZoneState zs;
if(m_dynamicCount < new_count) {
//we are booting more dynamics.
zs.port = 0;
zs.up = false;
zs.starts = 0;
int r;
char nbuf[20];
uint8 index;
//"for each zone we need to boot"
for(r = m_dynamicCount; r < new_count; r++) {
//find an idle ID
for(index = m_dynamicCount+1; index < 255; index++) {
sprintf(nbuf, "dynamic_%02d", index);
if(m_states.find(nbuf) != m_states.end())
continue;
m_states[nbuf] = zs;
StartZone(nbuf);
break;
}
}
m_dynamicCount = new_count;
} else if(new_count == 0) {
//kill all zones...
std::map<std::string, ZoneState>::iterator cur, end;
cur = m_states.begin();
end = m_states.end();
for(; cur != end; cur++) {
StopZone(cur->first.c_str());
}
} else {
//need to get rid of some zones...
//quick and dirty way to do this.. should do better (like looking for idle zones)
int found = 0;
std::map<std::string, ZoneState>::iterator cur, end;
cur = m_states.begin();
end = m_states.end();
for(; cur != end; cur++) {
if(cur->first.find("dynamic_") == 0) {
if(found >= new_count) {
//this zone exceeds the number of allowed booted zones.
StopZone(cur->first.c_str());
} else {
found++;
}
}
}
m_dynamicCount = new_count;
}
}
void LauncherLink::GetZoneList(std::vector<std::string> &l) {
std::map<std::string, ZoneState>::iterator cur, end;
cur = m_states.begin();
end = m_states.end();
for(; cur != end; cur++) {
l.push_back(cur->first.c_str());
}
}
void LauncherLink::GetZoneDetails(const char *short_name, std::map<std::string,std::string> &res) {
res.clear();
std::map<std::string, ZoneState>::iterator r;
r = m_states.find(short_name);
if(r == m_states.end()) {
res["error"] = "Zone Not Found";
res["name"] = short_name;
res["up"] = "0";
res["starts"] = "0";
res["port"] = "0";
} else {
res["name"] = r->first;
res["up"] = r->second.up?"1":"0";
res["starts"] = itoa(r->second.starts);
res["port"] = itoa(r->second.port);
}
}
void LauncherLink::Shutdown() {
ServerPacket* pack = new ServerPacket(ServerOP_ShutdownAll);
SendPacket(pack);
delete pack;
}
+81
View File
@@ -0,0 +1,81 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef LAUNCHERLINK_H_
#define LAUNCHERLINK_H_
#include "../common/EmuTCPConnection.h"
#include "../common/timer.h"
#include <string>
#include <vector>
#include <map>
class ServerPacket;
class LauncherLink {
public:
LauncherLink(int id, EmuTCPConnection *tcpc);
~LauncherLink();
bool Process();
bool SendPacket(ServerPacket* pack) { return tcpc->SendPacket(pack); }
// bool SendPacket(TCPConnection::TCPNetPacket_Struct* tnps) { return tcpc->SendPacket(tnps); }
int GetID() const { return(ID); }
void Disconnect() { tcpc->Disconnect(); }
inline bool HasName() const { return(m_name.length() > 0); }
inline uint32 GetIP() const { return tcpc->GetrIP(); }
inline uint16 GetPort() const { return tcpc->GetrPort(); }
inline const char * GetName() const { return(m_name.c_str()); }
inline int CountZones() const { return(m_states.size()); }
bool ContainsZone(const char *short_name) const;
//commands
void Shutdown();
void BootZone(const char *short_name, uint16 port);
void StartZone(const char *short_name);
void RestartZone(const char *short_name);
void StopZone(const char *short_name);
void BootDynamics(uint8 new_total);
void GetZoneList(std::vector<std::string> &list);
void GetZoneDetails(const char *short_name, std::map<std::string,std::string> &result);
protected:
const int ID;
EmuTCPConnection*const tcpc;
bool authenticated;
std::string m_name;
Timer m_bootTimer;
uint8 m_dynamicCount;
typedef struct {
bool up;
uint32 starts; //number of times this zone has started
uint16 port; //the port this zone wants to use (0=pick one)
} ZoneState;
std::map<std::string, ZoneState> m_states;
};
#endif /*LAUNCHERLINK_H_*/
+222
View File
@@ -0,0 +1,222 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "LauncherList.h"
#include "LauncherLink.h"
#include "../common/logsys.h"
#include "EQLConfig.h"
using namespace std;
LauncherList::LauncherList()
: nextID(1)
{
}
LauncherList::~LauncherList() {
vector<LauncherLink *>::iterator cur, end;
cur = m_pendingLaunchers.begin();
end = m_pendingLaunchers.end();
for(; cur != end; cur++) {
delete *cur;
}
map<string, EQLConfig *>::iterator curc, endc;
curc = m_configs.begin();
endc = m_configs.end();
for(; curc != endc; curc++) {
delete curc->second;
}
map<string, LauncherLink *>::iterator curl, endl;
curl = m_launchers.begin();
endl = m_launchers.end();
for(; curl != endl; curl++) {
delete curl->second;
}
}
void LauncherList::Process() {
//process pending launchers..
vector<LauncherLink *>::iterator cur, end;
cur = m_pendingLaunchers.begin();
while(cur != m_pendingLaunchers.end()) {
LauncherLink *l = *cur;
//printf("ProcP %d: %p\n", l->GetID(), l);
if(!l->Process()) {
//launcher has died before it identified itself.
_log(WORLD__LAUNCH, "Removing pending launcher %d", l->GetID());
cur = m_pendingLaunchers.erase(cur);
delete l;
} else if(l->HasName()) {
//launcher has identified itself now.
//remove ourself from the pending list
cur = m_pendingLaunchers.erase(cur);
string name = l->GetName();
//kill off anybody else using our name.
map<string, LauncherLink *>::iterator res;
res = m_launchers.find(name);
if(res != m_launchers.end()) {
_log(WORLD__LAUNCH, "Ghosting launcher %s", name.c_str());
delete res->second;
}
_log(WORLD__LAUNCH, "Removing pending launcher %d. Adding %s to active list.", l->GetID(), name.c_str());
//put the launcher in the list.
m_launchers[name] = l;
} else {
cur++;
}
}
//process active launchers.
map<string, LauncherLink *>::iterator curl, tmp;
curl = m_launchers.begin();
while(curl != m_launchers.end()) {
LauncherLink *l = curl->second;
//printf("Proc %s(%d): %p\n", l->GetName(), l->GetID(), l);
if(!l->Process()) {
//launcher has died before it identified itself.
_log(WORLD__LAUNCH, "Removing launcher %s (%d)", l->GetName(), l->GetID());
tmp = curl;
curl++;
m_launchers.erase(tmp);
delete l;
} else {
curl++;
}
}
}
LauncherLink *LauncherList::Get(const char *name) {
map<string, LauncherLink *>::iterator res;
res = m_launchers.find(name);
if(res == m_launchers.end())
return(NULL);
return(res->second);
/* string goal(name);
vector<LauncherLink *>::iterator cur, end;
cur = m_launchers.begin();
end = m_launchers.end();
for(; cur != end; cur++) {
if(goal == (*cur)->GetName())
return(*cur);
}
return(NULL);*/
}
LauncherLink *LauncherList::FindByZone(const char *short_name) {
map<string, LauncherLink *>::iterator cur, end;
cur = m_launchers.begin();
end = m_launchers.end();
for(; cur != end; cur++) {
if(cur->second->ContainsZone(short_name))
return(cur->second);
}
return(NULL);
}
void LauncherList::Add(EmuTCPConnection *conn) {
LauncherLink *it = new LauncherLink(nextID++, conn);
_log(WORLD__LAUNCH, "Adding pending launcher %d", it->GetID());
m_pendingLaunchers.push_back(it);
}
int LauncherList::GetLauncherCount() {
return(m_launchers.size());
}
void LauncherList::GetLauncherNameList(std::vector<string> &res) {
map<string, EQLConfig *>::iterator cur, end;
cur = m_configs.begin();
end = m_configs.end();
for(; cur != end; cur++) {
res.push_back(cur->first);
}
}
void LauncherList::LoadList() {
vector<string> launchers;
database.GetLauncherList(launchers);
vector<string>::iterator cur, end;
cur = launchers.begin();
end = launchers.end();
for(; cur != end; cur++) {
m_configs[*cur] = new EQLConfig(cur->c_str());
}
}
EQLConfig *LauncherList::GetConfig(const char *name) {
map<string, EQLConfig *>::iterator res;
res = m_configs.find(name);
if(res == m_configs.end()) {
return(NULL);
}
return(res->second);
}
void LauncherList::CreateLauncher(const char *name, uint8 dynamic_count) {
m_configs[name] = EQLConfig::CreateLauncher(name, dynamic_count);
}
void LauncherList::Remove(const char *name) {
map<string, EQLConfig *>::iterator resc;
resc = m_configs.find(name);
if(resc != m_configs.end()) {
delete resc->second;
m_configs.erase(resc);
}
map<string, LauncherLink *>::iterator resl;
resl = m_launchers.find(name);
if(resl != m_launchers.end()) {
resl->second->Disconnect();
}
}
+67
View File
@@ -0,0 +1,67 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef LAUNCHERLIST_H_
#define LAUNCHERLIST_H_
#include "../common/types.h"
#include <map>
#include <vector>
#include <string>
class LauncherLink;
class EmuTCPConnection;
class EQLConfig;
class LauncherList {
public:
LauncherList();
~LauncherList();
void Process();
void LoadList();
EQLConfig *GetConfig(const char *name);
void CreateLauncher(const char *name, uint8 dynamic_count);
void Remove(const char *name);
void Add(EmuTCPConnection *conn);
LauncherLink *Get(const char *name);
LauncherLink *FindByZone(const char *short_name);
int GetLauncherCount();
void GetLauncherNameList(std::vector<std::string> &list);
protected:
std::map<std::string, EQLConfig *> m_configs; //we own these objects
std::map<std::string, LauncherLink *> m_launchers; //we own these objects
// std::map<std::string, EQLConfig *> m_configs; //we own these objects
std::vector<LauncherLink *> m_pendingLaunchers; //we own these objects, have not yet identified themself
int nextID;
};
#endif /*LAUNCHERLIST_H_*/
+339
View File
@@ -0,0 +1,339 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include <iostream>
using namespace std;
#include <string.h>
#include <stdio.h>
#include <iomanip>
using namespace std;
#include <stdlib.h>
#include "../common/version.h"
#ifdef _WINDOWS
#include <process.h>
#include <windows.h>
#include <winsock.h>
#define snprintf _snprintf
#if (_MSC_VER < 1500)
#define vsnprintf _vsnprintf
#endif
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#else // Pyro: fix for linux
#include <sys/socket.h>
#ifdef FREEBSD //Timothy Whitman - January 7, 2003
#include <sys/types.h>
#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include "../common/unix.h"
#define SOCKET_ERROR -1
#define INVALID_SOCKET -1
extern int errno;
#endif
#define IGNORE_LS_FATAL_ERROR
#include "../common/servertalk.h"
#include "LoginServer.h"
#include "LoginServerList.h"
#include "../common/eq_packet_structs.h"
#include "../common/packet_dump.h"
#include "../common/MiscFunctions.h"
#include "zoneserver.h"
#include "worlddb.h"
#include "zonelist.h"
#include "clientlist.h"
#include "WorldConfig.h"
extern ZSList zoneserver_list;
extern ClientList client_list;
extern uint32 numzones;
extern uint32 numplayers;
extern volatile bool RunLoops;
LoginServer::LoginServer(const char* iAddress, uint16 iPort, const char* Account, const char* Password)
: statusupdate_timer(LoginServer_StatusUpdateInterval)
{
strn0cpy(LoginServerAddress,iAddress,256);
LoginServerPort = iPort;
strn0cpy(LoginAccount,Account,31);
strn0cpy(LoginPassword,Password,31);
CanAccountUpdate = false;
tcpc = new EmuTCPConnection(true);
tcpc->SetPacketMode(EmuTCPConnection::packetModeLogin);
}
LoginServer::~LoginServer() {
delete tcpc;
}
bool LoginServer::Process() {
const WorldConfig *Config=WorldConfig::get();
if (statusupdate_timer.Check()) {
this->SendStatus();
}
/************ Get all packets from packet manager out queue and process them ************/
ServerPacket *pack = 0;
while((pack = tcpc->PopPacket()))
{
_log(WORLD__LS_TRACE,"Recevied ServerPacket from LS OpCode 0x04x",pack->opcode);
_hex(WORLD__LS_TRACE,pack->pBuffer,pack->size);
switch(pack->opcode) {
case 0:
break;
case ServerOP_KeepAlive: {
// ignore this
break;
}
case ServerOP_UsertoWorldReq: {
UsertoWorldRequest_Struct* utwr = (UsertoWorldRequest_Struct*) pack->pBuffer;
uint32 id = database.GetAccountIDFromLSID(utwr->lsaccountid);
int16 status = database.CheckStatus(id);
ServerPacket* outpack = new ServerPacket;
outpack->opcode = ServerOP_UsertoWorldResp;
outpack->size = sizeof(UsertoWorldResponse_Struct);
outpack->pBuffer = new uchar[outpack->size];
memset(outpack->pBuffer, 0, outpack->size);
UsertoWorldResponse_Struct* utwrs = (UsertoWorldResponse_Struct*) outpack->pBuffer;
utwrs->lsaccountid = utwr->lsaccountid;
utwrs->ToID = utwr->FromID;
if(Config->Locked == true)
{
if((status == 0 || status < 100) && (status != -2 || status != -1))
utwrs->response = 0;
if(status >= 100)
utwrs->response = 1;
}
else {
utwrs->response = 1;
}
int32 x = Config->MaxClients;
if( (int32)numplayers >= x && x != -1 && x != 255 && status < 80)
utwrs->response = -3;
if(status == -1)
utwrs->response = -1;
if(status == -2)
utwrs->response = -2;
utwrs->worldid = utwr->worldid;
SendPacket(outpack);
delete outpack;
break;
}
case ServerOP_LSClientAuth: {
ServerLSClientAuth* slsca = (ServerLSClientAuth*) pack->pBuffer;
if (RuleI(World, AccountSessionLimit) >= 0) {
// Enforce the limit on the number of characters on the same account that can be
// online at the same time.
client_list.EnforceSessionLimit(slsca->lsaccount_id);
}
client_list.CLEAdd(slsca->lsaccount_id, slsca->name, slsca->key, slsca->worldadmin, slsca->ip, slsca->local);
break;
}
case ServerOP_LSFatalError: {
#ifndef IGNORE_LS_FATAL_ERROR
WorldConfig::DisableLoginserver();
_log(WORLD__LS_ERR, "Login server responded with FatalError. Disabling reconnect.");
#else
_log(WORLD__LS_ERR, "Login server responded with FatalError.");
#endif
if (pack->size > 1) {
_log(WORLD__LS_ERR, " %s",pack->pBuffer);
}
break;
}
case ServerOP_SystemwideMessage: {
ServerSystemwideMessage* swm = (ServerSystemwideMessage*) pack->pBuffer;
zoneserver_list.SendEmoteMessageRaw(0, 0, 0, swm->type, swm->message);
break;
}
case ServerOP_LSRemoteAddr: {
if (!Config->WorldAddress.length()) {
WorldConfig::SetWorldAddress((char *)pack->pBuffer);
_log(WORLD__LS, "Loginserver provided %s as world address",pack->pBuffer);
}
break;
}
case ServerOP_LSAccountUpdate: {
_log(WORLD__LS, "Received ServerOP_LSAccountUpdate packet from loginserver");
CanAccountUpdate = true;
break;
}
default:
{
_log(WORLD__LS_ERR, "Unknown LSOpCode: 0x%04x size=%d",(int)pack->opcode,pack->size);
DumpPacket(pack->pBuffer, pack->size);
break;
}
}
delete pack;
}
return true;
}
bool LoginServer::InitLoginServer() {
if(Connected() == false) {
if(ConnectReady()) {
_log(WORLD__LS, "Connecting to login server: %s:%d",LoginServerAddress,LoginServerPort);
Connect();
} else {
_log(WORLD__LS_ERR, "Not connected but not ready to connect, this is bad: %s:%d",
LoginServerAddress,LoginServerPort);
}
}
return true;
}
bool LoginServer::Connect() {
char tmp[25];
if(database.GetVariable("loginType",tmp,sizeof(tmp)) && strcasecmp(tmp,"MinILogin") == 0){
minilogin = true;
_log(WORLD__LS, "Setting World to MiniLogin Server type");
}
else
minilogin = false;
if (minilogin && WorldConfig::get()->WorldAddress.length()==0) {
_log(WORLD__LS_ERR, "**** For minilogin to work, you need to set the <address> element in the <world> section.");
return false;
}
char errbuf[TCPConnection_ErrorBufferSize];
if ((LoginServerIP = ResolveIP(LoginServerAddress, errbuf)) == 0) {
_log(WORLD__LS_ERR, "Unable to resolve '%s' to an IP.",LoginServerAddress);
return false;
}
if (LoginServerIP == 0 || LoginServerPort == 0) {
_log(WORLD__LS_ERR, "Connect info incomplete, cannot connect: %s:%d",LoginServerAddress,LoginServerPort);
return false;
}
if (tcpc->ConnectIP(LoginServerIP, LoginServerPort, errbuf)) {
_log(WORLD__LS, "Connected to Loginserver: %s:%d",LoginServerAddress,LoginServerPort);
if (minilogin)
SendInfo();
else
SendNewInfo();
SendStatus();
zoneserver_list.SendLSZones();
return true;
}
else {
_log(WORLD__LS_ERR, "Could not connect to login server: %s:%d %s",LoginServerAddress,LoginServerPort,errbuf);
return false;
}
}
void LoginServer::SendInfo() {
const WorldConfig *Config=WorldConfig::get();
ServerPacket* pack = new ServerPacket;
pack->opcode = ServerOP_LSInfo;
pack->size = sizeof(ServerLSInfo_Struct);
pack->pBuffer = new uchar[pack->size];
memset(pack->pBuffer, 0, pack->size);
ServerLSInfo_Struct* lsi = (ServerLSInfo_Struct*) pack->pBuffer;
strcpy(lsi->protocolversion, EQEMU_PROTOCOL_VERSION);
strcpy(lsi->serverversion, CURRENT_VERSION);
strcpy(lsi->name, Config->LongName.c_str());
strcpy(lsi->account, LoginAccount);
strcpy(lsi->password, LoginPassword);
strcpy(lsi->address, Config->WorldAddress.c_str());
SendPacket(pack);
delete pack;
}
void LoginServer::SendNewInfo() {
uint16 port;
const WorldConfig *Config=WorldConfig::get();
ServerPacket* pack = new ServerPacket;
pack->opcode = ServerOP_NewLSInfo;
pack->size = sizeof(ServerNewLSInfo_Struct);
pack->pBuffer = new uchar[pack->size];
memset(pack->pBuffer, 0, pack->size);
ServerNewLSInfo_Struct* lsi = (ServerNewLSInfo_Struct*) pack->pBuffer;
strcpy(lsi->protocolversion, EQEMU_PROTOCOL_VERSION);
strcpy(lsi->serverversion, CURRENT_VERSION);
strcpy(lsi->name, Config->LongName.c_str());
strcpy(lsi->shortname, Config->ShortName.c_str());
strcpy(lsi->account, LoginAccount);
strcpy(lsi->password, LoginPassword);
if (Config->WorldAddress.length())
strcpy(lsi->remote_address, Config->WorldAddress.c_str());
if (Config->LocalAddress.length())
strcpy(lsi->local_address, Config->LocalAddress.c_str());
else {
tcpc->GetSockName(lsi->local_address,&port);
WorldConfig::SetLocalAddress(lsi->local_address);
}
SendPacket(pack);
delete pack;
}
void LoginServer::SendStatus() {
statusupdate_timer.Start();
ServerPacket* pack = new ServerPacket;
pack->opcode = ServerOP_LSStatus;
pack->size = sizeof(ServerLSStatus_Struct);
pack->pBuffer = new uchar[pack->size];
memset(pack->pBuffer, 0, pack->size);
ServerLSStatus_Struct* lss = (ServerLSStatus_Struct*) pack->pBuffer;
if (WorldConfig::get()->Locked)
lss->status = -2;
else if (numzones <= 0)
lss->status = -2;
else
lss->status = numplayers;
lss->num_zones = numzones;
lss->num_players = numplayers;
SendPacket(pack);
delete pack;
}
void LoginServer::SendAccountUpdate(ServerPacket* pack) {
ServerLSAccountUpdate_Struct* s = (ServerLSAccountUpdate_Struct *) pack->pBuffer;
if(CanUpdate()) {
_log(WORLD__LS, "Sending ServerOP_LSAccountUpdate packet to loginserver: %s:%d",LoginServerAddress,LoginServerPort);
strn0cpy(s->worldaccount, LoginAccount, 30);
strn0cpy(s->worldpassword, LoginPassword, 30);
SendPacket(pack);
}
}
+62
View File
@@ -0,0 +1,62 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef LOGINSERVER_H
#define LOGINSERVER_H
#include "../common/servertalk.h"
#include "../common/linked_list.h"
#include "../common/timer.h"
#include "../common/queue.h"
#include "../common/eq_packet_structs.h"
#include "../common/Mutex.h"
#include "../common/EmuTCPConnection.h"
class LoginServer{
public:
LoginServer(const char*, uint16, const char*, const char*);
~LoginServer();
bool InitLoginServer();
bool Process();
bool Connect();
void SendInfo();
void SendNewInfo();
void SendStatus();
void SendPacket(ServerPacket* pack) { tcpc->SendPacket(pack); }
void SendAccountUpdate(ServerPacket* pack);
bool ConnectReady() { return tcpc->ConnectReady(); }
bool Connected() { return tcpc->Connected(); }
bool MiniLogin() { return minilogin; }
bool CanUpdate() { return CanAccountUpdate; }
private:
bool minilogin;
EmuTCPConnection* tcpc;
char LoginServerAddress[256];
uint32 LoginServerIP;
uint16 LoginServerPort;
char LoginAccount[32];
char LoginPassword[32];
bool CanAccountUpdate;
Timer statusupdate_timer;
};
#endif
+197
View File
@@ -0,0 +1,197 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include <iostream>
using namespace std;
#include <string.h>
#include <stdio.h>
#include <iomanip>
using namespace std;
#include <stdlib.h>
#include "../common/version.h"
#define IGNORE_LS_FATAL_ERROR
#include "../common/servertalk.h"
#include "LoginServer.h"
#include "LoginServerList.h"
#include "../common/eq_packet_structs.h"
#include "../common/packet_dump.h"
#include "zoneserver.h"
#include "worlddb.h"
#include "zonelist.h"
#include "clientlist.h"
#include "WorldConfig.h"
extern ZSList zoneserver_list;
extern LoginServerList loginserverlist;
extern ClientList client_list;
extern uint32 numzones;
extern uint32 numplayers;
extern volatile bool RunLoops;
LoginServerList::LoginServerList() {
}
LoginServerList::~LoginServerList() {
}
void LoginServerList::Add(const char* iAddress, uint16 iPort, const char* Account, const char* Password)
{
LoginServer* loginserver = new LoginServer(iAddress, iPort, Account, Password);
list.Insert(loginserver);
}
bool LoginServerList::Process() {
LinkedListIterator<LoginServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()){
iterator.GetData()->Process();
iterator.Advance();
}
return true;
}
#ifdef _WINDOWS
void AutoInitLoginServer(void *tmp) {
#else
void *AutoInitLoginServer(void *tmp) {
#endif
loginserverlist.InitLoginServer();
#ifndef WIN32
return 0;
#endif
}
void LoginServerList::InitLoginServer() {
LinkedListIterator<LoginServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()){
iterator.GetData()->InitLoginServer();
iterator.Advance();
}
}
bool LoginServerList::SendInfo() {
LinkedListIterator<LoginServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()){
iterator.GetData()->SendInfo();
iterator.Advance();
}
return true;
}
bool LoginServerList::SendNewInfo() {
LinkedListIterator<LoginServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()){
iterator.GetData()->SendNewInfo();
iterator.Advance();
}
return true;
}
bool LoginServerList::SendStatus() {
LinkedListIterator<LoginServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()){
iterator.GetData()->SendStatus();
iterator.Advance();
}
return true;
}
bool LoginServerList::SendPacket(ServerPacket* pack) {
LinkedListIterator<LoginServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()){
iterator.GetData()->SendPacket(pack);
iterator.Advance();
}
return true;
}
bool LoginServerList::SendAccountUpdate(ServerPacket* pack) {
LinkedListIterator<LoginServer*> iterator(list);
_log(WORLD__LS, "Requested to send ServerOP_LSAccountUpdate packet to all loginservers");
iterator.Reset();
while(iterator.MoreElements()){
if(iterator.GetData()->CanUpdate()) {
iterator.GetData()->SendAccountUpdate(pack);
}
iterator.Advance();
}
return true;
}
bool LoginServerList::Connected() {
LinkedListIterator<LoginServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()){
if(iterator.GetData()->Connected())
return true;
iterator.Advance();
}
return false;
}
bool LoginServerList::AllConnected() {
LinkedListIterator<LoginServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()){
if(iterator.GetData()->Connected() == false)
return false;
iterator.Advance();
}
return true;
}
bool LoginServerList::MiniLogin() {
LinkedListIterator<LoginServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()){
if(iterator.GetData()->MiniLogin())
return true;
iterator.Advance();
}
return false;
}
bool LoginServerList::CanUpdate() {
LinkedListIterator<LoginServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()){
if(iterator.GetData()->CanUpdate())
return true;
iterator.Advance();
}
return false;
}
+48
View File
@@ -0,0 +1,48 @@
#ifndef LOGINSERVERLIST_H_
#define LOGINSERVERLIST_H_
#include "../common/servertalk.h"
#include "../common/linked_list.h"
#include "../common/timer.h"
#include "../common/queue.h"
#include "../common/eq_packet_structs.h"
#include "../common/Mutex.h"
#include "../common/EmuTCPConnection.h"
#ifdef _WINDOWS
void AutoInitLoginServer(void *tmp);
#else
void *AutoInitLoginServer(void *tmp);
#endif
class LoginServer;
class LoginServerList{
public:
LoginServerList();
~LoginServerList();
void Add(const char*, uint16, const char*, const char*);
void InitLoginServer();
bool Process();
bool SendInfo();
bool SendNewInfo();
bool SendStatus();
bool SendPacket(ServerPacket *pack);
bool SendAccountUpdate(ServerPacket *pack);
bool Connected();
bool AllConnected();
bool MiniLogin();
bool CanUpdate();
protected:
LinkedList<LoginServer*> list;
};
#endif /*LOGINSERVERLIST_H_*/
+31
View File
@@ -0,0 +1,31 @@
#ifndef SOFCHARCREATEDATA_H
#define SOFCHARCREATEDATA_H
#pragma pack(1)
struct RaceClassAllocation {
unsigned int Index;
unsigned int BaseStats[7];
unsigned int DefaultPointAllocation[7];
};
struct RaceClassCombos {
unsigned int ExpansionRequired;
unsigned int Race;
unsigned int Class;
unsigned int Deity;
unsigned int AllocationIndex;
unsigned int Zone;
};
/*struct SoFCCData {
unsigned char Unknown;
unsigned int RaceClassStatEntryCount;
SoFCCRaceClassData RCData[109];
unsigned int Unknown2;
SoFCCStartZoneData StartZoneData[641];
};
*/
#pragma pack()
#endif
+54
View File
@@ -0,0 +1,54 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "WorldConfig.h"
WorldConfig *WorldConfig::_world_config = NULL;
string WorldConfig::GetByName(const string &var_name) const {
if(var_name == "UpdateStats")
return(UpdateStats?"true":"false");
if(var_name == "LoginDisabled")
return(LoginDisabled?"true":"false");
return(EQEmuConfig::GetByName(var_name));
}
+74
View File
@@ -0,0 +1,74 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WorldConfig_H
#define __WorldConfig_H
#include "../common/EQEmuConfig.h"
class WorldConfig : public EQEmuConfig {
public:
virtual string GetByName(const string &var_name) const;
bool UpdateStats;
bool LoginDisabled;
private:
static WorldConfig *_world_config;
WorldConfig() : EQEmuConfig() {
LoginDisabled=false;
UpdateStats=true;
}
public:
// Produce a const singleton
static const WorldConfig *get() {
if (_world_config == NULL)
LoadConfig();
return(_world_config);
}
// Load the config
static bool LoadConfig() {
if (_world_config != NULL)
delete _world_config;
_world_config=new WorldConfig;
_config=_world_config;
return _config->ParseFile(EQEmuConfig::ConfigFile.c_str(),"server");
}
// Accessors for the static private object
static void LockWorld() { if (_world_config) _world_config->Locked=true; }
static void UnlockWorld() { if (_world_config) _world_config->Locked=false; }
static void DisableStats() { if (_world_config) _world_config->UpdateStats=false; }
static void EnableStats() { if (_world_config) _world_config->UpdateStats=true; }
static void DisableLoginserver() { if (_world_config) _world_config->LoginDisabled=true; }
static void EnableLoginserver() { if (_world_config) _world_config->LoginDisabled=false; }
static void SetWorldAddress(string addr) { if (_world_config) _world_config->WorldAddress=addr; }
static void SetLocalAddress(string addr) { if (_world_config) _world_config->LocalAddress=addr; }
void Dump() const;
};
#endif
+35
View File
@@ -0,0 +1,35 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef WorldTCPCONNECTION_H
#define WorldTCPCONNECTION_H
#include "../common/types.h"
class WorldTCPConnection
{
public:
WorldTCPConnection() { }
virtual ~WorldTCPConnection() { }
virtual void SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message, ...) { }
virtual void SendEmoteMessageRaw(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message) { }
virtual inline bool IsConsole() { return false; }
virtual inline bool IsZoneServer() { return false; }
};
#endif
+2021
View File
File diff suppressed because it is too large Load Diff
+108
View File
@@ -0,0 +1,108 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef CLIENT_H
#define CLIENT_H
#include <string>
//#include "../common/EQStream.h"
#include "../common/linked_list.h"
#include "../common/timer.h"
//#include "zoneserver.h"
#include "../common/logsys.h"
#include "../common/eq_packet_structs.h"
#include "cliententry.h"
#define CLIENT_TIMEOUT 30000
class EQApplicationPacket;
class EQStreamInterface;
class Client {
public:
Client(EQStreamInterface* ieqs);
~Client();
bool Process();
void ReceiveData(uchar* buf, int len);
void SendCharInfo();
void SendMaxCharCreate(int max_chars);
void SendMembership();
void SendMembershipSettings();
void EnterWorld(bool TryBootup = true);
void ZoneUnavail();
void QueuePacket(const EQApplicationPacket* app, bool ack_req = true);
void Clearance(int8 response);
void SendGuildList();
void SendEnterWorld(std::string name);
void SendExpansionInfo();
void SendLogServer();
void SendApproveWorld();
void SendPostEnterWorld();
bool GenPassKey(char* key);
inline uint32 GetIP() { return ip; }
inline uint16 GetPort() { return port; }
inline uint32 GetZoneID() { return zoneID; }
inline uint32 GetInstanceID() { return instanceID; }
inline uint32 WaitingForBootup() { return pwaitingforbootup; }
inline const char * GetAccountName() { if (cle) { return cle->AccountName(); } return "NOCLE"; }
inline int16 GetAdmin() { if (cle) { return cle->Admin(); } return 0; }
inline uint32 GetAccountID() { if (cle) { return cle->AccountID(); } return 0; }
inline uint32 GetWID() { if (cle) { return cle->GetID(); } return 0; }
inline uint32 GetLSID() { if (cle) { return cle->LSID(); } return 0; }
inline const char* GetLSKey() { if (cle) { return cle->GetLSKey(); } return "NOKEY"; }
inline uint32 GetCharID() { return charid; }
inline const char* GetCharName() { return char_name; }
inline ClientListEntry* GetCLE() { return cle; }
inline void SetCLE(ClientListEntry* iCLE) { cle = iCLE; }
private:
uint32 ip;
uint16 port;
uint32 charid;
char char_name[64];
uint32 zoneID;
uint32 instanceID;
bool pZoning;
Timer autobootup_timeout;
uint32 pwaitingforbootup;
bool StartInTutorial;
uint32 ClientVersionBit;
bool OPCharCreate(char *name, CharCreate_Struct *cc);
void SetClassStartingSkills( PlayerProfile_Struct *pp );
void SetRaceStartingSkills( PlayerProfile_Struct *pp );
void SetRacialLanguages( PlayerProfile_Struct *pp );
ClientListEntry* cle;
Timer CLE_keepalive_timer;
Timer connect;
bool firstlogin;
bool seencharsel;
bool realfirstlogin;
bool HandlePacket(const EQApplicationPacket *app);
EQStreamInterface* const eqs;
};
bool CheckCharCreateInfoSoF(CharCreate_Struct *cc);
bool CheckCharCreateInfoTitanium(CharCreate_Struct *cc);
#endif
+326
View File
@@ -0,0 +1,326 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2005 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "cliententry.h"
#include "clientlist.h"
#include "LoginServer.h"
#include "LoginServerList.h"
#include "worlddb.h"
#include "zoneserver.h"
#include "WorldConfig.h"
#include "../common/guilds.h"
extern uint32 numplayers;
extern LoginServerList loginserverlist;
extern ClientList client_list;
extern volatile bool RunLoops;
ClientListEntry::ClientListEntry(uint32 in_id, uint32 iLSID, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin, uint32 ip, uint8 local)
: id(in_id)
{
ClearVars(true);
pIP = ip;
pLSID = iLSID;
if(iLSID > 0)
paccountid = database.GetAccountIDFromLSID(iLSID, paccountname, &padmin);
strn0cpy(plsname, iLoginName, sizeof(plsname));
strn0cpy(plskey, iLoginKey, sizeof(plskey));
pworldadmin = iWorldAdmin;
plocal=(local==1);
pinstance = 0;
}
ClientListEntry::ClientListEntry(uint32 in_id, uint32 iAccID, const char* iAccName, MD5& iMD5Pass, int16 iAdmin)
: id(in_id)
{
ClearVars(true);
pIP = 0;
pLSID = 0;
pworldadmin = 0;
paccountid = iAccID;
strn0cpy(paccountname, iAccName, sizeof(paccountname));
pMD5Pass = iMD5Pass;
padmin = iAdmin;
pinstance = 0;
}
ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer* iZS, ServerClientList_Struct* scl, int8 iOnline)
: id(in_id)
{
ClearVars(true);
pIP = 0;
pLSID = scl->LSAccountID;
strn0cpy(plsname, scl->name, sizeof(plsname));
strn0cpy(plskey, scl->lskey, sizeof(plskey));
pworldadmin = 0;
paccountid = scl->AccountID;
strn0cpy(paccountname, scl->AccountName, sizeof(paccountname));
padmin = scl->Admin;
pinstance = 0;
if (iOnline >= CLE_Status_Zoning)
Update(iZS, scl, iOnline);
else
SetOnline(iOnline);
}
ClientListEntry::~ClientListEntry() {
if (RunLoops) {
Camp(); // updates zoneserver's numplayers
client_list.RemoveCLEReferances(this);
}
}
void ClientListEntry::SetChar(uint32 iCharID, const char* iCharName) {
pcharid = iCharID;
strn0cpy(pname, iCharName, sizeof(pname));
}
void ClientListEntry::SetOnline(ZoneServer* iZS, int8 iOnline) {
if (iZS == this->Server())
SetOnline(iOnline);
}
void ClientListEntry::SetOnline(int8 iOnline) {
if (iOnline >= CLE_Status_Online && pOnline < CLE_Status_Online)
numplayers++;
else if (iOnline < CLE_Status_Online && pOnline >= CLE_Status_Online) {
numplayers--;
}
if (iOnline != CLE_Status_Online || pOnline < CLE_Status_Online)
pOnline = iOnline;
if (iOnline < CLE_Status_Zoning)
Camp();
if (pOnline >= CLE_Status_Online)
stale = 0;
}
void ClientListEntry::LSUpdate(ZoneServer* iZS){
if(WorldConfig::get()->UpdateStats){
ServerPacket* pack = new ServerPacket;
pack->opcode = ServerOP_LSZoneInfo;
pack->size = sizeof(ZoneInfo_Struct);
pack->pBuffer = new uchar[pack->size];
ZoneInfo_Struct* zone =(ZoneInfo_Struct*)pack->pBuffer;
zone->count=iZS->NumPlayers();
zone->zone = iZS->GetZoneID();
zone->zone_wid = iZS->GetID();
loginserverlist.SendPacket(pack);
safe_delete(pack);
}
}
void ClientListEntry::LSZoneChange(ZoneToZone_Struct* ztz){
if(WorldConfig::get()->UpdateStats){
ServerPacket* pack = new ServerPacket;
pack->opcode = ServerOP_LSPlayerZoneChange;
pack->size = sizeof(ServerLSPlayerZoneChange_Struct);
pack->pBuffer = new uchar[pack->size];
ServerLSPlayerZoneChange_Struct* zonechange =(ServerLSPlayerZoneChange_Struct*)pack->pBuffer;
zonechange->lsaccount_id = LSID();
zonechange->from = ztz->current_zone_id;
zonechange->to = ztz->requested_zone_id;
loginserverlist.SendPacket(pack);
safe_delete(pack);
}
}
void ClientListEntry::Update(ZoneServer* iZS, ServerClientList_Struct* scl, int8 iOnline) {
if (pzoneserver != iZS) {
if (pzoneserver){
pzoneserver->RemovePlayer();
LSUpdate(pzoneserver);
}
if (iZS){
iZS->AddPlayer();
LSUpdate(iZS);
}
}
pzoneserver = iZS;
pzone = scl->zone;
pinstance = scl->instance_id;
pcharid = scl->charid;
strcpy(pname, scl->name);
if (paccountid == 0) {
paccountid = scl->AccountID;
strcpy(paccountname, scl->AccountName);
strcpy(plsname, scl->AccountName);
pIP = scl->IP;
pLSID = scl->LSAccountID;
strn0cpy(plskey, scl->lskey, sizeof(plskey));
}
padmin = scl->Admin;
plevel = scl->level;
pclass_ = scl->class_;
prace = scl->race;
panon = scl->anon;
ptellsoff = scl->tellsoff;
pguild_id = scl->guild_id;
pLFG = scl->LFG;
gm = scl->gm;
pClientVersion = scl->ClientVersion;
// Fields from the LFG Window
if((scl->LFGFromLevel != 0) && (scl->LFGToLevel != 0)) {
pLFGFromLevel = scl->LFGFromLevel;
pLFGToLevel = scl->LFGToLevel;
pLFGMatchFilter = scl->LFGMatchFilter;
memcpy(pLFGComments, scl->LFGComments, sizeof(pLFGComments));
}
SetOnline(iOnline);
}
void ClientListEntry::LeavingZone(ZoneServer* iZS, int8 iOnline) {
if (iZS != 0 && iZS != pzoneserver)
return;
SetOnline(iOnline);
if (pzoneserver){
pzoneserver->RemovePlayer();
LSUpdate(pzoneserver);
}
pzoneserver = 0;
pzone = 0;
}
void ClientListEntry::ClearVars(bool iAll) {
if (iAll) {
pOnline = CLE_Status_Never;
stale = 0;
pLSID = 0;
memset(plsname, 0, sizeof(plsname));
memset(plskey, 0, sizeof(plskey));
pworldadmin = 0;
paccountid = 0;
memset(paccountname, 0, sizeof(paccountname));
padmin = 0;
}
pzoneserver = 0;
pzone = 0;
pcharid = 0;
memset(pname, 0, sizeof(pname));
plevel = 0;
pclass_ = 0;
prace = 0;
panon = 0;
ptellsoff = 0;
pguild_id = GUILD_NONE;
pLFG = 0;
gm = 0;
pClientVersion = 0;
}
void ClientListEntry::Camp(ZoneServer* iZS) {
if (iZS != 0 && iZS != pzoneserver)
return;
if (pzoneserver){
pzoneserver->RemovePlayer();
LSUpdate(pzoneserver);
}
ClearVars();
stale = 0;
}
bool ClientListEntry::CheckStale() {
stale++;
if (stale >= 3) {
if (pOnline > CLE_Status_Offline)
SetOnline(CLE_Status_Offline);
else
return true;
}
return false;
}
bool ClientListEntry::CheckAuth(uint32 iLSID, const char* iKey) {
// if (LSID() == iLSID && strncmp(plskey, iKey,10) == 0) {
if (strncmp(plskey, iKey,10) == 0) {
if (paccountid == 0 && LSID()>0) {
int16 tmpStatus = WorldConfig::get()->DefaultStatus;
paccountid = database.CreateAccount(plsname, 0, tmpStatus, LSID());
if (!paccountid) {
_log(WORLD__CLIENTLIST_ERR,"Error adding local account for LS login: '%s', duplicate name?" ,plsname);
return false;
}
strn0cpy(paccountname, plsname, sizeof(paccountname));
padmin = tmpStatus;
}
char lsworldadmin[15] = "0";
database.GetVariable("honorlsworldadmin", lsworldadmin, sizeof(lsworldadmin));
if (atoi(lsworldadmin) == 1 && pworldadmin != 0 && (padmin < pworldadmin || padmin == 0))
padmin = pworldadmin;
return true;
}
return false;
}
bool ClientListEntry::CheckAuth(const char* iName, MD5& iMD5Password) {
if (LSAccountID() == 0 && strcmp(paccountname, iName) == 0 && pMD5Pass == iMD5Password)
return true;
return false;
}
bool ClientListEntry::CheckAuth(uint32 id, const char* iKey, uint32 ip) {
if (pIP==ip && strncmp(plskey, iKey,10) == 0){
paccountid = id;
database.GetAccountFromID(id,paccountname,&padmin);
return true;
}
return false;
}
+126
View File
@@ -0,0 +1,126 @@
#ifndef CLIENTENTRY_H_
#define CLIENTENTRY_H_
#include "../common/types.h"
#include "../common/md5.h"
//#include "../common/eq_packet_structs.h"
#include "../common/servertalk.h"
#define CLE_Status_Never -1
#define CLE_Status_Offline 0
#define CLE_Status_Online 1 // Will not overwrite more specific online status
#define CLE_Status_CharSelect 2
#define CLE_Status_Zoning 3
#define CLE_Status_InZone 4
class ZoneServer;
struct ServerClientList_Struct;
class ClientListEntry {
public:
ClientListEntry(uint32 id, uint32 iLSID, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin = 0, uint32 ip = 0, uint8 local=0);
ClientListEntry(uint32 id, uint32 iAccID, const char* iAccName, MD5& iMD5Pass, int16 iAdmin = 0);
ClientListEntry(uint32 id, ZoneServer* iZS, ServerClientList_Struct* scl, int8 iOnline);
~ClientListEntry();
bool CheckStale();
void Update(ZoneServer* zoneserver, ServerClientList_Struct* scl, int8 iOnline = CLE_Status_InZone);
void LSUpdate(ZoneServer* zoneserver);
void LSZoneChange(ZoneToZone_Struct* ztz);
bool CheckAuth(uint32 iLSID, const char* key);
bool CheckAuth(const char* iName, MD5& iMD5Password);
bool CheckAuth(uint32 id, const char* key, uint32 ip);
void SetOnline(ZoneServer* iZS, int8 iOnline);
void SetOnline(int8 iOnline = CLE_Status_Online);
void SetChar(uint32 iCharID, const char* iCharName);
inline int8 Online() { return pOnline; }
inline const uint32 GetID() const { return id; }
inline const uint32 GetIP() const { return pIP; }
inline void SetIP(const uint32& iIP) { pIP = iIP; }
inline void KeepAlive() { stale = 0; }
inline uint8 GetStaleCounter() const { return stale; }
void LeavingZone(ZoneServer* iZS = 0, int8 iOnline = CLE_Status_Offline);
void Camp(ZoneServer* iZS = 0);
// Login Server stuff
inline uint32 LSID() const { return pLSID; }
inline uint32 LSAccountID() const { return pLSID; }
inline const char* LSName() const { return plsname; }
inline int16 WorldAdmin() const { return pworldadmin; }
inline const char* GetLSKey() const { return plskey; }
// Account stuff
inline uint32 AccountID() const { return paccountid; }
inline const char* AccountName() const { return paccountname; }
inline int16 Admin() const { return padmin; }
inline void SetAdmin(uint16 iAdmin) { padmin = iAdmin; }
// Character info
inline ZoneServer* Server() const { return pzoneserver; }
inline void ClearServer() { pzoneserver = 0; }
inline uint32 CharID() const { return pcharid; }
inline const char* name() const { return pname; }
inline uint32 zone() const { return pzone; }
inline uint16 instance() const { return pinstance; }
inline uint8 level() const { return plevel; }
inline uint8 class_() const { return pclass_; }
inline uint16 race() const { return prace; }
inline uint8 Anon() { return panon; }
inline uint8 TellsOff() const { return ptellsoff; }
inline uint32 GuildID() const { return pguild_id; }
inline void SetGuild(uint32 guild_id) { pguild_id = guild_id; }
inline bool LFG() const { return pLFG; }
inline uint8 GetGM() const { return gm; }
inline void SetGM(uint8 igm) { gm = igm; }
inline void SetZone(uint32 zone) { pzone = zone; }
inline bool IsLocalClient() const { return plocal; }
inline uint8 GetLFGFromLevel() const { return pLFGFromLevel; }
inline uint8 GetLFGToLevel() const { return pLFGToLevel; }
inline bool GetLFGMatchFilter() const { return pLFGMatchFilter; }
inline const char* GetLFGComments() const { return pLFGComments; }
inline uint8 GetClientVersion() { return pClientVersion; }
private:
void ClearVars(bool iAll = false);
const uint32 id;
uint32 pIP;
int8 pOnline;
uint8 stale;
// Login Server stuff
uint32 pLSID;
char plsname[32];
char plskey[16];
int16 pworldadmin; // Login server's suggested admin status setting
bool plocal;
// Account stuff
uint32 paccountid;
char paccountname[32];
MD5 pMD5Pass;
int16 padmin;
// Character info
ZoneServer* pzoneserver;
uint32 pzone;
uint16 pinstance;
uint32 pcharid;
char pname[64];
uint8 plevel;
uint8 pclass_;
uint16 prace;
uint8 panon;
uint8 ptellsoff;
uint32 pguild_id;
bool pLFG;
uint8 gm;
uint8 pClientVersion;
uint8 pLFGFromLevel;
uint8 pLFGToLevel;
bool pLFGMatchFilter;
char pLFGComments[64];
};
#endif /*CLIENTENTRY_H_*/
+1362
View File
File diff suppressed because it is too large Load Diff
+85
View File
@@ -0,0 +1,85 @@
#ifndef CLIENTLIST_H_
#define CLIENTLIST_H_
#include "../common/eq_packet_structs.h"
#include "../common/linked_list.h"
#include "../common/timer.h"
#include "../common/rulesys.h"
#include "../common/servertalk.h"
#include <vector>
#include <string>
class Client;
class ZoneServer;
class WorldTCPConnection;
class ClientListEntry;
class ServerPacket;
struct ServerClientList_Struct;
class ClientList {
public:
ClientList();
~ClientList();
void Process();
//from old ClientList
void Add(Client* client);
Client* Get(uint32 ip, uint16 port);
Client* FindByAccountID(uint32 account_id);
Client* FindByName(char* charname);
void ZoneBootup(ZoneServer* zs);
void RemoveCLEReferances(ClientListEntry* cle);
//from ZSList
void SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_Struct* whom, WorldTCPConnection* connection);
void SendFriendsWho(ServerFriendsWho_Struct *FriendsWho, WorldTCPConnection* connection);
void SendOnlineGuildMembers(uint32 FromID, uint32 GuildID);
void SendClientVersionSummary(const char *Name);
void SendLFGMatches(ServerLFGMatchesRequest_Struct *LFGMatchesRequest);
void ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct* whom, WorldTCPConnection* connection);
void SendCLEList(const int16& admin, const char* to, WorldTCPConnection* connection, const char* iName = 0);
bool SendPacket(const char* to, ServerPacket* pack);
void SendGuildPacket(uint32 guild_id, ServerPacket* pack);
void ClientUpdate(ZoneServer* zoneserver, ServerClientList_Struct* scl);
void CLERemoveZSRef(ZoneServer* iZS);
ClientListEntry* CheckAuth(uint32 iLSID, const char* iKey);
ClientListEntry* CheckAuth(const char* iName, const char* iPassword);
ClientListEntry* CheckAuth(uint32 id, const char* iKey, uint32 ip);
ClientListEntry* FindCharacter(const char* name);
ClientListEntry* FindCLEByAccountID(uint32 iAccID);
ClientListEntry* FindCLEByCharacterID(uint32 iCharID);
ClientListEntry* GetCLE(uint32 iID);
void GetCLEIP(uint32 iIP);
void DisconnectByIP(uint32 iIP);
void EnforceSessionLimit(uint32 iLSAccountID);
void CLCheckStale();
void CLEKeepAlive(uint32 numupdates, uint32* wid);
void CLEAdd(uint32 iLSID, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin = 0, uint32 ip = 0, uint8 local=0);
void UpdateClientGuild(uint32 char_id, uint32 guild_id);
int GetClientCount();
void GetClients(const char *zone_name, std::vector<ClientListEntry *> &into);
protected:
inline uint32 GetNextCLEID() { return NextCLEID++; }
//this is the list of people actively connected to zone
LinkedList<Client*> list;
//this is the list of people in any zone, not nescesarily connected to world
Timer CLStale_timer;
uint32 NextCLEID;
LinkedList<ClientListEntry *> clientlist;
};
#endif /*CLIENTLIST_H_*/
+843
View File
@@ -0,0 +1,843 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include <iostream>
using namespace std;
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "../common/version.h"
#include "console.h"
#include "zoneserver.h"
#include "worlddb.h"
#include "../common/packet_dump.h"
#include "../common/seperator.h"
#include "../common/eq_packet_structs.h"
#include "../common/EQPacket.h"
#include "LoginServer.h"
#include "LoginServerList.h"
#include "../common/serverinfo.h"
#include "../common/md5.h"
#include "../common/opcodemgr.h"
#include "../common/rulesys.h"
#include "../common/ruletypes.h"
#include "WorldConfig.h"
#include "zoneserver.h"
#include "zonelist.h"
#include "clientlist.h"
#include "LauncherList.h"
#include "ucs.h"
#include "queryserv.h"
#ifdef _WINDOWS
#define snprintf _snprintf
#if (_MSC_VER < 1500)
#define vsnprintf _vsnprintf
#endif
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#endif
extern ZSList zoneserver_list;
extern uint32 numzones;
extern LoginServerList loginserverlist;
extern ClientList client_list;
extern LauncherList launcher_list;
extern UCSConnection UCSLink;
extern QueryServConnection QSLink;
extern volatile bool RunLoops;
ConsoleList console_list;
Console::Console(EmuTCPConnection* itcpc)
: WorldTCPConnection(),
timeout_timer(RuleI(Console, SessionTimeOut)),
prompt_timer(1000)
{
tcpc = itcpc;
tcpc->SetEcho(true);
state = 0;
paccountid = 0;
memset(paccountname, 0, sizeof(paccountname));
admin = 0;
pAcceptMessages = false;
}
Console::~Console() {
if (tcpc)
tcpc->Free();
}
void Console::Die() {
state = CONSOLE_STATE_CLOSED;
struct in_addr in;
in.s_addr = GetIP();
_log(WORLD__CONSOLE,"Removing console from %s:%d",inet_ntoa(in),GetPort());
tcpc->Disconnect();
}
bool Console::SendChannelMessage(const ServerChannelMessage_Struct* scm) {
if (!pAcceptMessages)
return false;
switch (scm->chan_num) {
if(RuleB(Chat, ServerWideAuction)){
case 4: {
SendMessage(1, "%s auctions, '%s'", scm->from, scm->message);
break;
}
}
if(RuleB(Chat, ServerWideOOC)){
case 5: {
SendMessage(1, "%s says ooc, '%s'", scm->from, scm->message);
break;
}
}
case 6: {
SendMessage(1, "%s BROADCASTS, '%s'", scm->from, scm->message);
break;
}
case 7: {
SendMessage(1, "%s tells you, '%s'", scm->from, scm->message);
ServerPacket* pack = new ServerPacket(ServerOP_ChannelMessage, sizeof(ServerChannelMessage_Struct) + strlen(scm->message) + 1);
memcpy(pack->pBuffer, scm, pack->size);
ServerChannelMessage_Struct* scm2 = (ServerChannelMessage_Struct*) pack->pBuffer;
strcpy(scm2->deliverto, scm2->from);
scm2->noreply = true;
client_list.SendPacket(scm->from, pack);
safe_delete(pack);
break;
}
case 11: {
SendMessage(1, "%s GMSAYS, '%s'", scm->from, scm->message);
break;
}
default: {
return false;
}
}
return true;
}
bool Console::SendEmoteMessage(uint32 type, const char* message, ...) {
if (!message)
return false;
if (!pAcceptMessages)
return false;
va_list argptr;
char buffer[1024];
va_start(argptr, message);
vsnprintf(buffer, sizeof(buffer), message, argptr);
va_end(argptr);
SendMessage(1, message);
return true;
}
bool Console::SendEmoteMessageRaw(uint32 type, const char* message) {
if (!message)
return false;
if (!pAcceptMessages)
return false;
SendMessage(1, message);
return true;
}
void Console::SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message, ...) {
if (!message)
return;
if (to_guilddbid != 0 || to_minstatus > Admin())
return;
va_list argptr;
char buffer[1024];
va_start(argptr, message);
vsnprintf(buffer, sizeof(buffer), message, argptr);
va_end(argptr);
SendEmoteMessageRaw(to, to_guilddbid, to_minstatus, type, buffer);
}
void Console::SendEmoteMessageRaw(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message) {
if (!message)
return;
if (to_guilddbid != 0 || to_minstatus > Admin())
return;
SendMessage(1, message);
}
void Console::SendMessage(uint8 newline, const char* message, ...) {
if (!message)
return;
char* buffer = 0;
uint32 bufsize = 1500;
if (message)
bufsize += strlen(message);
buffer = new char[bufsize];
memset(buffer, 0, bufsize);
if (message != 0) {
va_list argptr;
va_start(argptr, message);
vsnprintf(buffer, bufsize - 512, message, argptr);
va_end(argptr);
}
if (newline) {
char outbuf[3];
outbuf[0] = 13;
outbuf[1] = 10;
outbuf[2] = 0;
for (int i=0; i < newline; i++)
strcat(buffer, outbuf);
}
tcpc->Send((uchar*) buffer, strlen(buffer));
safe_delete_array(buffer);
}
bool Console::Process() {
if (state == CONSOLE_STATE_CLOSED)
return false;
if (!tcpc->Connected()) {
struct in_addr in;
in.s_addr = GetIP();
_log(WORLD__CONSOLE,"Removing console (!tcpc->Connected) from %s:%d",inet_ntoa(in),GetPort());
return false;
}
//if we have not gotten the special markers after this timer, send login prompt
if(prompt_timer.Check()) {
prompt_timer.Disable();
if(tcpc->GetMode() == EmuTCPConnection::modeConsole)
tcpc->Send((const uchar*) "Username: ", strlen("Username: "));
}
if (timeout_timer.Check()) {
SendMessage(1, 0);
SendMessage(1, "Timeout, disconnecting...");
struct in_addr in;
in.s_addr = GetIP();
_log(WORLD__CONSOLE,"TCP connection timeout from %s:%d",inet_ntoa(in),GetPort());
return false;
}
if (tcpc->GetMode() == EmuTCPConnection::modePacket) {
struct in_addr in;
in.s_addr = GetIP();
if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeZone) {
ZoneServer* zs = new ZoneServer(tcpc);
_log(WORLD__CONSOLE,"New zoneserver #%d from %s:%d", zs->GetID(), inet_ntoa(in), GetPort());
zoneserver_list.Add(zs);
numzones++;
tcpc = 0;
} else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeLauncher) {
_log(WORLD__CONSOLE,"New launcher from %s:%d", inet_ntoa(in), GetPort());
launcher_list.Add(tcpc);
tcpc = 0;
} else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeUCS)
{
_log(WORLD__CONSOLE,"New UCS Connection from %s:%d", inet_ntoa(in), GetPort());
UCSLink.SetConnection(tcpc);
tcpc = 0;
}
else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeQueryServ)
{
_log(WORLD__CONSOLE,"New QS Connection from %s:%d", inet_ntoa(in), GetPort());
QSLink.SetConnection(tcpc);
tcpc = 0;
} else {
_log(WORLD__CONSOLE,"Unsupported packet mode from %s:%d", inet_ntoa(in), GetPort());
}
return false;
}
char* command = 0;
while ((command = tcpc->PopLine())) {
timeout_timer.Start();
ProcessCommand(command);
delete command;
}
return true;
}
void ConsoleList::Add(Console* con) {
list.Insert(con);
}
void ConsoleList::Process() {
LinkedListIterator<Console*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()) {
if (!iterator.GetData()->Process())
iterator.RemoveCurrent();
else
iterator.Advance();
}
}
void ConsoleList::KillAll() {
LinkedListIterator<Console*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()) {
iterator.GetData()->Die();
iterator.RemoveCurrent();
}
}
void ConsoleList::SendConsoleWho(WorldTCPConnection* connection, const char* to, int16 admin, char** output, uint32* outsize, uint32* outlen) {
LinkedListIterator<Console*> iterator(list);
iterator.Reset();
struct in_addr in;
int x = 0;
while(iterator.MoreElements()) {
in.s_addr = iterator.GetData()->GetIP();
if (admin >= iterator.GetData()->Admin())
AppendAnyLenString(output, outsize, outlen, " Console: %s:%i AccID: %i AccName: %s", inet_ntoa(in), iterator.GetData()->GetPort(), iterator.GetData()->AccountID(), iterator.GetData()->AccountName());
else
AppendAnyLenString(output, outsize, outlen, " Console: AccID: %i AccName: %s", iterator.GetData()->AccountID(), iterator.GetData()->AccountName());
if (*outlen >= 3584) {
connection->SendEmoteMessageRaw(to, 0, 0, 10, *output);
safe_delete(*output);
*outsize = 0;
*outlen = 0;
}
else {
if (connection->IsConsole())
AppendAnyLenString(output, outsize, outlen, "\r\n");
else
AppendAnyLenString(output, outsize, outlen, "\n");
}
x++;
iterator.Advance();
}
AppendAnyLenString(output, outsize, outlen, "%i consoles connected", x);
}
void ConsoleList::SendChannelMessage(const ServerChannelMessage_Struct* scm) {
LinkedListIterator<Console*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()) {
iterator.GetData()->SendChannelMessage(scm);
iterator.Advance();
}
}
void ConsoleList::SendEmoteMessage(uint32 type, const char* message, ...) {
va_list argptr;
char buffer[1024];
va_start(argptr, message);
vsnprintf(buffer, sizeof(buffer), message, argptr);
va_end(argptr);
SendEmoteMessageRaw(type, buffer);
}
void ConsoleList::SendEmoteMessageRaw(uint32 type, const char* message) {
LinkedListIterator<Console*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()) {
iterator.GetData()->SendEmoteMessageRaw(type, message);
iterator.Advance();
}
}
Console* ConsoleList::FindByAccountName(const char* accname) {
LinkedListIterator<Console*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()) {
if (strcasecmp(iterator.GetData()->AccountName(), accname) == 0)
return iterator.GetData();
iterator.Advance();
}
return 0;
}
void Console::ProcessCommand(const char* command) {
switch(state)
{
case CONSOLE_STATE_USERNAME:
{
if (strlen(command) >= 16) {
SendMessage(1, 0);
SendMessage(2, "Username buffer overflow.");
SendMessage(1, "Bye Bye.");
state = CONSOLE_STATE_CLOSED;
return;
}
strcpy(paccountname, command);
state = CONSOLE_STATE_PASSWORD;
SendMessage(0, "Password: ");
tcpc->SetEcho(false);
break;
}
case CONSOLE_STATE_PASSWORD:
{
if (strlen(command) >= 16) {
SendMessage(1, 0);
SendMessage(2, "Password buffer overflow.");
SendMessage(1, "Bye Bye.");
state = CONSOLE_STATE_CLOSED;
return;
}
paccountid = database.CheckLogin(paccountname,command);
if (paccountid == 0) {
SendMessage(1, 0);
SendMessage(2, "Login failed.");
SendMessage(1, "Bye Bye.");
state = CONSOLE_STATE_CLOSED;
return;
}
database.GetAccountName(paccountid, paccountname); // fixes case and stuff
admin = database.CheckStatus(paccountid);
if (!(admin >= consoleLoginStatus)) {
SendMessage(1, 0);
SendMessage(2, "Access denied.");
SendMessage(1, "Bye Bye.");
state = CONSOLE_STATE_CLOSED;
return;
}
_log(WORLD__CONSOLE,"TCP console authenticated: Username=%s, Admin=%d",paccountname,admin);
SendMessage(1, 0);
SendMessage(2, "Login accepted.");
state = CONSOLE_STATE_CONNECTED;
tcpc->SetEcho(true);
SendPrompt();
break;
}
case CONSOLE_STATE_CONNECTED: {
_log(WORLD__CONSOLE,"TCP command: %s: \"%s\"",paccountname,command);
Seperator sep(command);
if (strcasecmp(sep.arg[0], "help") == 0 || strcmp(sep.arg[0], "?") == 0) {
SendMessage(1, " whoami");
SendMessage(1, " who");
SendMessage(1, " zonestatus");
SendMessage(1, " uptime [zoneID#]");
SendMessage(1, " emote [zonename or charname or world] [type] [message]");
SendMessage(1, " echo [on/off]");
SendMessage(1, " acceptmessages [on/off]");
SendMessage(1, " tell [name] [message]");
SendMessage(1, " broadcast [message]");
SendMessage(1, " gmsay [message]");
SendMessage(1, " ooc [message]");
SendMessage(1, " auction [message]");
if (admin >= consoleKickStatus)
SendMessage(1, " kick [charname]");
if (admin >= consoleLockStatus)
SendMessage(1, " lock/unlock");
if (admin >= consoleZoneStatus) {
SendMessage(1, " zoneshutdown [zonename or ZoneServerID]");
SendMessage(1, " zonebootup [ZoneServerID] [zonename]");
SendMessage(1, " zonelock [list|lock|unlock] [zonename]");
}
if (admin >= consoleFlagStatus)
SendMessage(1, " flag [status] [accountname]");
if (admin >= consolePassStatus)
SendMessage(1, " setpass [accountname] [newpass]");
if (admin >= consoleWorldStatus) {
SendMessage(1, " version");
SendMessage(1, " worldshutdown");
}
if (admin >= 201) {
SendMessage(1, " IPLookup [name]");
}
if (admin >= 100) {
SendMessage(1, " LSReconnect");
SendMessage(1, " signalcharbyname charname ID");
}
}
else if (strcasecmp(sep.arg[0], "ping") == 0) {
// do nothing
}
else if (strcasecmp(sep.arg[0], "signalcharbyname") == 0) {
SendMessage(1, "Signal Sent to %s with ID %i", (char*) sep.arg[1], atoi(sep.arg[2]));
uint32 message_len = strlen((char*) sep.arg[1]) + 1;
ServerPacket* pack = new ServerPacket(ServerOP_CZSignalClientByName, sizeof(CZClientSignalByName_Struct) + message_len);
CZClientSignalByName_Struct* CZSC = (CZClientSignalByName_Struct*) pack->pBuffer;
strn0cpy(CZSC->Name, (char*) sep.arg[1], 64);
CZSC->data = atoi(sep.arg[2]);
zoneserver_list.SendPacket(pack);
safe_delete(pack);
}
else if (strcasecmp(sep.arg[0], "setpass") == 0 && admin >= consolePassStatus) {
if (sep.argnum != 2)
SendMessage(1, "Format: setpass accountname password");
else {
int16 tmpstatus = 0;
uint32 tmpid = database.GetAccountIDByName(sep.arg[1], &tmpstatus);
if (!tmpid)
SendMessage(1, "Error: Account not found");
else if (tmpstatus > admin)
SendMessage(1, "Cannot change password: Account's status is higher than yours");
else if (database.SetLocalPassword(tmpid, sep.arg[2]))
SendMessage(1, "Password changed.");
else
SendMessage(1, "Error changing password.");
}
}
else if (strcasecmp(sep.arg[0], "uptime") == 0) {
if (sep.IsNumber(1) && atoi(sep.arg[1]) > 0) {
ServerPacket* pack = new ServerPacket(ServerOP_Uptime, sizeof(ServerUptime_Struct));
ServerUptime_Struct* sus = (ServerUptime_Struct*) pack->pBuffer;
snprintf(sus->adminname, sizeof(sus->adminname), "*%s", this->GetName());
sus->zoneserverid = atoi(sep.arg[1]);
ZoneServer* zs = zoneserver_list.FindByID(sus->zoneserverid);
if (zs)
zs->SendPacket(pack);
else
SendMessage(1, "Zoneserver not found.");
delete pack;
}
else {
ZSList::ShowUpTime(this);
}
}
else if (strcasecmp(sep.arg[0], "md5") == 0) {
uint8 md5[16];
MD5::Generate((const uchar*) sep.argplus[1], strlen(sep.argplus[1]), md5);
SendMessage(1, "MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", md5[0], md5[1], md5[2], md5[3], md5[4], md5[5], md5[6], md5[7], md5[8], md5[9], md5[10], md5[11], md5[12], md5[13], md5[14], md5[15]);
}
else if (strcasecmp(sep.arg[0], "whoami") == 0) {
SendMessage(1, "You are logged in as '%s'", this->AccountName());
SendMessage(1, "You are known as '*%s'", this->AccountName());
SendMessage(1, "AccessLevel: %d", this->Admin());
}
else if (strcasecmp(sep.arg[0], "echo") == 0) {
if (strcasecmp(sep.arg[1], "on") == 0)
tcpc->SetEcho(true);
else if (strcasecmp(sep.arg[1], "off") == 0) {
if (pAcceptMessages)
SendMessage(1, "Echo can not be turned off while acceptmessages is on");
else
tcpc->SetEcho(false);
}
else
SendMessage(1, "Usage: echo [on/off]");
}
else if (strcasecmp(sep.arg[0], "acceptmessages") == 0) {
if (strcasecmp(sep.arg[1], "on") == 0)
if (tcpc->GetEcho())
SendMessage(1, "AcceptMessages can not be turned on while echo is on");
else
pAcceptMessages = true;
else if (strcasecmp(sep.arg[1], "off") == 0)
pAcceptMessages = false;
else
SendMessage(1, "Usage: acceptmessages [on/off]");
}
else if (strcasecmp(sep.arg[0], "tell") == 0) {
char tmpname[64];
tmpname[0] = '*';
strcpy(&tmpname[1], paccountname);
zoneserver_list.SendChannelMessage(tmpname, sep.arg[1], 7, 0, sep.argplus[2]);
}
else if (strcasecmp(sep.arg[0], "broadcast") == 0) {
char tmpname[64];
tmpname[0] = '*';
strcpy(&tmpname[1], paccountname);
zoneserver_list.SendChannelMessage(tmpname, 0, 6, 0, sep.argplus[1]);
}
else if (strcasecmp(sep.arg[0], "ooc") == 0) {
char tmpname[64];
tmpname[0] = '*';
strcpy(&tmpname[1], paccountname);
zoneserver_list.SendChannelMessage(tmpname, 0, 5, 0, sep.argplus[1]);
}
else if (strcasecmp(sep.arg[0], "auction") == 0) {
char tmpname[64];
tmpname[0] = '*';
strcpy(&tmpname[1], paccountname);
zoneserver_list.SendChannelMessage(tmpname, 0, 4, 0, sep.argplus[1]);
}
else if (strcasecmp(sep.arg[0], "gmsay") == 0 || strcasecmp(sep.arg[0], "pr") == 0) {
char tmpname[64];
tmpname[0] = '*';
strcpy(&tmpname[1], paccountname);
zoneserver_list.SendChannelMessage(tmpname, 0, 11, 0, sep.argplus[1]);
}
else if (strcasecmp(sep.arg[0], "emote") == 0) {
if (strcasecmp(sep.arg[1], "world") == 0)
zoneserver_list.SendEmoteMessageRaw(0, 0, 0, atoi(sep.arg[2]), sep.argplus[3]);
else {
ZoneServer* zs = zoneserver_list.FindByName(sep.arg[1]);
if (zs != 0)
zs->SendEmoteMessageRaw(0, 0, 0, atoi(sep.arg[2]), sep.argplus[3]);
else
zoneserver_list.SendEmoteMessageRaw(sep.arg[1], 0, 0, atoi(sep.arg[2]), sep.argplus[3]);
}
}
else if (strcasecmp(sep.arg[0], "movechar") == 0) {
if(sep.arg[1][0]==0 || sep.arg[2][0] == 0)
SendMessage(1, "Usage: movechar [charactername] [zonename]");
else {
if (!database.GetZoneID(sep.arg[2]))
SendMessage(1, "Error: Zone '%s' not found", sep.arg[2]);
else if (!database.CheckUsedName((char*) sep.arg[1])) {
if (!database.MoveCharacterToZone((char*) sep.arg[1], (char*) sep.arg[2]))
SendMessage(1, "Character Move Failed!");
else
SendMessage(1, "Character has been moved.");
}
else
SendMessage(1, "Character Does Not Exist");
}
}
else if (strcasecmp(sep.arg[0], "flag") == 0 && this->Admin() >= consoleFlagStatus) {
// SCORPIOUS2K - reversed parameter order for flag
if(sep.arg[2][0]==0 || !sep.IsNumber(1))
SendMessage(1, "Usage: flag [status] [accountname]");
else
{
if (atoi(sep.arg[1]) > this->Admin())
SendMessage(1, "You cannot set people's status to higher than your own");
else if (atoi(sep.arg[1]) < 0 && this->Admin() < consoleFlagStatus)
SendMessage(1, "You have too low of status to change flags");
else if (!database.SetAccountStatus(sep.arg[2], atoi(sep.arg[1])))
SendMessage(1, "Unable to flag account!");
else
SendMessage(1, "Account Flaged");
}
}
else if (strcasecmp(sep.arg[0], "kick") == 0 && admin >= consoleKickStatus) {
char tmpname[64];
tmpname[0] = '*';
strcpy(&tmpname[1], paccountname);
ServerPacket* pack = new ServerPacket;
pack->opcode = ServerOP_KickPlayer;
pack->size = sizeof(ServerKickPlayer_Struct);
pack->pBuffer = new uchar[pack->size];
ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*) pack->pBuffer;
strcpy(skp->adminname, tmpname);
strcpy(skp->name, sep.arg[1]);
skp->adminrank = this->Admin();
zoneserver_list.SendPacket(pack);
delete pack;
}
else if (strcasecmp(sep.arg[0], "who") == 0) {
Who_All_Struct* whom = new Who_All_Struct;
memset(whom, 0, sizeof(Who_All_Struct));
whom->lvllow = 0xFFFF;
whom->lvlhigh = 0xFFFF;
whom->wclass = 0xFFFF;
whom->wrace = 0xFFFF;
whom->gmlookup = 0xFFFF;
for (int i=1; i<=sep.argnum; i++) {
if (strcasecmp(sep.arg[i], "gm") == 0)
whom->gmlookup = 1;
else if (sep.IsNumber(i)) {
if (whom->lvllow == 0xFFFF) {
whom->lvllow = atoi(sep.arg[i]);
whom->lvlhigh = whom->lvllow;
}
else if (atoi(sep.arg[i]) > int(whom->lvllow))
whom->lvlhigh = atoi(sep.arg[i]);
else
whom->lvllow = atoi(sep.arg[i]);
}
else
strn0cpy(whom->whom, sep.arg[i], sizeof(whom->whom));
}
client_list.ConsoleSendWhoAll(0, admin, whom, this);
delete whom;
}
else if (strcasecmp(sep.arg[0], "zonestatus") == 0) {
zoneserver_list.SendZoneStatus(0, admin, this);
}
else if (strcasecmp(sep.arg[0], "exit") == 0 || strcasecmp(sep.arg[0], "quit") == 0) {
SendMessage(1, "Bye Bye.");
state = CONSOLE_STATE_CLOSED;
}
else if (strcasecmp(sep.arg[0], "zoneshutdown") == 0 && admin >= consoleZoneStatus) {
if (sep.arg[1][0] == 0) {
SendMessage(1, "Usage: zoneshutdown zoneshortname");
} else {
char tmpname[64];
tmpname[0] = '*';
strcpy(&tmpname[1], paccountname);
ServerPacket* pack = new ServerPacket;
pack->size = sizeof(ServerZoneStateChange_struct);
pack->pBuffer = new uchar[pack->size];
memset(pack->pBuffer, 0, sizeof(ServerZoneStateChange_struct));
ServerZoneStateChange_struct* s = (ServerZoneStateChange_struct *) pack->pBuffer;
pack->opcode = ServerOP_ZoneShutdown;
strcpy(s->adminname, tmpname);
if (sep.arg[1][0] >= '0' && sep.arg[1][0] <= '9')
s->ZoneServerID = atoi(sep.arg[1]);
else
s->zoneid = database.GetZoneID(sep.arg[1]);
ZoneServer* zs = 0;
if (s->ZoneServerID != 0)
zs = zoneserver_list.FindByID(s->ZoneServerID);
else if (s->zoneid != 0)
zs = zoneserver_list.FindByName(database.GetZoneName(s->zoneid));
else
SendMessage(1, "Error: ZoneShutdown: neither ID nor name specified");
if (zs == 0)
SendMessage(1, "Error: ZoneShutdown: zoneserver not found");
else
zs->SendPacket(pack);
delete pack;
}
}
else if (strcasecmp(sep.arg[0], "zonebootup") == 0 && admin >= consoleZoneStatus) {
if (sep.arg[2][0] == 0 || !sep.IsNumber(1)) {
SendMessage(1, "Usage: zonebootup ZoneServerID# zoneshortname");
} else {
char tmpname[64];
tmpname[0] = '*';
strcpy(&tmpname[1], paccountname);
_log(WORLD__CONSOLE,"Console ZoneBootup: %s, %s, %s",tmpname,sep.arg[2],sep.arg[1]);
zoneserver_list.SOPZoneBootup(tmpname, atoi(sep.arg[1]), sep.arg[2], (bool) (strcasecmp(sep.arg[3], "static") == 0));
}
}
else if (strcasecmp(sep.arg[0], "worldshutdown") == 0 && admin >= consoleWorldStatus) {
ServerPacket* pack = new ServerPacket(ServerOP_ShutdownAll);
zoneserver_list.SendPacket(pack);
delete pack;
SendMessage(1, "Sending shutdown packet... goodbye.");
CatchSignal(0);
}
else if (strcasecmp(sep.arg[0], "lock") == 0 && admin >= consoleLockStatus) {
WorldConfig::LockWorld();
if (loginserverlist.Connected()) {
loginserverlist.SendStatus();
SendMessage(1, "World locked.");
}
else {
SendMessage(1, "World locked, but login server not connected.");
}
}
else if (strcasecmp(sep.arg[0], "unlock") == 0 && admin >= consoleLockStatus) {
WorldConfig::UnlockWorld();
if (loginserverlist.Connected()) {
loginserverlist.SendStatus();
SendMessage(1, "World unlocked.");
}
else {
SendMessage(1, "World unlocked, but login server not connected.");
}
}
else if (strcasecmp(sep.arg[0], "version") == 0 && admin >= consoleWorldStatus) {
SendMessage(1, "Current version information.");
SendMessage(1, " %s", CURRENT_WORLD_VERSION);
SendMessage(1, " Compiled on: %s at %s", COMPILE_DATE, COMPILE_TIME);
SendMessage(1, " Last modified on: %s", LAST_MODIFIED);
}
else if (strcasecmp(sep.arg[0], "serverinfo") == 0 && admin >= 200) {
if (strcasecmp(sep.arg[1], "os") == 0) {
#ifdef _WINDOWS
GetOS();
char intbuffer [sizeof(unsigned long)];
SendMessage(1, "Operating system information.");
SendMessage(1, " %s", Ver_name);
SendMessage(1, " Build number: %s", ultoa(Ver_build, intbuffer, 10));
SendMessage(1, " Minor version: %s", ultoa(Ver_min, intbuffer, 10));
SendMessage(1, " Major version: %s", ultoa(Ver_maj, intbuffer, 10));
SendMessage(1, " Platform Id: %s", ultoa(Ver_pid, intbuffer, 10));
#else
char os_string[100];
SendMessage(1, "Operating system information.");
SendMessage(1, " %s", GetOS(os_string));
#endif
}
else {
SendMessage(1, "Usage: Serverinfo [type]");
SendMessage(1, " OS - Operating system version information.");
}
}
else if (strcasecmp(sep.arg[0], "IPLookup") == 0 && admin >= 201) {
client_list.SendCLEList(admin, 0, this, sep.argplus[1]);
}
else if (strcasecmp(sep.arg[0], "LSReconnect") == 0 && admin >= 100) {
#ifdef _WINDOWS
_beginthread(AutoInitLoginServer, 0, NULL);
#else
pthread_t thread;
pthread_create(&thread, NULL, &AutoInitLoginServer, NULL);
#endif
RunLoops = true;
SendMessage(1, " Login Server Reconnect manually restarted by Console");
_log(WORLD__CONSOLE,"Login Server Reconnect manually restarted by Console");
}
else if (strcasecmp(sep.arg[0], "zonelock") == 0 && admin >= consoleZoneStatus) {
if (strcasecmp(sep.arg[1], "list") == 0) {
zoneserver_list.ListLockedZones(0, this);
}
else if (strcasecmp(sep.arg[1], "lock") == 0 && admin >= 101) {
uint16 tmp = database.GetZoneID(sep.arg[2]);
if (tmp) {
if (zoneserver_list.SetLockedZone(tmp, true))
zoneserver_list.SendEmoteMessage(0, 0, 80, 15, "Zone locked: %s", database.GetZoneName(tmp));
else
SendMessage(1, "Failed to change lock");
}
else
SendMessage(1, "Usage: #zonelock lock [zonename]");
}
else if (strcasecmp(sep.arg[1], "unlock") == 0 && admin >= 101) {
uint16 tmp = database.GetZoneID(sep.arg[2]);
if (tmp) {
if (zoneserver_list.SetLockedZone(tmp, false))
zoneserver_list.SendEmoteMessage(0, 0, 80, 15, "Zone unlocked: %s", database.GetZoneName(tmp));
else
SendMessage(1, "Failed to change lock");
}
else
SendMessage(1, "Usage: #zonelock unlock [zonename]");
}
else {
SendMessage(1, "#zonelock sub-commands");
SendMessage(1, " list");
if (admin >= 101) {
SendMessage(1, " lock [zonename]");
SendMessage(1, " unlock [zonename]");
}
}
}
else {
SendMessage(1, "Command unknown.");
}
if (state == CONSOLE_STATE_CONNECTED)
SendPrompt();
break;
}
default: {
break;
}
}
}
void Console::SendPrompt() {
if (tcpc->GetEcho())
SendMessage(0, "%s> ", paccountname);
}
+108
View File
@@ -0,0 +1,108 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef CONSOLE_H
#define CONSOLE_H
enum {
consoleLoginStatus = 50, //ability to log in, basic commands.
httpLoginStatus = 100, //can log into the HTTP interface
consoleFlagStatus = 200, //flag
consoleKickStatus = 150, //kick
consoleLockStatus = 150, //world lock/unlock
consoleZoneStatus = 150, //zone up/down/lock
consolePassStatus = 200, //change password
consoleWorldStatus = 200, //world shutdown
consoleOpcodesStatus = 250
};
#define CONSOLE_STATE_USERNAME 0
#define CONSOLE_STATE_PASSWORD 1
#define CONSOLE_STATE_CONNECTED 2
#define CONSOLE_STATE_CLOSED 3
#include "../common/linked_list.h"
#include "../common/timer.h"
#include "../common/queue.h"
#include "../common/EmuTCPConnection.h"
#include "WorldTCPConnection.h"
#include "../common/Mutex.h"
struct ServerChannelMessage_Struct;
class Console : public WorldTCPConnection {
public:
Console(EmuTCPConnection* itcpc);
virtual ~Console();
virtual inline bool IsConsole() { return true; }
bool Process();
void Send(const char* message);
int16 Admin() { return admin; }
uint32 GetIP() { return tcpc->GetrIP(); }
uint16 GetPort() { return tcpc->GetrPort(); }
void ProcessCommand(const char* command);
void Die();
bool SendChannelMessage(const ServerChannelMessage_Struct* scm);
bool SendEmoteMessage(uint32 type, const char* message, ...);
bool SendEmoteMessageRaw(uint32 type, const char* message);
void SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message, ...);
void SendEmoteMessageRaw(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message);
void SendMessage(uint8 newline, const char* message, ...);
const char* GetName() { return paccountname; }
const char* AccountName() { return paccountname; }
uint32 AccountID() { return paccountid; }
private:
EmuTCPConnection* tcpc;
Timer timeout_timer;
Timer prompt_timer;
void SendPrompt();
uint32 paccountid;
char paccountname[30];
bool pAcceptMessages;
uint8 state;
int16 admin;
uchar textbuf[1024];
int bufindex;
};
class ConsoleList
{
public:
ConsoleList() {}
~ConsoleList() {}
void Add(Console* con);
void Process();
void KillAll();
void SendChannelMessage(const ServerChannelMessage_Struct* scm);
void SendConsoleWho(WorldTCPConnection* connection, const char* to, int16 admin, char** output, uint32* outsize, uint32* outlen);
void SendEmoteMessage(uint32 type, const char* message, ...);
void SendEmoteMessageRaw(uint32 type, const char* message);
Console* FindByAccountName(const char* accname);
private:
LinkedList<Console*> list;
};
#endif
+279
View File
@@ -0,0 +1,279 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "lfplist.h"
#include "cliententry.h"
#include "clientlist.h"
#include "zoneserver.h"
#include "zonelist.h"
#include "../common/logsys.h"
#include "../common/MiscFunctions.h"
extern ClientList client_list;
extern ZSList zoneserver_list;
GroupLFP::GroupLFP(uint32 inLeaderID) {
LeaderID = inLeaderID;
for(unsigned int i=0; i<MAX_GROUP_MEMBERS; i++) {
Members[i].Name[0] = '\0';
Members[i].Class = 0;
Members[i].Level = 0;
Members[i].Zone = 0;
}
FromLevel = 1;
ToLevel = 100;
Classes = 0x01FFFE;
Comments[0] = '\0';
}
void GroupLFP::SetDetails(ServerLFPUpdate_Struct *Update) {
ClientListEntry *CLE;
// Update->Action can be 1 or 255.
// If it is 255, we update the members only, not the level/class filters.
//
if(Update->Action != 255) {
MatchFilter = Update->MatchFilter;
FromLevel = Update->FromLevel;
ToLevel = Update->ToLevel;
Classes = Update->Classes;
strcpy(Comments, Update->Comments);
}
for(unsigned int i=0; i<MAX_GROUP_MEMBERS; i++) {
strcpy(Members[i].Name,Update->Members[i].Name);
// If we were passed the class/level and zone information, use that.
if(Update->Members[i].Class && Update->Members[i].Level && Update->Members[i].Zone) {
Members[i].Class = Update->Members[i].Class;
Members[i].Level = Update->Members[i].Level;
Members[i].Zone = Update->Members[i].Zone;
Members[i].GuildID = Update->Members[i].GuildID;
}
// Otherwise try and find the information ourselves.
else {
CLE = client_list.FindCharacter(Members[i].Name);
if(CLE) {
Members[i].Class = CLE->class_();
Members[i].Level = CLE->level();
Members[i].Zone = CLE->zone();
Members[i].GuildID = CLE->GuildID();
}
else {
Members[i].Class = 0;
Members[i].Level = 0;
Members[i].Zone = 0;
Members[i].GuildID = 0xFFFF;
}
}
}
}
void GroupLFP::RemoveMember(int Index) {
Members[Index].Name[0] = '\0';
}
GroupLFPList::GroupLFPList() : LFPStaleTimer(60000) {
}
void GroupLFPList::Process() {
// Once a minute, check for clients in a LFP group who are no longer connected, and remove them.
// If the client that posted the LFP group has gone, remove the entire LFP entry.
//
// We also update the level, class and zone for each member of the group. Their class will usually
// never change, but if the LFP group is posted while a member is zoning, it will initially be
// 'Unknown Class', so we will fill it in here.
if(!LFPStaleTimer.Check())
return;
GroupLFP* Group;
LinkedListIterator<GroupLFP*> Iterator(LFPGroupList);
Iterator.Reset();
while(Iterator.MoreElements()) {
Group = Iterator.GetData();
int MemberCount = 0;
if(Group) {
GroupLFPMemberEntry* GroupMembers = Group->Members;
if(!GroupMembers) {
Iterator.Advance();
continue;
}
for(unsigned int i=0; i<MAX_GROUP_MEMBERS; i++) {
if(GroupMembers[i].Name[0] == '\0')
continue;
ClientListEntry *CLE = client_list.FindCharacter(GroupMembers[i].Name);
if(!CLE) {
// The first member entry is always the person who posted the LFP group, either
// a single ungrouped player, or the leader of the group. If (s)he is gone, remove
// the group from LFP.
if(i==0) break;
Group->RemoveMember(i);
}
else {
// If the level/class/zone information we have is valid, update
// the player's information.
//
if(CLE->level() > 0)
GroupMembers[i].Level = CLE->level();
if(CLE->class_() > 0)
GroupMembers[i].Class = CLE->class_();
if(CLE->zone() > 0)
GroupMembers[i].Zone = CLE->zone();
MemberCount++;
}
}
if(MemberCount == 0) {
// If the leader or all the members are not online, remove the entry.
Iterator.RemoveCurrent();
continue;
}
}
Iterator.Advance();
}
}
void GroupLFPList::RemoveGroup(ServerLFPUpdate_Struct *Update) {
GroupLFP* Group;
LinkedListIterator<GroupLFP*> Iterator(LFPGroupList);
Iterator.Reset();
while(Iterator.MoreElements()) {
Group = Iterator.GetData();
if(Group && (Group->GetID() == Update->LeaderID)) {
Iterator.RemoveCurrent();
return;
}
Iterator.Advance();
}
}
void GroupLFPList::UpdateGroup(ServerLFPUpdate_Struct *Update) {
GroupLFP* Group;
LinkedListIterator<GroupLFP*> Iterator(LFPGroupList);
Iterator.Reset();
while(Iterator.MoreElements()) {
Group = Iterator.GetData();
if(Group && (Group->GetID() == Update->LeaderID)) {
Group->SetDetails(Update);
return;
}
Iterator.Advance();
}
Group = new GroupLFP(Update->LeaderID);
if(Group) {
Group->SetDetails(Update);
LFPGroupList.Append(Group);
}
}
void GroupLFPList::SendLFPMatches(ServerLFPMatchesRequest_Struct* smrs) {
int Matches = 0;
GroupLFP* Group;
LinkedListIterator<GroupLFP*> Iterator(LFPGroupList);
Iterator.Reset();
while(Iterator.MoreElements()) {
Group = Iterator.GetData();
Iterator.Advance();
if(Group) {
// Just check if the leader is within the requested level range.
if((Group->Members[0].Level < smrs->FromLevel) || (Group->Members[0].Level > smrs->ToLevel))
continue;
// If the Player putting up the LFP request specified MatchFilter = true, then anyone
// searching for groups LFP must meet the specified criteria to see this group.
if(Group->MatchFilter) {
unsigned int BitMask = 1 << smrs->QuerierClass;
if(!(BitMask & Group->Classes)) continue;
if(!((smrs->QuerierLevel >= Group->FromLevel) && (smrs->QuerierLevel <= Group->ToLevel))) continue;
}
Matches++;
}
}
ServerPacket* Pack = new ServerPacket(ServerOP_LFPMatches, (sizeof(ServerLFPMatchesResponse_Struct) * Matches) + 4);
char *Buf = (char *)Pack->pBuffer;
VARSTRUCT_ENCODE_TYPE(uint32, Buf, smrs->FromID);
ServerLFPMatchesResponse_Struct* Buffer = (ServerLFPMatchesResponse_Struct*)Buf;
Iterator.Reset();
if(Matches) {
while(Iterator.MoreElements() && (Matches > 0)) {
Group = Iterator.GetData();
Iterator.Advance();
if(Group) {
if((Group->Members[0].Level < smrs->FromLevel) || (Group->Members[0].Level > smrs->ToLevel))
continue;
if(Group->MatchFilter) {
unsigned int BitMask = 1 << smrs->QuerierClass;
if(!(BitMask & Group->Classes)) continue;
if(!((smrs->QuerierLevel >= Group->FromLevel) && (smrs->QuerierLevel <= Group->ToLevel))) continue;
}
Buffer->FromLevel = Group->FromLevel;
Buffer->ToLevel = Group->ToLevel;
Buffer->Classes = Group->Classes;
memcpy(Buffer->Members, Group->Members, 64 * MAX_GROUP_MEMBERS);
strcpy(Buffer->Comments, Group->Comments);
Matches--;
Buffer++;
}
}
Pack->Deflate();
}
ClientListEntry* CLE = client_list.FindCharacter(smrs->FromName);
if (CLE != NULL) {
if (CLE->Server() != NULL)
CLE->Server()->SendPacket(Pack);
}
else {
ZoneServer* zs = zoneserver_list.FindByName(smrs->FromName);
if (zs != NULL)
zs->SendPacket(Pack);
}
safe_delete(Pack);
}
+66
View File
@@ -0,0 +1,66 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef LFPENTRY_H
#define LFPENTRY_H
#include "../common/eq_packet_structs.h"
#include "../common/servertalk.h"
#include "../common/linked_list.h"
#include "../common/timer.h"
class GroupLFP {
public:
GroupLFP(uint32 LeaderID);
void SetDetails(ServerLFPUpdate_Struct *Update);
inline GroupLFPMemberEntry* GetMembers() { return Members; }
inline uint32 GetID() { return LeaderID; }
void RemoveMember(int Index);
friend class GroupLFPList;
private:
uint32 LeaderID;
uint8 MatchFilter;
uint32 FromLevel;
uint32 ToLevel;
uint32 Classes;
char Comments[64];
GroupLFPMemberEntry Members[MAX_GROUP_MEMBERS];
};
class GroupLFPList {
public:
GroupLFPList();
void UpdateGroup(ServerLFPUpdate_Struct *Update);
void RemoveGroup(ServerLFPUpdate_Struct *Update);
void SendLFPMatches(ServerLFPMatchesRequest_Struct* smrs);
void Process();
private:
LinkedList<GroupLFP*> LFPGroupList;
Timer LFPStaleTimer;
};
#endif
+568
View File
@@ -0,0 +1,568 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include <iostream>
using namespace std;
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include "../common/debug.h"
#include "../common/queue.h"
#include "../common/timer.h"
#include "../common/EQStreamFactory.h"
#include "../common/EQPacket.h"
#include "client.h"
#include "worlddb.h"
#include "../common/seperator.h"
#include "../common/version.h"
#include "../common/eqtime.h"
#include "../common/timeoutmgr.h"
#include "../common/EQEMuError.h"
#include "../common/opcodemgr.h"
#include "../common/guilds.h"
#include "../common/EQStreamIdent.h"
//#include "../common/patches/Client62.h"
#include "../common/rulesys.h"
#include "../common/platform.h"
#include "../common/crash.h"
#ifdef _WINDOWS
#include <process.h>
#define snprintf _snprintf
#if (_MSC_VER < 1500)
#define vsnprintf _vsnprintf
#endif
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#include <conio.h>
#else
#include <pthread.h>
#include "../common/unix.h"
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#ifndef FREEBSD
union semun {
int val;
struct semid_ds *buf;
ushort *array;
struct seminfo *__buf;
void *__pad;
};
#endif
#endif
#include "../common/EMuShareMem.h"
extern LoadEMuShareMemDLL EMuShareMemDLL;
/*
Zone only right now.
#ifdef EQPROFILE
#ifdef COMMON_PROFILE
CommonProfiler _cp;
#endif
#endif*/
#include "zoneserver.h"
#include "console.h"
#include "LoginServer.h"
#include "LoginServerList.h"
#include "EQWHTTPHandler.h"
#include "../common/dbasync.h"
#include "../common/EmuTCPServer.h"
#include "WorldConfig.h"
#include "../common/patches/patches.h"
#include "zoneserver.h"
#include "zonelist.h"
#include "clientlist.h"
#include "LauncherList.h"
#include "wguild_mgr.h"
#include "lfplist.h"
#include "AdventureManager.h"
#include "ucs.h"
#include "queryserv.h"
TimeoutManager timeout_manager;
EQStreamFactory eqsf(WorldStream,9000);
EmuTCPServer tcps;
ClientList client_list;
GroupLFPList LFPGroupList;
ZSList zoneserver_list;
LoginServerList loginserverlist;
EQWHTTPServer http_server;
UCSConnection UCSLink;
QueryServConnection QSLink;
LauncherList launcher_list;
AdventureManager adventure_manager;
DBAsync *dbasync = NULL;
RuleManager *rules = new RuleManager();
volatile bool RunLoops = true;
uint32 numclients = 0;
uint32 numzones = 0;
bool holdzones = false;
extern ConsoleList console_list;
void CatchSignal(int sig_num);
int main(int argc, char** argv) {
RegisterExecutablePlatform(ExePlatformWorld);
set_exception_handler();
// Load server configuration
_log(WORLD__INIT, "Loading server configuration..");
if (!WorldConfig::LoadConfig()) {
_log(WORLD__INIT_ERR, "Loading server configuration failed.");
return(1);
}
const WorldConfig *Config=WorldConfig::get();
if(!load_log_settings(Config->LogSettingsFile.c_str()))
_log(WORLD__INIT, "Warning: Unable to read %s", Config->LogSettingsFile.c_str());
else
_log(WORLD__INIT, "Log settings loaded from %s", Config->LogSettingsFile.c_str());
_log(WORLD__INIT, "CURRENT_WORLD_VERSION:%s", CURRENT_WORLD_VERSION);
#ifdef _DEBUG
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
if (signal(SIGINT, CatchSignal) == SIG_ERR) {
_log(WORLD__INIT_ERR, "Could not set signal handler");
return 0;
}
if (signal(SIGTERM, CatchSignal) == SIG_ERR) {
_log(WORLD__INIT_ERR, "Could not set signal handler");
return 0;
}
#ifndef WIN32
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
_log(WORLD__INIT_ERR, "Could not set signal handler");
return 0;
}
#endif
// add login server config to list
if (Config->LoginCount == 0) {
if (Config->LoginHost.length()) {
loginserverlist.Add(Config->LoginHost.c_str(), Config->LoginPort, Config->LoginAccount.c_str(), Config->LoginPassword.c_str());
_log(WORLD__INIT, "Added loginserver %s:%i", Config->LoginHost.c_str(), Config->LoginPort);
}
} else {
LinkedList<LoginConfig*> loginlist=Config->loginlist;
LinkedListIterator<LoginConfig*> iterator(loginlist);
iterator.Reset();
while(iterator.MoreElements()) {
loginserverlist.Add(iterator.GetData()->LoginHost.c_str(), iterator.GetData()->LoginPort, iterator.GetData()->LoginAccount.c_str(), iterator.GetData()->LoginPassword.c_str());
_log(WORLD__INIT, "Added loginserver %s:%i", iterator.GetData()->LoginHost.c_str(), iterator.GetData()->LoginPort);
iterator.Advance();
}
}
_log(WORLD__INIT, "Connecting to MySQL...");
if (!database.Connect(
Config->DatabaseHost.c_str(),
Config->DatabaseUsername.c_str(),
Config->DatabasePassword.c_str(),
Config->DatabaseDB.c_str(),
Config->DatabasePort)) {
_log(WORLD__INIT_ERR, "Cannot continue without a database connection.");
return(1);
}
dbasync = new DBAsync(&database);
guild_mgr.SetDatabase(&database);
if (argc >= 2) {
char tmp[2];
if (strcasecmp(argv[1], "help") == 0 || strcasecmp(argv[1], "?") == 0 || strcasecmp(argv[1], "/?") == 0 || strcasecmp(argv[1], "-?") == 0 || strcasecmp(argv[1], "-h") == 0 || strcasecmp(argv[1], "-help") == 0) {
cout << "Worldserver command line commands:" << endl;
cout << "adduser username password flag - adds a user account" << endl;
cout << "flag username flag - sets GM flag on the account" << endl;
cout << "startzone zoneshortname - sets the starting zone" << endl;
cout << "-holdzones - reboots lost zones" << endl;
return 0;
}
else if (strcasecmp(argv[1], "-holdzones") == 0) {
cout << "Reboot Zones mode ON" << endl;
holdzones = true;
}
else if (database.GetVariable("disablecommandline", tmp, 2)) {
if (strlen(tmp) == 1) {
if (tmp[0] == '1') {
cout << "Command line disabled in database... exiting" << endl;
return 0;
}
}
}
else if (strcasecmp(argv[1], "adduser") == 0) {
if (argc == 5) {
if (Seperator::IsNumber(argv[4])) {
if (atoi(argv[4]) >= 0 && atoi(argv[4]) <= 255) {
if (database.CreateAccount(argv[2], argv[3], atoi(argv[4])) == 0)
cout << "database.CreateAccount failed." << endl;
else
cout << "Account created: Username='" << argv[2] << "', Password='" << argv[3] << "', status=" << argv[4] << endl;
return 0;
}
}
}
cout << "Usage: world adduser username password flag" << endl;
cout << "flag = 0, 1 or 2" << endl;
return 0;
}
else if (strcasecmp(argv[1], "flag") == 0) {
if (argc == 4) {
if (Seperator::IsNumber(argv[3])) {
if (atoi(argv[3]) >= 0 && atoi(argv[3]) <= 255) {
if (database.SetAccountStatus(argv[2], atoi(argv[3])))
cout << "Account flagged: Username='" << argv[2] << "', status=" << argv[3] << endl;
else
cout << "database.SetAccountStatus failed." << endl;
return 0;
}
}
}
cout << "Usage: world flag username flag" << endl;
cout << "flag = 0-200" << endl;
return 0;
}
else if (strcasecmp(argv[1], "startzone") == 0) {
if (argc == 3) {
if (strlen(argv[2]) < 3) {
cout << "Error: zone name too short" << endl;
}
else if (strlen(argv[2]) > 15) {
cout << "Error: zone name too long" << endl;
}
else {
if (database.SetVariable("startzone", argv[2]))
cout << "Starting zone changed: '" << argv[2] << "'" << endl;
else
cout << "database.SetVariable failed." << endl;
}
return 0;
}
cout << "Usage: world startzone zoneshortname" << endl;
return 0;
}
else {
cout << "Error, unknown command line option" << endl;
return 0;
}
}
if(Config->WorldHTTPEnabled) {
_log(WORLD__INIT, "Starting HTTP world service...");
http_server.Start(Config->WorldHTTPPort, Config->WorldHTTPMimeFile.c_str());
} else {
_log(WORLD__INIT, "HTTP world service disabled.");
}
_log(WORLD__INIT, "Loading variables..");
database.LoadVariables();
_log(WORLD__INIT, "Loading zones..");
database.LoadZoneNames();
_log(WORLD__INIT, "Clearing groups..");
database.ClearGroup();
_log(WORLD__INIT, "Clearing raids..");
database.ClearRaid();
database.ClearRaidDetails();
_log(WORLD__INIT, "Loading items..");
if (!database.LoadItems()) {
_log(WORLD__INIT_ERR, "Error: Could not load item data. But ignoring");
}
_log(WORLD__INIT, "Loading guilds..");
guild_mgr.LoadGuilds();
//rules:
{
char tmp[64];
if (database.GetVariable("RuleSet", tmp, sizeof(tmp)-1)) {
_log(WORLD__INIT, "Loading rule set '%s'", tmp);
if(!rules->LoadRules(&database, tmp)) {
_log(WORLD__INIT_ERR, "Failed to load ruleset '%s', falling back to defaults.", tmp);
}
} else {
if(!rules->LoadRules(&database, "default")) {
_log(WORLD__INIT, "No rule set configured, using default rules");
} else {
_log(WORLD__INIT, "Loaded default rule set 'default'", tmp);
}
}
}
if(RuleB(World, ClearTempMerchantlist)){
_log(WORLD__INIT, "Clearing temporary merchant lists..");
database.ClearMerchantTemp();
}
_log(WORLD__INIT, "Loading EQ time of day..");
if (!zoneserver_list.worldclock.loadFile(Config->EQTimeFile.c_str()))
_log(WORLD__INIT_ERR, "Unable to load %s", Config->EQTimeFile.c_str());
_log(WORLD__INIT, "Loading launcher list..");
launcher_list.LoadList();
char tmp[20];
tmp[0] = '\0';
database.GetVariable("holdzones",tmp, 20);
if ((strcasecmp(tmp, "1") == 0)) {
holdzones = true;
}
_log(WORLD__INIT, "Reboot zone modes %s",holdzones ? "ON" : "OFF");
_log(WORLD__INIT, "Deleted %i stale player corpses from database", database.DeleteStalePlayerCorpses());
if (RuleB(World, DeleteStaleCorpeBackups) == true) {
_log(WORLD__INIT, "Deleted %i stale player backups from database", database.DeleteStalePlayerBackups());
}
_log(WORLD__INIT, "Loading adventures...");
if(!adventure_manager.LoadAdventureTemplates())
{
_log(WORLD__INIT_ERR, "Unable to load adventure templates.");
}
if(!adventure_manager.LoadAdventureEntries())
{
_log(WORLD__INIT_ERR, "Unable to load adventure templates.");
}
adventure_manager.Load();
adventure_manager.LoadLeaderboardInfo();
_log(WORLD__INIT, "Purging expired instances");
database.PurgeExpiredInstances();
Timer PurgeInstanceTimer(450000);
PurgeInstanceTimer.Start(450000);
_log(WORLD__INIT, "Loading char create info...");
database.LoadCharacterCreateAllocations();
database.LoadCharacterCreateCombos();
char errbuf[TCPConnection_ErrorBufferSize];
if (tcps.Open(Config->WorldTCPPort, errbuf)) {
_log(WORLD__INIT,"Zone (TCP) listener started.");
} else {
_log(WORLD__INIT_ERR,"Failed to start zone (TCP) listener on port %d:",Config->WorldTCPPort);
_log(WORLD__INIT_ERR," %s",errbuf);
return 1;
}
if (eqsf.Open()) {
_log(WORLD__INIT,"Client (UDP) listener started.");
} else {
_log(WORLD__INIT_ERR,"Failed to start client (UDP) listener (port 9000)");
return 1;
}
//register all the patches we have avaliable with the stream identifier.
EQStreamIdentifier stream_identifier;
RegisterAllPatches(stream_identifier);
zoneserver_list.shutdowntimer = new Timer(60000);
zoneserver_list.shutdowntimer->Disable();
zoneserver_list.reminder = new Timer(20000);
zoneserver_list.reminder->Disable();
Timer InterserverTimer(INTERSERVER_TIMER); // does MySQL pings and auto-reconnect
InterserverTimer.Trigger();
uint8 ReconnectCounter = 100;
EQStream* eqs;
EmuTCPConnection* tcpc;
EQStreamInterface *eqsi;
while(RunLoops) {
Timer::SetCurrentTime();
//check the factory for any new incoming streams.
while ((eqs = eqsf.Pop())) {
//pull the stream out of the factory and give it to the stream identifier
//which will figure out what patch they are running, and set up the dynamic
//structures and opcodes for that patch.
struct in_addr in;
in.s_addr = eqs->GetRemoteIP();
_log(WORLD__CLIENT, "New connection from %s:%d", inet_ntoa(in),ntohs(eqs->GetRemotePort()));
stream_identifier.AddStream(eqs); //takes the stream
}
//give the stream identifier a chance to do its work....
stream_identifier.Process();
//check the stream identifier for any now-identified streams
while((eqsi = stream_identifier.PopIdentified())) {
//now that we know what patch they are running, start up their client object
struct in_addr in;
in.s_addr = eqsi->GetRemoteIP();
if (RuleB(World, UseBannedIPsTable)){ //Lieka: Check to see if we have the responsibility for blocking IPs.
_log(WORLD__CLIENT, "Checking inbound connection %s against BannedIPs table", inet_ntoa(in));
if (!database.CheckBannedIPs(inet_ntoa(in))){ //Lieka: Check inbound IP against banned IP table.
_log(WORLD__CLIENT, "Connection %s PASSED banned IPs check. Processing connection.", inet_ntoa(in));
Client* client = new Client(eqsi);
// @merth: client->zoneattempt=0;
client_list.Add(client);
} else {
_log(WORLD__CLIENT, "Connection from %s FAILED banned IPs check. Closing connection.", inet_ntoa(in));
eqsi->Close(); //Lieka: If the inbound IP is on the banned table, close the EQStream.
}
}
if (!RuleB(World, UseBannedIPsTable)){
_log(WORLD__CLIENT, "New connection from %s:%d, processing connection", inet_ntoa(in), ntohs(eqsi->GetRemotePort()));
Client* client = new Client(eqsi);
// @merth: client->zoneattempt=0;
client_list.Add(client);
}
}
client_list.Process();
while ((tcpc = tcps.NewQueuePop())) {
struct in_addr in;
in.s_addr = tcpc->GetrIP();
_log(WORLD__ZONE, "New TCP connection from %s:%d", inet_ntoa(in),tcpc->GetrPort());
console_list.Add(new Console(tcpc));
}
if(PurgeInstanceTimer.Check())
{
database.PurgeExpiredInstances();
}
//check for timeouts in other threads
timeout_manager.CheckTimeouts();
loginserverlist.Process();
console_list.Process();
zoneserver_list.Process();
launcher_list.Process();
UCSLink.Process();
QSLink.Process();
LFPGroupList.Process();
adventure_manager.Process();
if (InterserverTimer.Check()) {
InterserverTimer.Start();
database.ping();
AsyncLoadVariables(dbasync, &database);
ReconnectCounter++;
if (ReconnectCounter >= 12) { // only create thread to reconnect every 10 minutes. previously we were creating a new thread every 10 seconds
ReconnectCounter = 0;
if (loginserverlist.AllConnected() == false) {
#ifdef _WINDOWS
_beginthread(AutoInitLoginServer, 0, NULL);
#else
pthread_t thread;
pthread_create(&thread, NULL, &AutoInitLoginServer, NULL);
#endif
}
}
}
if (numclients == 0) {
Sleep(50);
continue;
}
Sleep(20);
}
_log(WORLD__SHUTDOWN,"World main loop completed.");
_log(WORLD__SHUTDOWN,"Shutting down console connections (if any).");
console_list.KillAll();
_log(WORLD__SHUTDOWN,"Shutting down zone connections (if any).");
zoneserver_list.KillAll();
_log(WORLD__SHUTDOWN,"Zone (TCP) listener stopped.");
tcps.Close();
_log(WORLD__SHUTDOWN,"Client (UDP) listener stopped.");
eqsf.Close();
_log(WORLD__SHUTDOWN,"Signaling HTTP service to stop...");
http_server.Stop();
#if 0
#if defined(SHAREMEM) && !defined(WIN32)
for (int ipc_files = 0; ipc_files <= 4; ipc_files++) {
key_t share_key;
switch (ipc_files) {
// Item
case 0: share_key = ftok(".", 'I'); break;
// Npctype
case 1: share_key = ftok(".", 'N'); break;
// Door
case 2: share_key = ftok(".", 'D'); break;
// Spell
case 3: share_key = ftok(".", 'S'); break;
// Faction
case 4: share_key = ftok(".", 'F'); break;
// ERROR Fatal
default: cerr<<"Opps!"<<endl; share_key = 0xFF; break;
}
int share_id = shmget(share_key, 0, IPC_NOWAIT|0400);
if (share_id <= 0) {
cerr<<"exiting could not check user count on shared memory ipcs mem leak!!!!!!!! id="<<share_id<<" key:"<<share_key<<endl;
exit(1);
}
struct shmid_ds mem_users;
if ((shmctl(share_id, IPC_STAT, &mem_users)) != 0) {
cerr<<"exiting error checking user count on shared memory, marking for deletion!!!!!id="<<share_id<<" key:"<<share_key<<endl;
shmctl(share_id, IPC_RMID, 0);
exit(1);
}
if (mem_users.shm_nattch == 0) {
//cerr<<"exiting stale share marked for deletion!id="<<share_id<<" key:"<<share_key<<endl;
shmctl(share_id, IPC_RMID, 0);
}
else if (mem_users.shm_nattch == 1) {
//cerr<<"mem_users = 1"<<endl;
// Detatch and delete shared mem here
EMuShareMemDLL.Unload();
shmctl(share_id, IPC_RMID, 0);
}
}
#endif
#endif
CheckEQEMuErrorAndPause();
return 0;
}
void CatchSignal(int sig_num) {
_log(WORLD__SHUTDOWN,"Caught signal %d",sig_num);
if(zoneserver_list.worldclock.saveFile(WorldConfig::get()->EQTimeFile.c_str())==false)
_log(WORLD__SHUTDOWN,"Failed to save time file.");
RunLoops = false;
}
void UpdateWindowTitle(char* iNewTitle) {
#ifdef _WINDOWS
char tmp[500];
if (iNewTitle) {
snprintf(tmp, sizeof(tmp), "World: %s", iNewTitle);
}
else {
snprintf(tmp, sizeof(tmp), "World");
}
SetConsoleTitle(tmp);
#endif
}
+88
View File
@@ -0,0 +1,88 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef WIN32
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#else
#include <cerrno>
#include <fcntl.h>
#include <windows.h>
#include <winsock.h>
#endif
void CatchSignal(int sig_num);
void UpdateWindowTitle(char* iNewTitle);
#define EQ_WORLD_PORT 9000 //mandated by the client
#define LOGIN_PORT 5997
class NetConnection
{
public:
NetConnection() {
world_locked = false;
for (int i=0; i<5; i++) {
memset(loginaddress[i], 0, sizeof(loginaddress[i]));
loginport[i] = LOGIN_PORT;
}
memset(worldname, 0, sizeof(worldname));
memset(worldshortname, 0, sizeof(worldshortname));
memset(worldaccount, 0, sizeof(worldaccount));
memset(worldpassword, 0, sizeof(worldpassword));
memset(worldaddress, 0, sizeof(worldaddress));
memset(chataddress, 0, sizeof(chataddress));
DEFAULTSTATUS=0;
LoginServerInfo = 0;//ReadLoginINI();
UpdateStats = false;
}
~NetConnection() { }
bool ReadLoginINI();
bool LoginServerInfo;
bool UpdateStats;
char* GetLoginInfo(uint16* oPort);
inline char* GetLoginAddress(uint8 i) { return loginaddress[i]; }
inline uint16 GetLoginPort(uint8 i) { return loginport[i]; }
inline char* GetWorldName() { return worldname; }
inline char* GetWorldShortName() { return worldshortname; }
inline char* GetWorldAccount() { return worldaccount; }
inline char* GetWorldPassword() { return worldpassword; }
inline char* GetWorldAddress() { return worldaddress; }
inline uint8 GetDefaultStatus() { return DEFAULTSTATUS; }
inline char* GetChatAddress() { return chataddress; }
uint16 GetChatPort() { return chatport; }
bool world_locked;
private:
int listening_socket;
char loginaddress[5][255];
uint16 loginport[5];
uint16 chatport;
char worldname[201];
char worldshortname[31];
char worldaccount[31];
char worldpassword[31];
char worldaddress[255];
char chataddress[255];
uint8 DEFAULTSTATUS;
};
+492
View File
@@ -0,0 +1,492 @@
/*
* This file was generated automatically by xsubpp version 1.9508 from the
* contents of tmp. Do not edit this file, edit tmp instead.
*
* ANY CHANGES MADE HERE WILL BE LOST!
*
*/
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
typedef const char Const_char;
#ifdef EMBPERL
#include "../common/debug.h"
#include "EQWParser.h"
#include "EQLConfig.h"
#ifdef THIS /* this macro seems to leak out on some systems */
#undef THIS
#endif
XS(XS_EQLConfig_GetName); /* prototype to pass -Wmissing-prototypes */
XS(XS_EQLConfig_GetName)
{
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: EQLConfig::GetName(THIS)");
{
EQLConfig * THIS;
Const_char * RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "EQLConfig")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(EQLConfig *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type EQLConfig");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
RETVAL = THIS->GetName();
sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
}
XSRETURN(1);
}
XS(XS_EQLConfig_GetStaticCount); /* prototype to pass -Wmissing-prototypes */
XS(XS_EQLConfig_GetStaticCount)
{
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: EQLConfig::GetStaticCount(THIS)");
{
EQLConfig * THIS;
int RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "EQLConfig")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(EQLConfig *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type EQLConfig");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
RETVAL = THIS->GetStaticCount();
XSprePUSH; PUSHi((IV)RETVAL);
}
XSRETURN(1);
}
XS(XS_EQLConfig_IsConnected); /* prototype to pass -Wmissing-prototypes */
XS(XS_EQLConfig_IsConnected)
{
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: EQLConfig::IsConnected(THIS)");
{
EQLConfig * THIS;
bool RETVAL;
if (sv_derived_from(ST(0), "EQLConfig")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(EQLConfig *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type EQLConfig");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
RETVAL = THIS->IsConnected();
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
}
XSRETURN(1);
}
XS(XS_EQLConfig_DeleteLauncher); /* prototype to pass -Wmissing-prototypes */
XS(XS_EQLConfig_DeleteLauncher)
{
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: EQLConfig::DeleteLauncher(THIS)");
{
EQLConfig * THIS;
if (sv_derived_from(ST(0), "EQLConfig")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(EQLConfig *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type EQLConfig");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
THIS->DeleteLauncher();
}
XSRETURN_EMPTY;
}
XS(XS_EQLConfig_RestartZone); /* prototype to pass -Wmissing-prototypes */
XS(XS_EQLConfig_RestartZone)
{
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: EQLConfig::RestartZone(THIS, zone_ref)");
{
EQLConfig * THIS;
Const_char * zone_ref = (Const_char *)SvPV_nolen(ST(1));
if (sv_derived_from(ST(0), "EQLConfig")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(EQLConfig *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type EQLConfig");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
THIS->RestartZone(zone_ref);
}
XSRETURN_EMPTY;
}
XS(XS_EQLConfig_StopZone); /* prototype to pass -Wmissing-prototypes */
XS(XS_EQLConfig_StopZone)
{
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: EQLConfig::StopZone(THIS, zone_ref)");
{
EQLConfig * THIS;
Const_char * zone_ref = (Const_char *)SvPV_nolen(ST(1));
if (sv_derived_from(ST(0), "EQLConfig")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(EQLConfig *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type EQLConfig");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
THIS->StopZone(zone_ref);
}
XSRETURN_EMPTY;
}
XS(XS_EQLConfig_StartZone); /* prototype to pass -Wmissing-prototypes */
XS(XS_EQLConfig_StartZone)
{
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: EQLConfig::StartZone(THIS, zone_ref)");
{
EQLConfig * THIS;
Const_char * zone_ref = (Const_char *)SvPV_nolen(ST(1));
if (sv_derived_from(ST(0), "EQLConfig")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(EQLConfig *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type EQLConfig");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
THIS->StartZone(zone_ref);
}
XSRETURN_EMPTY;
}
XS(XS_EQLConfig_BootStaticZone); /* prototype to pass -Wmissing-prototypes */
XS(XS_EQLConfig_BootStaticZone)
{
dXSARGS;
if (items != 3)
Perl_croak(aTHX_ "Usage: EQLConfig::BootStaticZone(THIS, short_name, port)");
{
EQLConfig * THIS;
bool RETVAL;
Const_char * short_name = (Const_char *)SvPV_nolen(ST(1));
uint16 port = (uint16)SvUV(ST(2));
if (sv_derived_from(ST(0), "EQLConfig")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(EQLConfig *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type EQLConfig");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
RETVAL = THIS->BootStaticZone(short_name, port);
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
}
XSRETURN(1);
}
XS(XS_EQLConfig_ChangeStaticZone); /* prototype to pass -Wmissing-prototypes */
XS(XS_EQLConfig_ChangeStaticZone)
{
dXSARGS;
if (items != 3)
Perl_croak(aTHX_ "Usage: EQLConfig::ChangeStaticZone(THIS, short_name, port)");
{
EQLConfig * THIS;
bool RETVAL;
Const_char * short_name = (Const_char *)SvPV_nolen(ST(1));
uint16 port = (uint16)SvUV(ST(2));
if (sv_derived_from(ST(0), "EQLConfig")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(EQLConfig *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type EQLConfig");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
RETVAL = THIS->ChangeStaticZone(short_name, port);
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
}
XSRETURN(1);
}
XS(XS_EQLConfig_DeleteStaticZone); /* prototype to pass -Wmissing-prototypes */
XS(XS_EQLConfig_DeleteStaticZone)
{
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: EQLConfig::DeleteStaticZone(THIS, short_name)");
{
EQLConfig * THIS;
bool RETVAL;
Const_char * short_name = (Const_char *)SvPV_nolen(ST(1));
if (sv_derived_from(ST(0), "EQLConfig")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(EQLConfig *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type EQLConfig");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
RETVAL = THIS->DeleteStaticZone(short_name);
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
}
XSRETURN(1);
}
XS(XS_EQLConfig_SetDynamicCount); /* prototype to pass -Wmissing-prototypes */
XS(XS_EQLConfig_SetDynamicCount)
{
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: EQLConfig::SetDynamicCount(THIS, count)");
{
EQLConfig * THIS;
bool RETVAL;
int count = (int)SvIV(ST(1));
if (sv_derived_from(ST(0), "EQLConfig")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(EQLConfig *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type EQLConfig");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
RETVAL = THIS->SetDynamicCount(count);
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
}
XSRETURN(1);
}
XS(XS_EQLConfig_GetDynamicCount); /* prototype to pass -Wmissing-prototypes */
XS(XS_EQLConfig_GetDynamicCount)
{
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: EQLConfig::GetDynamicCount(THIS)");
{
EQLConfig * THIS;
int RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "EQLConfig")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(EQLConfig *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type EQLConfig");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
RETVAL = THIS->GetDynamicCount();
XSprePUSH; PUSHi((IV)RETVAL);
}
XSRETURN(1);
}
XS(XS_EQLConfig_ListZones); /* prototype to pass -Wmissing-prototypes */
XS(XS_EQLConfig_ListZones)
{
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: EQLConfig::ListZones(THIS)");
{
EQLConfig * THIS;
vector<string> RETVAL;
if (sv_derived_from(ST(0), "EQLConfig")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(EQLConfig *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type EQLConfig");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
RETVAL = THIS->ListZones();
ST(0) = sv_newmortal();
{
U32 ix_RETVAL;
/* pop crap off the stack we dont really want */
POPs;
POPs;
/* grow the stack to the number of elements being returned */
EXTEND(SP, RETVAL.size());
for (ix_RETVAL = 0; ix_RETVAL < RETVAL.size(); ix_RETVAL++) {
const string &it = RETVAL[ix_RETVAL];
ST(ix_RETVAL) = sv_newmortal();
sv_setpvn(ST(ix_RETVAL), it.c_str(), it.length());
}
/* hackish, but im over it. The normal xsubpp return will be right below this */
XSRETURN(RETVAL.size());
}
}
XSRETURN(1);
}
XS(XS_EQLConfig_GetZoneDetails); /* prototype to pass -Wmissing-prototypes */
XS(XS_EQLConfig_GetZoneDetails)
{
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: EQLConfig::GetZoneDetails(THIS, zone_ref)");
{
EQLConfig * THIS;
map<string,string> RETVAL;
Const_char * zone_ref = (Const_char *)SvPV_nolen(ST(1));
if (sv_derived_from(ST(0), "EQLConfig")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(EQLConfig *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type EQLConfig");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
RETVAL = THIS->GetZoneDetails(zone_ref);
ST(0) = sv_newmortal();
if (RETVAL.begin()!=RETVAL.end())
{
//NOTE: we are leaking the original ST(0) right now
HV *hv = newHV();
sv_2mortal((SV*)hv);
ST(0) = newRV((SV*)hv);
map<string,string>::const_iterator cur, end;
cur = RETVAL.begin();
end = RETVAL.end();
for(; cur != end; cur++) {
/* get the element from the hash, creating if needed (will be needed) */
SV**ele = hv_fetch(hv, cur->first.c_str(), cur->first.length(), TRUE);
if(ele == NULL) {
Perl_croak(aTHX_ "Unable to create a hash element for RETVAL");
break;
}
/* put our string in the SV associated with this element in the hash */
sv_setpvn(*ele, cur->second.c_str(), cur->second.length());
}
}
}
XSRETURN(1);
}
#ifdef __cplusplus
extern "C"
#endif
XS(boot_EQLConfig); /* prototype to pass -Wmissing-prototypes */
XS(boot_EQLConfig)
{
dXSARGS;
char file[256];
strncpy(file, __FILE__, 256);
file[255] = 0;
if(items != 1)
fprintf(stderr, "boot_quest does not take any arguments.");
char buf[128];
//add the strcpy stuff to get rid of const warnings....
XS_VERSION_BOOTCHECK ;
newXSproto(strcpy(buf, "GetName"), XS_EQLConfig_GetName, file, "$");
newXSproto(strcpy(buf, "GetStaticCount"), XS_EQLConfig_GetStaticCount, file, "$");
newXSproto(strcpy(buf, "IsConnected"), XS_EQLConfig_IsConnected, file, "$");
newXSproto(strcpy(buf, "DeleteLauncher"), XS_EQLConfig_DeleteLauncher, file, "$");
newXSproto(strcpy(buf, "RestartZone"), XS_EQLConfig_RestartZone, file, "$$");
newXSproto(strcpy(buf, "StopZone"), XS_EQLConfig_StopZone, file, "$$");
newXSproto(strcpy(buf, "StartZone"), XS_EQLConfig_StartZone, file, "$$");
newXSproto(strcpy(buf, "BootStaticZone"), XS_EQLConfig_BootStaticZone, file, "$$$");
newXSproto(strcpy(buf, "ChangeStaticZone"), XS_EQLConfig_ChangeStaticZone, file, "$$$");
newXSproto(strcpy(buf, "DeleteStaticZone"), XS_EQLConfig_DeleteStaticZone, file, "$$");
newXSproto(strcpy(buf, "SetDynamicCount"), XS_EQLConfig_SetDynamicCount, file, "$$");
newXSproto(strcpy(buf, "GetDynamicCount"), XS_EQLConfig_GetDynamicCount, file, "$");
newXSproto(strcpy(buf, "ListZones"), XS_EQLConfig_ListZones, file, "$");
newXSproto(strcpy(buf, "GetZoneDetails"), XS_EQLConfig_GetZoneDetails, file, "$$");
XSRETURN_YES;
}
#endif //EMBPERL_XS_CLASSES
+1023
View File
File diff suppressed because it is too large Load Diff
+345
View File
@@ -0,0 +1,345 @@
/*
* This file was generated automatically by xsubpp version 1.9508 from the
* contents of tmp. Do not edit this file, edit tmp instead.
*
* ANY CHANGES MADE HERE WILL BE LOST!
*
*/
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
typedef const char Const_char;
#ifdef EMBPERL
#include "../common/debug.h"
#include "EQWParser.h"
#include "HTTPRequest.h"
#ifdef THIS /* this macro seems to leak out on some systems */
#undef THIS
#endif
XS(XS_HTTPRequest_get); /* prototype to pass -Wmissing-prototypes */
XS(XS_HTTPRequest_get)
{
dXSARGS;
if (items < 2 || items > 3)
Perl_croak(aTHX_ "Usage: HTTPRequest::get(THIS, name, default_value= \"\")");
{
HTTPRequest * THIS;
Const_char * RETVAL;
dXSTARG;
Const_char * name = (Const_char *)SvPV_nolen(ST(1));
Const_char * default_value;
if (sv_derived_from(ST(0), "HTTPRequest")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(HTTPRequest *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type HTTPRequest");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
if (items < 3)
default_value = "";
else {
default_value = (Const_char *)SvPV_nolen(ST(2));
}
RETVAL = THIS->get(name, default_value);
sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
}
XSRETURN(1);
}
XS(XS_HTTPRequest_getInt); /* prototype to pass -Wmissing-prototypes */
XS(XS_HTTPRequest_getInt)
{
dXSARGS;
if (items < 2 || items > 3)
Perl_croak(aTHX_ "Usage: HTTPRequest::getInt(THIS, name, default_value= 0)");
{
HTTPRequest * THIS;
int RETVAL;
dXSTARG;
Const_char * name = (Const_char *)SvPV_nolen(ST(1));
int default_value;
if (sv_derived_from(ST(0), "HTTPRequest")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(HTTPRequest *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type HTTPRequest");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
if (items < 3)
default_value = 0;
else {
default_value = (int)SvIV(ST(2));
}
RETVAL = THIS->getInt(name, default_value);
XSprePUSH; PUSHi((IV)RETVAL);
}
XSRETURN(1);
}
XS(XS_HTTPRequest_getFloat); /* prototype to pass -Wmissing-prototypes */
XS(XS_HTTPRequest_getFloat)
{
dXSARGS;
if (items < 2 || items > 3)
Perl_croak(aTHX_ "Usage: HTTPRequest::getFloat(THIS, name, default_value= 0.0)");
{
HTTPRequest * THIS;
float RETVAL;
dXSTARG;
Const_char * name = (Const_char *)SvPV_nolen(ST(1));
float default_value;
if (sv_derived_from(ST(0), "HTTPRequest")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(HTTPRequest *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type HTTPRequest");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
if (items < 3)
default_value = 0.0;
else {
default_value = (float)SvNV(ST(2));
}
RETVAL = THIS->getFloat(name, default_value);
XSprePUSH; PUSHn((double)RETVAL);
}
XSRETURN(1);
}
XS(XS_HTTPRequest_getEscaped); /* prototype to pass -Wmissing-prototypes */
XS(XS_HTTPRequest_getEscaped)
{
dXSARGS;
if (items < 2 || items > 3)
Perl_croak(aTHX_ "Usage: HTTPRequest::getEscaped(THIS, name, default_value= \"\")");
{
HTTPRequest * THIS;
Const_char * RETVAL;
dXSTARG;
Const_char * name = (Const_char *)SvPV_nolen(ST(1));
Const_char * default_value;
if (sv_derived_from(ST(0), "HTTPRequest")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(HTTPRequest *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type HTTPRequest");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
if (items < 3)
default_value = "";
else {
default_value = (Const_char *)SvPV_nolen(ST(2));
}
RETVAL = THIS->getEscaped(name, default_value);
sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
}
XSRETURN(1);
}
XS(XS_HTTPRequest_get_all); /* prototype to pass -Wmissing-prototypes */
XS(XS_HTTPRequest_get_all)
{
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: HTTPRequest::get_all(THIS)");
{
HTTPRequest * THIS;
map<string,string> RETVAL;
if (sv_derived_from(ST(0), "HTTPRequest")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(HTTPRequest *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type HTTPRequest");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
RETVAL = THIS->get_all();
ST(0) = sv_newmortal();
if (RETVAL.begin()!=RETVAL.end())
{
//NOTE: we are leaking the original ST(0) right now
HV *hv = newHV();
sv_2mortal((SV*)hv);
ST(0) = newRV((SV*)hv);
map<string,string>::const_iterator cur, end;
cur = RETVAL.begin();
end = RETVAL.end();
for(; cur != end; cur++) {
/* get the element from the hash, creating if needed (will be needed) */
SV**ele = hv_fetch(hv, cur->first.c_str(), cur->first.length(), TRUE);
if(ele == NULL) {
Perl_croak(aTHX_ "Unable to create a hash element for RETVAL");
break;
}
/* put our string in the SV associated with this element in the hash */
sv_setpvn(*ele, cur->second.c_str(), cur->second.length());
}
}
}
XSRETURN(1);
}
XS(XS_HTTPRequest_redirect); /* prototype to pass -Wmissing-prototypes */
XS(XS_HTTPRequest_redirect)
{
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: HTTPRequest::redirect(THIS, URL)");
{
HTTPRequest * THIS;
Const_char * URL = (Const_char *)SvPV_nolen(ST(1));
if (sv_derived_from(ST(0), "HTTPRequest")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(HTTPRequest *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type HTTPRequest");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
THIS->redirect(URL);
}
XSRETURN_EMPTY;
}
XS(XS_HTTPRequest_SetResponseCode); /* prototype to pass -Wmissing-prototypes */
XS(XS_HTTPRequest_SetResponseCode)
{
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: HTTPRequest::SetResponseCode(THIS, code)");
{
HTTPRequest * THIS;
Const_char * code = (Const_char *)SvPV_nolen(ST(1));
if (sv_derived_from(ST(0), "HTTPRequest")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(HTTPRequest *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type HTTPRequest");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
THIS->SetResponseCode(code);
}
XSRETURN_EMPTY;
}
XS(XS_HTTPRequest_header); /* prototype to pass -Wmissing-prototypes */
XS(XS_HTTPRequest_header)
{
dXSARGS;
if (items != 3)
Perl_croak(aTHX_ "Usage: HTTPRequest::header(THIS, name, value)");
{
HTTPRequest * THIS;
Const_char * name = (Const_char *)SvPV_nolen(ST(1));
Const_char * value = (Const_char *)SvPV_nolen(ST(2));
if (sv_derived_from(ST(0), "HTTPRequest")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(HTTPRequest *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type HTTPRequest");
if(THIS == NULL)
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
THIS->header(name, value);
}
XSRETURN_EMPTY;
}
#ifdef __cplusplus
extern "C"
#endif
XS(boot_HTTPRequest); /* prototype to pass -Wmissing-prototypes */
XS(boot_HTTPRequest)
{
dXSARGS;
char file[256];
strncpy(file, __FILE__, 256);
file[255] = 0;
if(items != 1)
fprintf(stderr, "boot_quest does not take any arguments.");
char buf[128];
//add the strcpy stuff to get rid of const warnings....
XS_VERSION_BOOTCHECK ;
newXSproto(strcpy(buf, "get"), XS_HTTPRequest_get, file, "$$;$");
newXSproto(strcpy(buf, "getInt"), XS_HTTPRequest_getInt, file, "$$;$");
newXSproto(strcpy(buf, "getFloat"), XS_HTTPRequest_getFloat, file, "$$;$");
newXSproto(strcpy(buf, "getEscaped"), XS_HTTPRequest_getEscaped, file, "$$;$");
newXSproto(strcpy(buf, "get_all"), XS_HTTPRequest_get_all, file, "$");
newXSproto(strcpy(buf, "redirect"), XS_HTTPRequest_redirect, file, "$$");
newXSproto(strcpy(buf, "SetResponseCode"), XS_HTTPRequest_SetResponseCode, file, "$$");
newXSproto(strcpy(buf, "header"), XS_HTTPRequest_header, file, "$$$");
XSRETURN_YES;
}
#endif //EMBPERL_XS_CLASSES
+133
View File
@@ -0,0 +1,133 @@
#include "../common/debug.h"
#include "queryserv.h"
#include "WorldConfig.h"
#include "clientlist.h"
#include "zonelist.h"
#include "../common/logsys.h"
#include "../common/logtypes.h"
#include "../common/md5.h"
#include "../common/EmuTCPConnection.h"
#include "../common/packet_dump.h"
extern ClientList client_list;
extern ZSList zoneserver_list;
QueryServConnection::QueryServConnection()
{
Stream = 0;
authenticated = false;
}
void QueryServConnection::SetConnection(EmuTCPConnection *inStream)
{
if(Stream)
{
_log(QUERYSERV__ERROR, "Incoming QueryServ Connection while we were already connected to a QueryServ.");
Stream->Disconnect();
}
Stream = inStream;
authenticated = false;
}
bool QueryServConnection::Process()
{
if (!Stream || !Stream->Connected())
return false;
ServerPacket *pack = 0;
while((pack = Stream->PopPacket()))
{
if (!authenticated)
{
if (WorldConfig::get()->SharedKey.length() > 0)
{
if (pack->opcode == ServerOP_ZAAuth && pack->size == 16)
{
uint8 tmppass[16];
MD5::Generate((const uchar*) WorldConfig::get()->SharedKey.c_str(), WorldConfig::get()->SharedKey.length(), tmppass);
if (memcmp(pack->pBuffer, tmppass, 16) == 0)
authenticated = true;
else
{
struct in_addr in;
in.s_addr = GetIP();
_log(QUERYSERV__ERROR, "QueryServ authorization failed.");
ServerPacket* pack = new ServerPacket(ServerOP_ZAAuthFailed);
SendPacket(pack);
delete pack;
Disconnect();
return false;
}
}
else
{
struct in_addr in;
in.s_addr = GetIP();
_log(QUERYSERV__ERROR, "QueryServ authorization failed.");
ServerPacket* pack = new ServerPacket(ServerOP_ZAAuthFailed);
SendPacket(pack);
delete pack;
Disconnect();
return false;
}
}
else
{
_log(QUERYSERV__ERROR,"**WARNING** You have not configured a world shared key in your config file. You should add a <key>STRING</key> element to your <world> element to prevent unauthroized zone access.");
authenticated = true;
}
delete pack;
continue;
}
switch(pack->opcode)
{
case 0:
break;
case ServerOP_KeepAlive:
{
// ignore this
break;
}
case ServerOP_ZAAuth:
{
_log(QUERYSERV__ERROR, "Got authentication from QueryServ when they are already authenticated.");
break;
}
case ServerOP_QueryServGeneric:
{
uint32 ZoneID = pack->ReadUInt32();
uint16 InstanceID = pack->ReadUInt32();
zoneserver_list.SendPacket(ZoneID, InstanceID, pack);
break;
}
case ServerOP_LFGuildUpdate:
{
zoneserver_list.SendPacket(pack);
break;
}
default:
{
_log(QUERYSERV__ERROR, "Unknown ServerOPcode from QueryServ 0x%04x, size %d", pack->opcode, pack->size);
DumpPacket(pack->pBuffer, pack->size);
break;
}
}
delete pack;
}
return(true);
}
bool QueryServConnection::SendPacket(ServerPacket* pack)
{
if(!Stream)
return false;
return Stream->SendPacket(pack);
}
+23
View File
@@ -0,0 +1,23 @@
#ifndef QueryServ_H
#define QueryServ_H
#include "../common/types.h"
#include "../common/EmuTCPConnection.h"
#include "../common/servertalk.h"
class QueryServConnection
{
public:
QueryServConnection();
void SetConnection(EmuTCPConnection *inStream);
bool Process();
bool SendPacket(ServerPacket* pack);
void Disconnect() { if(Stream) Stream->Disconnect(); }
void SendMessage(const char *From, const char *Message);
private:
inline uint32 GetIP() const { return Stream ? Stream->GetrIP() : 0; }
EmuTCPConnection *Stream;
bool authenticated;
};
#endif /*QueryServ_H_*/
+129
View File
@@ -0,0 +1,129 @@
#include "../common/debug.h"
#include "ucs.h"
#include "WorldConfig.h"
#include "../common/logsys.h"
#include "../common/logtypes.h"
#include "../common/md5.h"
#include "../common/EmuTCPConnection.h"
#include "../common/packet_dump.h"
UCSConnection::UCSConnection()
{
Stream = 0;
authenticated = false;
}
void UCSConnection::SetConnection(EmuTCPConnection *inStream)
{
if(Stream)
{
_log(UCS__ERROR, "Incoming UCS Connection while we were already connected to a UCS.");
Stream->Disconnect();
}
Stream = inStream;
authenticated = false;
}
bool UCSConnection::Process()
{
if (!Stream || !Stream->Connected())
return false;
ServerPacket *pack = 0;
while((pack = Stream->PopPacket()))
{
if (!authenticated)
{
if (WorldConfig::get()->SharedKey.length() > 0)
{
if (pack->opcode == ServerOP_ZAAuth && pack->size == 16)
{
uint8 tmppass[16];
MD5::Generate((const uchar*) WorldConfig::get()->SharedKey.c_str(), WorldConfig::get()->SharedKey.length(), tmppass);
if (memcmp(pack->pBuffer, tmppass, 16) == 0)
authenticated = true;
else
{
struct in_addr in;
in.s_addr = GetIP();
_log(UCS__ERROR, "UCS authorization failed.");
ServerPacket* pack = new ServerPacket(ServerOP_ZAAuthFailed);
SendPacket(pack);
delete pack;
Disconnect();
return false;
}
}
else
{
struct in_addr in;
in.s_addr = GetIP();
_log(UCS__ERROR, "UCS authorization failed.");
ServerPacket* pack = new ServerPacket(ServerOP_ZAAuthFailed);
SendPacket(pack);
delete pack;
Disconnect();
return false;
}
}
else
{
_log(UCS__ERROR,"**WARNING** You have not configured a world shared key in your config file. You should add a <key>STRING</key> element to your <world> element to prevent unauthroized zone access.");
authenticated = true;
}
delete pack;
continue;
}
switch(pack->opcode)
{
case 0:
break;
case ServerOP_KeepAlive:
{
// ignore this
break;
}
case ServerOP_ZAAuth:
{
_log(UCS__ERROR, "Got authentication from UCS when they are already authenticated.");
break;
}
default:
{
_log(UCS__ERROR, "Unknown ServerOPcode from UCS 0x%04x, size %d", pack->opcode, pack->size);
DumpPacket(pack->pBuffer, pack->size);
break;
}
}
delete pack;
}
return(true);
}
bool UCSConnection::SendPacket(ServerPacket* pack)
{
if(!Stream)
return false;
return Stream->SendPacket(pack);
}
void UCSConnection::SendMessage(const char *From, const char *Message)
{
ServerPacket* pack = new ServerPacket(ServerOP_UCSMessage, strlen(From) + strlen(Message) + 2);
char *Buffer = (char *)pack->pBuffer;
VARSTRUCT_ENCODE_STRING(Buffer, From);
VARSTRUCT_ENCODE_STRING(Buffer, Message);
SendPacket(pack);
safe_delete(pack);
}
+23
View File
@@ -0,0 +1,23 @@
#ifndef UCS_H
#define UCS_H
#include "../common/types.h"
#include "../common/EmuTCPConnection.h"
#include "../common/servertalk.h"
class UCSConnection
{
public:
UCSConnection();
void SetConnection(EmuTCPConnection *inStream);
bool Process();
bool SendPacket(ServerPacket* pack);
void Disconnect() { if(Stream) Stream->Disconnect(); }
void SendMessage(const char *From, const char *Message);
private:
inline uint32 GetIP() const { return Stream ? Stream->GetrIP() : 0; }
EmuTCPConnection *Stream;
bool authenticated;
};
#endif /*UCS_H_*/
+172
View File
@@ -0,0 +1,172 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "wguild_mgr.h"
#include "../common/servertalk.h"
#include "clientlist.h"
#include "zonelist.h"
extern ClientList client_list;
extern ZSList zoneserver_list;
WorldGuildManager guild_mgr;
void WorldGuildManager::SendGuildRefresh(uint32 guild_id, bool name, bool motd, bool rank, bool relation) {
_log(GUILDS__REFRESH, "Broadcasting guild refresh for %d, changes: name=%d, motd=%d, rank=d, relation=%d", guild_id, name, motd, rank, relation);
ServerPacket* pack = new ServerPacket(ServerOP_RefreshGuild, sizeof(ServerGuildRefresh_Struct));
ServerGuildRefresh_Struct *s = (ServerGuildRefresh_Struct *) pack->pBuffer;
s->guild_id = guild_id;
s->name_change = name;
s->motd_change = motd;
s->rank_change = rank;
s->relation_change = relation;
zoneserver_list.SendPacket(pack);
safe_delete(pack);
}
void WorldGuildManager::SendCharRefresh(uint32 old_guild_id, uint32 guild_id, uint32 charid) {
_log(GUILDS__REFRESH, "Broadcasting char refresh for %d from guild %d to world", charid, guild_id);
ServerPacket* pack = new ServerPacket(ServerOP_GuildCharRefresh, sizeof(ServerGuildCharRefresh_Struct));
ServerGuildCharRefresh_Struct *s = (ServerGuildCharRefresh_Struct *) pack->pBuffer;
s->guild_id = guild_id;
s->old_guild_id = old_guild_id;
s->char_id = charid;
zoneserver_list.SendPacket(pack);
safe_delete(pack);
}
void WorldGuildManager::SendGuildDelete(uint32 guild_id) {
_log(GUILDS__REFRESH, "Broadcasting guild delete for guild %d to world", guild_id);
ServerPacket* pack = new ServerPacket(ServerOP_DeleteGuild, sizeof(ServerGuildID_Struct));
ServerGuildID_Struct *s = (ServerGuildID_Struct *) pack->pBuffer;
s->guild_id = guild_id;
zoneserver_list.SendPacket(pack);
safe_delete(pack);
}
void WorldGuildManager::ProcessZonePacket(ServerPacket *pack) {
switch(pack->opcode) {
case ServerOP_RefreshGuild: {
if(pack->size != sizeof(ServerGuildRefresh_Struct)) {
_log(GUILDS__ERROR, "Received ServerOP_RefreshGuild of incorrect size %d, expected %d", pack->size, sizeof(ServerGuildRefresh_Struct));
return;
}
ServerGuildRefresh_Struct *s = (ServerGuildRefresh_Struct *) pack->pBuffer;
_log(GUILDS__REFRESH, "Received and broadcasting guild refresh for %d, changes: name=%d, motd=%d, rank=d, relation=%d", s->guild_id, s->name_change, s->motd_change, s->rank_change, s->relation_change);
//broadcast this packet to all zones.
zoneserver_list.SendPacket(pack);
//preform a local refresh.
if(!RefreshGuild(s->guild_id)) {
_log(GUILDS__ERROR, "Unable to preform local refresh on guild %d", s->guild_id);
//can we do anything?
}
break;
}
case ServerOP_GuildCharRefresh: {
if(pack->size != sizeof(ServerGuildCharRefresh_Struct)) {
_log(GUILDS__ERROR, "Received ServerOP_RefreshGuild of incorrect size %d, expected %d", pack->size, sizeof(ServerGuildCharRefresh_Struct));
return;
}
ServerGuildCharRefresh_Struct *s = (ServerGuildCharRefresh_Struct *) pack->pBuffer;
_log(GUILDS__REFRESH, "Received and broadcasting guild member refresh for char %d to all zones with members of guild %d", s->char_id, s->guild_id);
//preform the local update
client_list.UpdateClientGuild(s->char_id, s->guild_id);
//broadcast this update to any zone with a member in this guild.
//client_list.SendGuildPacket(s->guild_id, pack);
//because im sick of this not working, sending it to all zones, just spends a bit more bandwidth.
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_DeleteGuild: {
if(pack->size != sizeof(ServerGuildID_Struct)) {
_log(GUILDS__ERROR, "Received ServerOP_DeleteGuild of incorrect size %d, expected %d", pack->size, sizeof(ServerGuildID_Struct));
return;
}
ServerGuildID_Struct *s = (ServerGuildID_Struct *) pack->pBuffer;
_log(GUILDS__REFRESH, "Received and broadcasting guild delete for guild %d", s->guild_id);
//broadcast this packet to all zones.
zoneserver_list.SendPacket(pack);
//preform a local refresh.
if(!LocalDeleteGuild(s->guild_id)) {
_log(GUILDS__ERROR, "Unable to preform local delete on guild %d", s->guild_id);
//can we do anything?
}
break;
}
case ServerOP_GuildMemberUpdate: {
if(pack->size != sizeof(ServerGuildMemberUpdate_Struct))
{
_log(GUILDS__ERROR, "Received ServerOP_GuildMemberUpdate of incorrect size %d, expected %d", pack->size, sizeof(ServerGuildMemberUpdate_Struct));
return;
}
zoneserver_list.SendPacket(pack);
break;
}
default:
_log(GUILDS__ERROR, "Unknown packet 0x%x received from zone??", pack->opcode);
break;
}
}
+31
View File
@@ -0,0 +1,31 @@
#ifndef GUILD_MGR_H_
#define GUILD_MGR_H_
#include "../common/types.h"
#include "../common/guild_base.h"
class Client;
class ServerPacket;
class WorldGuildManager : public BaseGuildManager {
public:
//called by zoneserver when it receives a guild message from zone.
void ProcessZonePacket(ServerPacket *pack);
uint8 *MakeGuildMembers(uint32 guild_id, const char *prefix_name, uint32 &length); //make a guild member list packet, returns ownership of the buffer.
protected:
virtual void SendGuildRefresh(uint32 guild_id, bool name, bool motd, bool rank, bool relation);
virtual void SendCharRefresh(uint32 old_guild_id, uint32 guild_id, uint32 charid);
virtual void SendRankUpdate(uint32 CharID) { return; }
virtual void SendGuildDelete(uint32 guild_id);
//map<uint32, uint32> m_tribute; //map from guild ID to current tribute ammount
};
extern WorldGuildManager guild_mgr;
#endif /*GUILD_MGR_H_*/
+58
View File
@@ -0,0 +1,58 @@
#include "../common/debug.h"
#include "../common/logsys.h"
#include "zoneserver.h"
#include "client.h"
#include <stdarg.h>
#include <stdio.h>
void log_message_clientVA(LogType type, Client *who, const char *fmt, va_list args) {
char prefix_buffer[256];
snprintf(prefix_buffer, 255, "[%s] %s: ", log_type_info[type].name, who->GetAccountName());
prefix_buffer[255] = '\0';
LogFile->writePVA(EQEMuLog::Debug, prefix_buffer, fmt, args);
}
void log_message_client(LogType type, Client *who, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
log_message_clientVA(type, who, fmt, args);
va_end(args);
}
void log_message_zoneVA(LogType type, ZoneServer *who, const char *fmt, va_list args) {
char prefix_buffer[256];
char zone_tag[65];
const char *zone_name=who->GetZoneName();
if (*zone_name==0)
snprintf(zone_tag,64,"[%d]", who->GetID());
else
snprintf(zone_tag,64,"[%d] [%s]",who->GetID(),zone_name);
snprintf(prefix_buffer, 255, "[%s] %s ", log_type_info[type].name, zone_tag);
prefix_buffer[255] = '\0';
LogFile->writePVA(EQEMuLog::Debug, prefix_buffer, fmt, args);
}
void log_message_zone(LogType type, ZoneServer *who, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
log_message_zoneVA(type, who, fmt, args);
va_end(args);
}
+650
View File
@@ -0,0 +1,650 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "worlddb.h"
//#include "../common/Item.h"
#include "../common/MiscFunctions.h"
#include "../common/eq_packet_structs.h"
#include "../common/Item.h"
#include "../common/dbasync.h"
#include "../common/rulesys.h"
#include <iostream>
#include <cstdlib>
#include <vector>
#include "SoFCharCreateData.h"
using namespace std;
WorldDatabase database;
extern std::vector<RaceClassAllocation> character_create_allocations;
extern std::vector<RaceClassCombos> character_create_race_class_combos;
// solar: the current stuff is at the bottom of this function
void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct* cs) {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
Inventory *inv;
for (int i=0; i<10; i++) {
strcpy(cs->name[i], "<none>");
cs->zone[i] = 0;
cs->level[i] = 0;
cs->tutorial[i] = 0;
cs->gohome[i] = 0;
}
int char_num = 0;
unsigned long* lengths;
// Populate character info
if (RunQuery(query, MakeAnyLenString(&query, "SELECT name,profile,zonename,class,level FROM character_ WHERE account_id=%i order by name limit 10", account_id), errbuf, &result)) {
safe_delete_array(query);
while ((row = mysql_fetch_row(result))) {
lengths = mysql_fetch_lengths(result);
////////////
//////////// This is the current one, the other are for converting
////////////
if ((lengths[1] == sizeof(PlayerProfile_Struct))) {
strcpy(cs->name[char_num], row[0]);
PlayerProfile_Struct* pp = (PlayerProfile_Struct*)row[1];
uint8 clas = atoi(row[3]);
uint8 lvl = atoi(row[4]);
// Character information
if(lvl == 0)
cs->level[char_num] = pp->level; //no level in DB, trust PP
else
cs->level[char_num] = lvl;
if(clas == 0)
cs->class_[char_num] = pp->class_; //no class in DB, trust PP
else
cs->class_[char_num] = clas;
cs->race[char_num] = pp->race;
cs->gender[char_num] = pp->gender;
cs->deity[char_num] = pp->deity;
cs->zone[char_num] = GetZoneID(row[2]);
cs->face[char_num] = pp->face;
cs->haircolor[char_num] = pp->haircolor;
cs->beardcolor[char_num] = pp->beardcolor;
cs->eyecolor2[char_num] = pp->eyecolor2;
cs->eyecolor1[char_num] = pp->eyecolor1;
cs->hairstyle[char_num] = pp->hairstyle;
cs->beard[char_num] = pp->beard;
cs->drakkin_heritage[char_num] = pp->drakkin_heritage;
cs->drakkin_tattoo[char_num] = pp->drakkin_tattoo;
cs->drakkin_details[char_num] = pp->drakkin_details;
if(RuleB(World, EnableTutorialButton) && (lvl <= RuleI(World, MaxLevelForTutorial)))
cs->tutorial[char_num] = 1;
if(RuleB(World, EnableReturnHomeButton)) {
int now = time(NULL);
if((now - pp->lastlogin) >= RuleI(World, MinOfflineTimeToReturnHome))
cs->gohome[char_num] = 1;
}
// This part creates home city entries for characters created before the home bind point was tracked.
// Do it here because the player profile is already loaded and it's as good a spot as any. This whole block should
// probably be removed at some point, when most accounts are safely converted.
if(pp->binds[4].zoneId == 0) {
bool altered = false;
MYSQL_RES *result2;
MYSQL_ROW row2;
char startzone[50] = {0};
// check for start zone variable (I didn't even know any variables were still being used...)
if(database.GetVariable("startzone", startzone, 50)) {
uint32 zoneid = database.GetZoneID(startzone);
if(zoneid) {
pp->binds[4].zoneId = zoneid;
GetSafePoints(zoneid, 0, &pp->binds[4].x, &pp->binds[4].y, &pp->binds[4].z);
altered = true;
}
}
else {
RunQuery(query,
MakeAnyLenString(&query,
"SELECT zone_id,bind_id,x,y,z FROM start_zones "
"WHERE player_class=%i AND player_deity=%i AND player_race=%i",
pp->class_,
pp->deity,
pp->race
),
errbuf,
&result2
);
safe_delete_array(query);
// if there is only one possible start city, set it
if(mysql_num_rows(result2) == 1) {
row2 = mysql_fetch_row(result2);
if(atoi(row2[1]) != 0) { // if a bind_id is specified, make them start there
pp->binds[4].zoneId = (uint32)atoi(row2[1]);
GetSafePoints(pp->binds[4].zoneId, 0, &pp->binds[4].x, &pp->binds[4].y, &pp->binds[4].z);
}
else { // otherwise, use the zone and coordinates given
pp->binds[4].zoneId = (uint32)atoi(row2[0]);
float x = atof(row2[2]);
float y = atof(row2[3]);
float z = atof(row2[4]);
if(x == 0 && y == 0 && z == 0)
GetSafePoints(pp->binds[4].zoneId, 0, &x, &y, &z);
pp->binds[4].x = x;
pp->binds[4].y = y;
pp->binds[4].z = z;
}
altered = true;
}
mysql_free_result(result2);
}
// update the player profile
if(altered) {
uint32 char_id = GetCharacterID(cs->name[char_num]);
RunQuery(query,MakeAnyLenString(&query,"SELECT extprofile FROM character_ WHERE id=%i",char_id), errbuf, &result2);
safe_delete_array(query);
if(result2) {
row2 = mysql_fetch_row(result2);
ExtendedProfile_Struct* ext = (ExtendedProfile_Struct*)row2[0];
SetPlayerProfile(account_id,char_id,pp,inv,ext, 0, 0, 5);
}
mysql_free_result(result2);
}
} // end of "set start zone" block
// Character's equipped items
// @merth: Haven't done bracer01/bracer02 yet.
// Also: this needs a second look after items are a little more solid
// NOTE: items don't have a color, players MAY have a tint, if the
// use_tint part is set. otherwise use the regular color
inv = new Inventory;
if(GetInventory(account_id, cs->name[char_num], inv))
{
for (uint8 material = 0; material <= 8; material++)
{
uint32 color;
ItemInst *item = inv->GetItem(Inventory::CalcSlotFromMaterial(material));
if(item == 0)
continue;
cs->equip[char_num][material] = item->GetItem()->Material;
if(pp->item_tint[material].rgb.use_tint) // they have a tint (LoY dye)
color = pp->item_tint[material].color;
else // no tint, use regular item color
color = item->GetItem()->Color;
cs->cs_colors[char_num][material].color = color;
// the weapons are kept elsewhere
if ((material==MATERIAL_PRIMARY) || (material==MATERIAL_SECONDARY))
{
if(strlen(item->GetItem()->IDFile) > 2) {
uint32 idfile=atoi(&item->GetItem()->IDFile[2]);
if (material==MATERIAL_PRIMARY)
cs->primary[char_num]=idfile;
else
cs->secondary[char_num]=idfile;
}
}
}
}
else
{
printf("Error loading inventory for %s\n", cs->name[char_num]);
}
safe_delete(inv);
if (++char_num > 10)
break;
}
else
{
cout << "Got a bogus character (" << row[0] << ") Ignoring!!!" << endl;
cout << "PP length ="<<lengths[1]<<" but PP should be "<<sizeof(PlayerProfile_Struct)<<endl;
//DeleteCharacter(row[0]);
}
}
mysql_free_result(result);
}
else
{
cerr << "Error in GetCharSelectInfo query '" << query << "' " << errbuf << endl;
safe_delete_array(query);
return;
}
return;
}
int WorldDatabase::MoveCharacterToBind(int CharID, uint8 bindnum) {
// if an invalid bind point is specified, use the primary bind
if (bindnum > 4)
bindnum = 0;
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
uint32 affected_rows = 0;
PlayerProfile_Struct pp;
bool PPValid = false;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT profile from character_ where id='%i'", CharID), errbuf, &result)) {
row = mysql_fetch_row(result);
unsigned long* lengths = mysql_fetch_lengths(result);
if (lengths[0] == sizeof(PlayerProfile_Struct)) {
memcpy(&pp, row[0], sizeof(PlayerProfile_Struct));
PPValid = true;
}
mysql_free_result(result);
}
safe_delete_array(query);
if(!PPValid) return 0;
const char *BindZoneName = StaticGetZoneName(pp.binds[bindnum].zoneId);
if(!strcmp(BindZoneName, "UNKNWN")) return pp.zone_id;
if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET zonename = '%s',zoneid=%i,x=%f, y=%f, z=%f, instanceid=0 WHERE id='%i'",
BindZoneName, pp.binds[bindnum].zoneId, pp.binds[bindnum].x, pp.binds[bindnum].y, pp.binds[bindnum].z,
CharID), errbuf, 0,&affected_rows)) {
return pp.zone_id;
}
safe_delete_array(query);
return pp.binds[bindnum].zoneId;
}
bool WorldDatabase::GetStartZone(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_cc)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row = 0;
int rows;
if(!in_pp || !in_cc)
return false;
in_pp->x = in_pp->y = in_pp->z = in_pp->heading = in_pp->zone_id = 0;
in_pp->binds[0].x = in_pp->binds[0].y = in_pp->binds[0].z = in_pp->binds[0].zoneId = 0;
RunQuery
(
query,
MakeAnyLenString
(
&query,
"SELECT x,y,z,heading,zone_id,bind_id FROM start_zones "
"WHERE player_choice=%i AND player_class=%i "
"AND player_deity=%i AND player_race=%i",
in_cc->start_zone,
in_cc->class_,
in_cc->deity,
in_cc->race
),
errbuf,
&result
);
LogFile->write(EQEMuLog::Status, "Start zone query: %s\n", query);
safe_delete_array(query);
if((rows = mysql_num_rows(result)) > 0)
row = mysql_fetch_row(result);
if(row)
{
LogFile->write(EQEMuLog::Status, "Found starting location in start_zones");
in_pp->x = atof(row[0]);
in_pp->y = atof(row[1]);
in_pp->z = atof(row[2]);
in_pp->heading = atof(row[3]);
in_pp->zone_id = atoi(row[4]);
in_pp->binds[0].zoneId = atoi(row[5]);
}
else
{
printf("No start_zones entry in database, using defaults\n");
switch(in_cc->start_zone)
{
case 0:
{
in_pp->zone_id = 24; // erudnext
in_pp->binds[0].zoneId = 38; // tox
break;
}
case 1:
{
in_pp->zone_id =2; // qeynos2
in_pp->binds[0].zoneId = 2; // qeynos2
break;
}
case 2:
{
in_pp->zone_id =29; // halas
in_pp->binds[0].zoneId = 30; // everfrost
break;
}
case 3:
{
in_pp->zone_id =19; // rivervale
in_pp->binds[0].zoneId = 20; // kithicor
break;
}
case 4:
{
in_pp->zone_id =9; // freportw
in_pp->binds[0].zoneId = 9; // freportw
break;
}
case 5:
{
in_pp->zone_id =40; // neriaka
in_pp->binds[0].zoneId = 25; // nektulos
break;
}
case 6:
{
in_pp->zone_id =52; // gukta
in_pp->binds[0].zoneId = 46; // innothule
break;
}
case 7:
{
in_pp->zone_id =49; // oggok
in_pp->binds[0].zoneId = 47; // feerrott
break;
}
case 8:
{
in_pp->zone_id =60; // kaladima
in_pp->binds[0].zoneId = 68; // butcher
break;
}
case 9:
{
in_pp->zone_id =54; // gfaydark
in_pp->binds[0].zoneId = 54; // gfaydark
break;
}
case 10:
{
in_pp->zone_id =61; // felwithea
in_pp->binds[0].zoneId = 54; // gfaydark
break;
}
case 11:
{
in_pp->zone_id =55; // akanon
in_pp->binds[0].zoneId = 56; // steamfont
break;
}
case 12:
{
in_pp->zone_id =82; // cabwest
in_pp->binds[0].zoneId = 78; // fieldofbone
break;
}
case 13:
{
in_pp->zone_id =155; // sharvahl
in_pp->binds[0].zoneId = 155; // sharvahl
break;
}
}
}
if(in_pp->x == 0 && in_pp->y == 0 && in_pp->z == 0)
database.GetSafePoints(in_pp->zone_id, 0, &in_pp->x, &in_pp->y, &in_pp->z);
if(in_pp->binds[0].x == 0 && in_pp->binds[0].y == 0 && in_pp->binds[0].z == 0)
database.GetSafePoints(in_pp->binds[0].zoneId, 0, &in_pp->binds[0].x, &in_pp->binds[0].y, &in_pp->binds[0].z);
if(result)
mysql_free_result(result);
return true;
}
bool WorldDatabase::GetStartZoneSoF(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_cc)
{
// SoF doesn't send the player_choice field in character creation, it now sends the real zoneID instead.
//
// For SoF, search for an entry in start_zones with a matching zone_id, class, race and deity.
//
// For now, if no row matching row is found, send them to Crescent Reach, as that is probably the most likely
// reason for no match being found.
//
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row = 0;
int rows;
if(!in_pp || !in_cc)
return false;
in_pp->x = in_pp->y = in_pp->z = in_pp->heading = in_pp->zone_id = 0;
in_pp->binds[0].x = in_pp->binds[0].y = in_pp->binds[0].z = in_pp->binds[0].zoneId = 0;
RunQuery
(
query,
MakeAnyLenString
(
&query,
"SELECT x,y,z,heading,bind_id FROM start_zones "
"WHERE zone_id=%i AND player_class=%i "
"AND player_deity=%i AND player_race=%i",
in_cc->start_zone,
in_cc->class_,
in_cc->deity,
in_cc->race
),
errbuf,
&result
);
LogFile->write(EQEMuLog::Status, "SoF Start zone query: %s\n", query);
_log(WORLD__CLIENT_TRACE, "SoF Start zone query: %s\n", query);
safe_delete_array(query);
if((rows = mysql_num_rows(result)) > 0)
row = mysql_fetch_row(result);
if(row)
{
LogFile->write(EQEMuLog::Status, "Found starting location in start_zones");
in_pp->x = atof(row[0]);
in_pp->y = atof(row[1]);
in_pp->z = atof(row[2]);
in_pp->heading = atof(row[3]);
in_pp->zone_id = in_cc->start_zone;
in_pp->binds[0].zoneId = atoi(row[4]);
}
else
{
printf("No start_zones entry in database, using defaults\n");
if(in_cc->start_zone == RuleI(World, TutorialZoneID))
in_pp->zone_id = in_cc->start_zone;
else {
in_pp->x = in_pp->binds[0].x = -51;
in_pp->y = in_pp->binds[0].y = -20;
in_pp->z = in_pp->binds[0].z = 0.79;
in_pp->zone_id = in_pp->binds[0].zoneId = 394; // Crescent Reach.
}
}
if(in_pp->x == 0 && in_pp->y == 0 && in_pp->z == 0)
database.GetSafePoints(in_pp->zone_id, 0, &in_pp->x, &in_pp->y, &in_pp->z);
if(in_pp->binds[0].x == 0 && in_pp->binds[0].y == 0 && in_pp->binds[0].z == 0)
database.GetSafePoints(in_pp->binds[0].zoneId, 0, &in_pp->binds[0].x, &in_pp->binds[0].y, &in_pp->binds[0].z);
if(result)
mysql_free_result(result);
return true;
}
void WorldDatabase::GetLauncherList(std::vector<std::string> &rl) {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
rl.clear();
if (RunQuery(query, MakeAnyLenString(&query,
"SELECT name FROM launcher" )
, errbuf, &result))
{
while ((row = mysql_fetch_row(result))) {
rl.push_back(row[0]);
}
mysql_free_result(result);
}
else {
LogFile->write(EQEMuLog::Error, "WorldDatabase::GetLauncherList: %s", errbuf);
}
safe_delete_array(query);
}
void WorldDatabase::SetMailKey(int CharID, int IPAddress, int MailKey) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
char MailKeyString[17];
if(RuleB(Chat, EnableMailKeyIPVerification) == true)
sprintf(MailKeyString, "%08X%08X", IPAddress, MailKey);
else
sprintf(MailKeyString, "%08X", MailKey);
if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET mailkey = '%s' WHERE id='%i'",
MailKeyString, CharID), errbuf))
LogFile->write(EQEMuLog::Error, "WorldDatabase::SetMailKey(%i, %s) : %s", CharID, MailKeyString, errbuf);
safe_delete_array(query);
}
bool WorldDatabase::GetCharacterLevel(const char *name, int &level)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if(RunQuery(query, MakeAnyLenString(&query, "SELECT level FROM character_ WHERE name='%s'", name), errbuf, &result))
{
if(row = mysql_fetch_row(result))
{
level = atoi(row[0]);
mysql_free_result(result);
safe_delete_array(query);
return true;
}
mysql_free_result(result);
}
else
{
LogFile->write(EQEMuLog::Error, "WorldDatabase::GetCharacterLevel: %s", errbuf);
}
safe_delete_array(query);
return false;
}
bool WorldDatabase::LoadCharacterCreateAllocations() {
character_create_allocations.clear();
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if(RunQuery(query, MakeAnyLenString(&query, "SELECT * FROM char_create_point_allocations order by id"), errbuf, &result)) {
safe_delete_array(query);
while(row = mysql_fetch_row(result)) {
RaceClassAllocation allocate;
int r = 0;
allocate.Index = atoi(row[r++]);
allocate.BaseStats[0] = atoi(row[r++]);
allocate.BaseStats[3] = atoi(row[r++]);
allocate.BaseStats[1] = atoi(row[r++]);
allocate.BaseStats[2] = atoi(row[r++]);
allocate.BaseStats[4] = atoi(row[r++]);
allocate.BaseStats[5] = atoi(row[r++]);
allocate.BaseStats[6] = atoi(row[r++]);
allocate.DefaultPointAllocation[0] = atoi(row[r++]);
allocate.DefaultPointAllocation[3] = atoi(row[r++]);
allocate.DefaultPointAllocation[1] = atoi(row[r++]);
allocate.DefaultPointAllocation[2] = atoi(row[r++]);
allocate.DefaultPointAllocation[4] = atoi(row[r++]);
allocate.DefaultPointAllocation[5] = atoi(row[r++]);
allocate.DefaultPointAllocation[6] = atoi(row[r++]);
character_create_allocations.push_back(allocate);
}
mysql_free_result(result);
} else {
safe_delete_array(query);
return false;
}
return true;
}
bool WorldDatabase::LoadCharacterCreateCombos() {
character_create_race_class_combos.clear();
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if(RunQuery(query, MakeAnyLenString(&query, "select * from char_create_combinations order by race, class, deity, start_zone"), errbuf, &result)) {
safe_delete_array(query);
while(row = mysql_fetch_row(result)) {
RaceClassCombos combo;
int r = 0;
combo.AllocationIndex = atoi(row[r++]);
combo.Race = atoi(row[r++]);
combo.Class = atoi(row[r++]);
combo.Deity = atoi(row[r++]);
combo.Zone = atoi(row[r++]);
combo.ExpansionRequired = atoi(row[r++]);
character_create_race_class_combos.push_back(combo);
}
mysql_free_result(result);
} else {
safe_delete_array(query);
return false;
}
return true;
}
+50
View File
@@ -0,0 +1,50 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef WORLDDB_H_
#define WORLDDB_H_
#include "../common/shareddb.h"
#include "../common/ZoneNumbers.h"
struct PlayerProfile_Struct;
struct CharCreate_Struct;
struct CharacterSelect_Struct;
class WorldDatabase : public SharedDatabase {
public:
bool GetStartZone(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_cc);
bool GetStartZoneSoF(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_cc);
void GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct*);
int MoveCharacterToBind(int CharID, uint8 bindnum = 0);
void GetLauncherList(std::vector<std::string> &result);
void SetMailKey(int CharID, int IPAddress, int MailKey);
bool GetCharacterLevel(const char *name, int &level);
bool LoadCharacterCreateAllocations();
bool LoadCharacterCreateCombos();
protected:
};
extern WorldDatabase database;
#endif /*WORLDDB_H_*/
+730
View File
@@ -0,0 +1,730 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2005 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/debug.h"
#include "zonelist.h"
#include "zoneserver.h"
#include "WorldTCPConnection.h"
#include "worlddb.h"
#include "console.h"
#include "WorldConfig.h"
#include "../common/servertalk.h"
#include "../common/MiscFunctions.h"
extern uint32 numzones;
extern bool holdzones;
extern ConsoleList console_list;
ZSList::ZSList()
{
NextID = 1;
CurGroupID = 1;
LastAllocatedPort=0;
memset(pLockedZones, 0, sizeof(pLockedZones));
}
ZSList::~ZSList() {
}
void ZSList::ShowUpTime(WorldTCPConnection* con, const char* adminname) {
uint32 ms = Timer::GetCurrentTime();
uint32 d = ms / 86400000;
ms -= d * 86400000;
uint32 h = ms / 3600000;
ms -= h * 3600000;
uint32 m = ms / 60000;
ms -= m * 60000;
uint32 s = ms / 1000;
if (d)
con->SendEmoteMessage(adminname, 0, 0, 0, "Worldserver Uptime: %02id %02ih %02im %02is", d, h, m, s);
else if (h)
con->SendEmoteMessage(adminname, 0, 0, 0, "Worldserver Uptime: %02ih %02im %02is", h, m, s);
else
con->SendEmoteMessage(adminname, 0, 0, 0, "Worldserver Uptime: %02im %02is", m, s);
}
void ZSList::Add(ZoneServer* zoneserver) {
list.Insert(zoneserver);
zoneserver->SendGroupIDs(); //send its initial set of group ids
}
void ZSList::KillAll() {
LinkedListIterator<ZoneServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()) {
iterator.GetData()->Disconnect();
iterator.RemoveCurrent();
numzones--;
}
}
void ZSList::Process() {
if(shutdowntimer && shutdowntimer->Check()){
_log(WORLD__ZONELIST, "Shutdown timer has expired. Telling all zones to shut down and exiting. (fake sigint)");
ServerPacket* pack2 = new ServerPacket;
pack2->opcode = ServerOP_ShutdownAll;
pack2->size=0;
SendPacket(pack2);
safe_delete(pack2);
Process();
CatchSignal(2);
}
if(reminder && reminder->Check()){
SendEmoteMessage(0,0,0,15,"<SYSTEMWIDE MESSAGE>:SYSTEM MSG:World coming down, everyone log out now. World will shut down in %i seconds...",shutdowntimer->GetRemainingTime()/1000);
}
LinkedListIterator<ZoneServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()) {
if (!iterator.GetData()->Process()) {
ZoneServer* zs = iterator.GetData();
struct in_addr in;
in.s_addr = zs->GetIP();
_log(WORLD__ZONELIST,"Removing zoneserver #%d at %s:%d",zs->GetID(),zs->GetCAddress(),zs->GetCPort());
zs->LSShutDownUpdate(zs->GetZoneID());
if (holdzones){
_log(WORLD__ZONELIST,"Hold Zones mode is ON - rebooting lost zone");
if(!zs->IsStaticZone())
RebootZone(inet_ntoa(in),zs->GetCPort(),zs->GetCAddress(),zs->GetID());
else
RebootZone(inet_ntoa(in),zs->GetCPort(),zs->GetCAddress(),zs->GetID(),database.GetZoneID(zs->GetZoneName()));
}
iterator.RemoveCurrent();
numzones--;
}
else {
iterator.Advance();
}
}
}
bool ZSList::SendPacket(ServerPacket* pack) {
LinkedListIterator<ZoneServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()) {
iterator.GetData()->SendPacket(pack);
iterator.Advance();
}
return true;
}
bool ZSList::SendPacket(uint32 ZoneID, ServerPacket* pack) {
LinkedListIterator<ZoneServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()) {
if (iterator.GetData()->GetZoneID() == ZoneID) {
ZoneServer* tmp = iterator.GetData();
return(tmp->SendPacket(pack));
}
iterator.Advance();
}
return(false);
}
bool ZSList::SendPacket(uint32 ZoneID, uint16 instanceID, ServerPacket* pack) {
LinkedListIterator<ZoneServer*> iterator(list);
iterator.Reset();
if(instanceID != 0)
{
while(iterator.MoreElements()) {
if(iterator.GetData()->GetInstanceID() == instanceID) {
ZoneServer* tmp = iterator.GetData();
return(tmp->SendPacket(pack));
}
iterator.Advance();
}
}
else
{
while(iterator.MoreElements()) {
if (iterator.GetData()->GetZoneID() == ZoneID
&& iterator.GetData()->GetInstanceID() == 0) {
ZoneServer* tmp = iterator.GetData();
return(tmp->SendPacket(pack));
}
iterator.Advance();
}
}
return(false);
}
ZoneServer* ZSList::FindByName(const char* zonename) {
LinkedListIterator<ZoneServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements())
{
if (strcasecmp(iterator.GetData()->GetZoneName(), zonename) == 0) {
ZoneServer* tmp = iterator.GetData();
return tmp;
}
iterator.Advance();
}
return 0;
}
ZoneServer* ZSList::FindByID(uint32 ZoneID) {
LinkedListIterator<ZoneServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()) {
if (iterator.GetData()->GetID() == ZoneID) {
ZoneServer* tmp = iterator.GetData();
return tmp;
}
iterator.Advance();
}
return 0;
}
ZoneServer* ZSList::FindByZoneID(uint32 ZoneID) {
LinkedListIterator<ZoneServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements())
{
ZoneServer* tmp = iterator.GetData();
if (tmp->GetZoneID() == ZoneID && tmp->GetInstanceID() == 0) {
return tmp;
}
iterator.Advance();
}
return 0;
}
ZoneServer* ZSList::FindByPort(uint16 port) {
LinkedListIterator<ZoneServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements())
{
if (iterator.GetData()->GetCPort() == port) {
ZoneServer* tmp = iterator.GetData();
return tmp;
}
iterator.Advance();
}
return 0;
}
ZoneServer* ZSList::FindByInstanceID(uint32 InstanceID)
{
LinkedListIterator<ZoneServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements())
{
if (iterator.GetData()->GetInstanceID() == InstanceID) {
ZoneServer* tmp = iterator.GetData();
return tmp;
}
iterator.Advance();
}
return 0;
}
bool ZSList::SetLockedZone(uint16 iZoneID, bool iLock) {
for (int i=0; i<MaxLockedZones; i++) {
if (iLock) {
if (pLockedZones[i] == 0) {
pLockedZones[i] = iZoneID;
return true;
}
}
else {
if (pLockedZones[i] == iZoneID) {
pLockedZones[i] = 0;
return true;
}
}
}
return false;
}
bool ZSList::IsZoneLocked(uint16 iZoneID) {
for (int i=0; i<MaxLockedZones; i++) {
if (pLockedZones[i] == iZoneID)
return true;
}
return false;
}
void ZSList::ListLockedZones(const char* to, WorldTCPConnection* connection) {
int x = 0;
for (int i=0; i<MaxLockedZones; i++) {
if (pLockedZones[i]) {
connection->SendEmoteMessageRaw(to, 0, 0, 0, database.GetZoneName(pLockedZones[i], true));
x++;
}
}
connection->SendEmoteMessage(to, 0, 0, 0, "%i zones locked.", x);
}
void ZSList::SendZoneStatus(const char* to, int16 admin, WorldTCPConnection* connection) {
LinkedListIterator<ZoneServer*> iterator(list);
struct in_addr in;
iterator.Reset();
char locked[4];
if (WorldConfig::get()->Locked == true)
strcpy(locked, "Yes");
else
strcpy(locked, "No");
char* output = 0;
uint32 outsize = 0, outlen = 0;
if (connection->IsConsole())
AppendAnyLenString(&output, &outsize, &outlen, "World Locked: %s\r\n", locked);
else
AppendAnyLenString(&output, &outsize, &outlen, "World Locked: %s^", locked);
if (connection->IsConsole())
AppendAnyLenString(&output, &outsize, &outlen, "Zoneservers online:\r\n");
else
AppendAnyLenString(&output, &outsize, &outlen, "Zoneservers online:^");
// connection->SendEmoteMessage(to, 0, 0, 0, "World Locked: %s", locked);
// connection->SendEmoteMessage(to, 0, 0, 0, "Zoneservers online:");
int v=0, w=0, x=0, y=0, z=0;
char tmpStatic[2] = { 0, 0 }, tmpZone[64];
memset(tmpZone, 0, sizeof(tmpZone));
ZoneServer* zs = 0;
while(iterator.MoreElements()) {
zs = iterator.GetData();
in.s_addr = zs->GetIP();
if(zs->IsStaticZone())
z++;
else if (zs->GetZoneID() != 0)
w++;
else if(zs->GetZoneID() == 0 && !zs->IsBootingUp())
v++;
if (zs->IsStaticZone())
tmpStatic[0] = 'S';
else
tmpStatic[0] = ' ';
if (admin >= 150) {
if (zs->GetZoneID())
snprintf(tmpZone, sizeof(tmpZone), "%s (%i)", zs->GetZoneName(), zs->GetZoneID());
else if (zs->IsBootingUp())
strcpy(tmpZone, "...");
else
tmpZone[0] = 0;
AppendAnyLenString(&output, &outsize, &outlen, " #%-3i %s %15s:%-5i %2i %s:%i %s", zs->GetID(), tmpStatic, inet_ntoa(in), zs->GetPort(), zs->NumPlayers(), zs->GetCAddress(), zs->GetCPort(), tmpZone);
if (outlen >= 3584) {
connection->SendEmoteMessageRaw(to, 0, 0, 10, output);
safe_delete(output);
outsize = 0;
outlen = 0;
}
else {
if (connection->IsConsole())
AppendAnyLenString(&output, &outsize, &outlen, "\r\n");
else
AppendAnyLenString(&output, &outsize, &outlen, "^");
}
x++;
}
else if (zs->GetZoneID() != 0) {
if (zs->GetZoneID())
strcpy(tmpZone, zs->GetZoneName());
else
tmpZone[0] = 0;
AppendAnyLenString(&output, &outsize, &outlen, " #%i %s %s", zs->GetID(), tmpStatic, tmpZone);
if (outlen >= 3584) {
connection->SendEmoteMessageRaw(to, 0, 0, 10, output);
safe_delete(output);
outsize = 0;
outlen = 0;
}
else {
if (connection->IsConsole())
AppendAnyLenString(&output, &outsize, &outlen, "\r\n");
else
AppendAnyLenString(&output, &outsize, &outlen, "^");
}
x++;
}
y++;
iterator.Advance();
}
if (connection->IsConsole())
AppendAnyLenString(&output, &outsize, &outlen, "%i servers listed. %i servers online.\r\n", x, y);
else
AppendAnyLenString(&output, &outsize, &outlen, "%i servers listed. %i servers online.^", x, y);
AppendAnyLenString(&output, &outsize, &outlen, "%i zones are static zones, %i zones are booted zones, %i zones available.",z,w,v);
// connection->SendEmoteMessage(to, 0, 0, "%i servers listed. %i servers online.", x, y);
// connection->SendEmoteMessage(to,0,0,"%i zones are static zones, %i zones are booted zones, %i zones available.",z,w,v);
if (output)
connection->SendEmoteMessageRaw(to, 0, 0, 10, output);
safe_delete(output);
}
void ZSList::SendChannelMessage(const char* from, const char* to, uint8 chan_num, uint8 language, const char* message, ...) {
if (!message)
return;
va_list argptr;
char buffer[1024];
va_start(argptr, message);
vsnprintf(buffer, sizeof(buffer), message, argptr);
va_end(argptr);
SendChannelMessageRaw(from, to, chan_num, language, buffer);
}
void ZSList::SendChannelMessageRaw(const char* from, const char* to, uint8 chan_num, uint8 language, const char* message) {
if (!message)
return;
ServerPacket* pack = new ServerPacket;
pack->opcode = ServerOP_ChannelMessage;
pack->size = sizeof(ServerChannelMessage_Struct)+strlen(message)+1;
pack->pBuffer = new uchar[pack->size];
memset(pack->pBuffer, 0, pack->size);
ServerChannelMessage_Struct* scm = (ServerChannelMessage_Struct*) pack->pBuffer;
if (from == 0) {
strcpy(scm->from, "WServer");
scm->noreply = true;
}
else if (from[0] == 0) {
strcpy(scm->from, "WServer");
scm->noreply = true;
}
else
strcpy(scm->from, from);
if (to != 0) {
strcpy((char *) scm->to, to);
strcpy((char *) scm->deliverto, to);
}
else {
scm->to[0] = 0;
scm->deliverto[0] = 0;
}
scm->language = language;
scm->chan_num = chan_num;
strcpy(&scm->message[0], message);
if (scm->chan_num == 5 || scm->chan_num == 6 || scm->chan_num == 11) {
console_list.SendChannelMessage(scm);
}
pack->Deflate();
SendPacket(pack);
delete pack;
}
void ZSList::SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message, ...) {
if (!message)
return;
va_list argptr;
char buffer[1024];
va_start(argptr, message);
vsnprintf(buffer, sizeof(buffer), message, argptr);
va_end(argptr);
SendEmoteMessageRaw(to, to_guilddbid, to_minstatus, type, buffer);
}
void ZSList::SendEmoteMessageRaw(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message) {
if (!message)
return;
ServerPacket* pack = new ServerPacket;
pack->opcode = ServerOP_EmoteMessage;
pack->size = sizeof(ServerEmoteMessage_Struct)+strlen(message)+1;
pack->pBuffer = new uchar[pack->size];
memset(pack->pBuffer, 0, pack->size);
ServerEmoteMessage_Struct* sem = (ServerEmoteMessage_Struct*) pack->pBuffer;
if (to) {
if (to[0] == '*') {
Console* con = console_list.FindByAccountName(&to[1]);
if (con)
con->SendEmoteMessageRaw(to, to_guilddbid, to_minstatus, type, message);
delete pack;
return;
}
strcpy((char *) sem->to, to);
}
else {
sem->to[0] = 0;
}
sem->guilddbid = to_guilddbid;
sem->minstatus = to_minstatus;
sem->type = type;
strcpy(&sem->message[0], message);
char tempto[64]={0};
if(to)
strn0cpy(tempto,to,64);
pack->Deflate();
if (tempto[0] == 0) {
SendPacket(pack);
if (to_guilddbid == 0)
console_list.SendEmoteMessageRaw(type, message);
}
else {
ZoneServer* zs = FindByName(to);
if (zs != 0)
zs->SendPacket(pack);
else
SendPacket(pack);
}
delete pack;
}
void ZSList::SendTimeSync() {
ServerPacket* pack = new ServerPacket(ServerOP_SyncWorldTime, sizeof(eqTimeOfDay));
eqTimeOfDay* tod = (eqTimeOfDay*) pack->pBuffer;
tod->start_eqtime=worldclock.getStartEQTime();
tod->start_realtime=worldclock.getStartRealTime();
SendPacket(pack);
delete pack;
}
void ZSList::NextGroupIDs(uint32 &start, uint32 &end) {
start = CurGroupID;
CurGroupID += 1000; //hand them out 1000 at a time...
if(CurGroupID < start) { //handle overflow
start = 1;
CurGroupID = 1001;
}
end = CurGroupID - 1;
}
void ZSList::SOPZoneBootup(const char* adminname, uint32 ZoneServerID, const char* zonename, bool iMakeStatic) {
ZoneServer* zs = 0;
ZoneServer* zs2 = 0;
uint32 zoneid;
if (!(zoneid = database.GetZoneID(zonename)))
SendEmoteMessage(adminname, 0, 0, 0, "Error: SOP_ZoneBootup: zone '%s' not found in 'zone' table. Typo protection=ON.", zonename);
else {
if (ZoneServerID != 0)
zs = FindByID(ZoneServerID);
else
SendEmoteMessage(adminname, 0, 0, 0, "Error: SOP_ZoneBootup: ServerID must be specified");
if (zs == 0)
SendEmoteMessage(adminname, 0, 0, 0, "Error: SOP_ZoneBootup: zoneserver not found");
else {
zs2 = FindByName(zonename);
if (zs2 != 0)
SendEmoteMessage(adminname, 0, 0, 0, "Error: SOP_ZoneBootup: zone '%s' already being hosted by ZoneServer #%i", zonename, zs2->GetID());
else {
zs->TriggerBootup(zoneid, 0, adminname, iMakeStatic);
}
}
}
}
void ZSList::RebootZone(const char* ip1,uint16 port,const char* ip2, uint32 skipid, uint32 zoneid){
// get random zone
LinkedListIterator<ZoneServer*> iterator(list);
uint32 x = 0;
iterator.Reset();
while(iterator.MoreElements()) {
x++;
iterator.Advance();
}
if (x == 0)
return;
ZoneServer** tmp = new ZoneServer*[x];
uint32 y = 0;
iterator.Reset();
while(iterator.MoreElements()) {
if (!strcmp(iterator.GetData()->GetCAddress(),ip2) && !iterator.GetData()->IsBootingUp() && iterator.GetData()->GetID() != skipid) {
tmp[y++] = iterator.GetData();
}
iterator.Advance();
}
if (y == 0) {
safe_delete(tmp);
return;
}
uint32 z = MakeRandomInt(0, y-1);
ServerPacket* pack = new ServerPacket(ServerOP_ZoneReboot, sizeof(ServerZoneReboot_Struct));
ServerZoneReboot_Struct* s = (ServerZoneReboot_Struct*) pack->pBuffer;
// strcpy(s->ip1,ip1);
strcpy(s->ip2,ip2);
s->port = port;
s->zoneid = zoneid;
if(zoneid != 0)
_log(WORLD__ZONELIST,"Rebooting static zone with the ID of: %i",zoneid);
tmp[z]->SendPacket(pack);
delete pack;
safe_delete_array(tmp);
}
uint16 ZSList::GetAvailableZonePort()
{
const WorldConfig *Config=WorldConfig::get();
int i;
uint16 port=0;
if (LastAllocatedPort==0)
i=Config->ZonePortLow;
else
i=LastAllocatedPort+1;
while(i!=LastAllocatedPort && port==0) {
if (i>Config->ZonePortHigh)
i=Config->ZonePortLow;
if (!FindByPort(i)) {
port=i;
break;
}
i++;
}
LastAllocatedPort=port;
return port;
}
uint32 ZSList::TriggerBootup(uint32 iZoneID, uint32 iInstanceID) {
if(iInstanceID > 0)
{
LinkedListIterator<ZoneServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()) {
if(iterator.GetData()->GetInstanceID() == iInstanceID)
{
return iterator.GetData()->GetID();
}
iterator.Advance();
}
iterator.Reset();
while(iterator.MoreElements()) {
if (iterator.GetData()->GetZoneID() == 0 && !iterator.GetData()->IsBootingUp()) {
ZoneServer* zone=iterator.GetData();
zone->TriggerBootup(iZoneID, iInstanceID);
return zone->GetID();
}
iterator.Advance();
}
return 0;
}
else
{
LinkedListIterator<ZoneServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()) {
if(iterator.GetData()->GetZoneID() == iZoneID && iterator.GetData()->GetInstanceID() == 0)
{
return iterator.GetData()->GetID();
}
iterator.Advance();
}
iterator.Reset();
while(iterator.MoreElements()) {
if (iterator.GetData()->GetZoneID() == 0 && !iterator.GetData()->IsBootingUp()) {
ZoneServer* zone=iterator.GetData();
zone->TriggerBootup(iZoneID);
return zone->GetID();
}
iterator.Advance();
}
return 0;
}
/*Old Random boot zones use this if your server is distributed across computers.
LinkedListIterator<ZoneServer*> iterator(list);
srand(time(NULL));
uint32 x = 0;
iterator.Reset();
while(iterator.MoreElements()) {
x++;
iterator.Advance();
}
if (x == 0) {
return 0;
}
ZoneServer** tmp = new ZoneServer*[x];
uint32 y = 0;
iterator.Reset();
while(iterator.MoreElements()) {
if (iterator.GetData()->GetZoneID() == 0 && !iterator.GetData()->IsBootingUp()) {
tmp[y++] = iterator.GetData();
}
iterator.Advance();
}
if (y == 0) {
safe_delete(tmp);
return 0;
}
uint32 z = rand() % y;
tmp[z]->TriggerBootup(iZoneID);
uint32 ret = tmp[z]->GetID();
safe_delete(tmp);
return ret;
*/
}
void ZSList::SendLSZones(){
LinkedListIterator<ZoneServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()) {
ZoneServer* zs = iterator.GetData();
zs->LSBootUpdate(zs->GetZoneID(),true);
iterator.Advance();
}
}
int ZSList::GetZoneCount() {
return(numzones);
}
void ZSList::GetZoneIDList(vector<uint32> &zones) {
LinkedListIterator<ZoneServer*> iterator(list);
iterator.Reset();
while(iterator.MoreElements()) {
ZoneServer* zs = iterator.GetData();
zones.push_back(zs->GetID());
iterator.Advance();
}
}
+82
View File
@@ -0,0 +1,82 @@
#ifndef ZONELIST_H_
#define ZONELIST_H_
#include "../common/types.h"
#include "../common/eqtime.h"
#include "../common/timer.h"
#include "../common/linked_list.h"
#include <vector>
class WorldTCPConnection;
class ServerPacket;
class ZoneServer;
class ZSList
{
public:
enum { MaxLockedZones = 10 };
static void ShowUpTime(WorldTCPConnection* con, const char* adminname = 0);
ZSList();
~ZSList();
ZoneServer* FindByName(const char* zonename);
ZoneServer* FindByID(uint32 ZoneID);
ZoneServer* FindByZoneID(uint32 ZoneID);
ZoneServer* FindByPort(uint16 port);
ZoneServer* FindByInstanceID(uint32 InstanceID);
void SendChannelMessage(const char* from, const char* to, uint8 chan_num, uint8 language, const char* message, ...);
void SendChannelMessageRaw(const char* from, const char* to, uint8 chan_num, uint8 language, const char* message);
void SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message, ...);
void SendEmoteMessageRaw(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message);
void SendZoneStatus(const char* to, int16 admin, WorldTCPConnection* connection);
void SendTimeSync();
void Add(ZoneServer* zoneserver);
void Process();
void KillAll();
bool SendPacket(ServerPacket* pack);
bool SendPacket(uint32 zoneid, ServerPacket* pack);
bool SendPacket(uint32 zoneid, uint16 instanceid, ServerPacket* pack);
inline uint32 GetNextID() { return NextID++; }
void RebootZone(const char* ip1,uint16 port, const char* ip2, uint32 skipid, uint32 zoneid = 0);
uint32 TriggerBootup(uint32 iZoneID, uint32 iInstanceID = 0);
void SOPZoneBootup(const char* adminname, uint32 ZoneServerID, const char* zonename, bool iMakeStatic = false);
EQTime worldclock;
bool SetLockedZone(uint16 iZoneID, bool iLock);
bool IsZoneLocked(uint16 iZoneID);
void ListLockedZones(const char* to, WorldTCPConnection* connection);
Timer* shutdowntimer;
Timer* reminder;
void NextGroupIDs(uint32 &start, uint32 &end);
void SendLSZones();
uint16 GetAvailableZonePort();
int GetZoneCount();
void GetZoneIDList(std::vector<uint32> &zones);
protected:
uint32 NextID;
LinkedList<ZoneServer*> list;
uint16 pLockedZones[MaxLockedZones];
uint32 CurGroupID;
uint16 LastAllocatedPort;
};
#endif /*ZONELIST_H_*/
+1431
View File
File diff suppressed because it is too large Load Diff
+93
View File
@@ -0,0 +1,93 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef ZONESERVER_H
#define ZONESERVER_H
#include "WorldTCPConnection.h"
#include "../common/EmuTCPConnection.h"
#include <string.h>
#include <string>
class Client;
class ServerPacket;
class ZoneServer : public WorldTCPConnection {
public:
ZoneServer(EmuTCPConnection* itcpc);
~ZoneServer();
virtual inline bool IsZoneServer() { return true; }
bool Process();
bool SendPacket(ServerPacket* pack) { return tcpc->SendPacket(pack); }
void SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message, ...);
void SendEmoteMessageRaw(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message);
bool SetZone(uint32 iZoneID, uint32 iInstanceID = 0, bool iStaticZone = false);
void TriggerBootup(uint32 iZoneID = 0, uint32 iInstanceID = 0, const char* iAdminName = 0, bool iMakeStatic = false);
void Disconnect() { tcpc->Disconnect(); }
void IncommingClient(Client* client);
void LSBootUpdate(uint32 zoneid, uint32 iInstanceID = 0, bool startup = false);
void LSSleepUpdate(uint32 zoneid);
void LSShutDownUpdate(uint32 zoneid);
uint32 GetPrevZoneID() { return oldZoneID; }
void ChangeWID(uint32 iCharID, uint32 iWID);
void SendGroupIDs();
inline const char* GetZoneName() const { return zone_name; }
inline const char* GetZoneLongName() const { return long_name; }
const char* GetCompileTime() const{ return compiled; }
void SetCompile(char* in_compile){ strcpy(compiled,in_compile); }
inline uint32 GetZoneID() const { return zoneID; }
inline uint32 GetIP() const { return tcpc->GetrIP(); }
inline uint16 GetPort() const { return tcpc->GetrPort(); }
inline const char* GetCAddress() const { return clientaddress; }
inline uint16 GetCPort() const { return clientport; }
inline uint32 GetID() const { return ID; }
inline bool IsBootingUp() const { return BootingUp; }
inline bool IsStaticZone() const{ return staticzone; }
inline uint32 NumPlayers() const { return pNumPlayers; }
inline void AddPlayer() { pNumPlayers++; }
inline void RemovePlayer() { pNumPlayers--; }
inline const char * GetLaunchName() const { return(launcher_name.c_str()); }
inline const char * GetLaunchedName() const { return(launched_name.c_str()); }
inline uint32 GetInstanceID() { return instanceID; }
inline void SetInstanceID(uint32 i) { instanceID = i; }
private:
EmuTCPConnection* const tcpc;
uint32 ID;
char clientaddress[250];
uint16 clientport;
bool BootingUp;
bool staticzone;
bool authenticated;
uint32 pNumPlayers;
char compiled[25];
char zone_name[32];
char long_name[256];
uint32 zoneID;
uint32 oldZoneID;
Timer ls_zboot;
uint32 instanceID; //instance ids contain a zone id, and a zone version
std::string launcher_name; //the launcher which started us
std::string launched_name; //the name of the zone we launched.
};
#endif