Compare commits

..

2 Commits

Author SHA1 Message Date
Kayne Ruse a5757748cf That didn't go as well as I'd hoped 2015-01-21 04:20:31 +11:00
Kayne Ruse f4e4728ce3 Partial solution for collision problems 2015-01-21 03:06:35 +11:00
49 changed files with 879 additions and 1233 deletions
+1 -1
View File
@@ -127,7 +127,7 @@ void BaseScene::HandleEvents() {
break; break;
#ifdef USE_EVENT_JOYSTICK #ifdef USE_EVENT_JOYSTICK
//EMPTY //TODO: joystick/gamepad support
#endif #endif
#ifdef USE_EVENT_UNKNOWN #ifdef USE_EVENT_UNKNOWN
+1 -1
View File
@@ -59,7 +59,7 @@ protected:
virtual void KeyUp(SDL_KeyboardEvent const&) {} virtual void KeyUp(SDL_KeyboardEvent const&) {}
#ifdef USE_EVENT_JOYSTICK #ifdef USE_EVENT_JOYSTICK
//EMPTY //TODO: joystick/gamepad support
#endif #endif
#ifdef USE_EVENT_UNKNOWN #ifdef USE_EVENT_UNKNOWN
+4 -3
View File
@@ -37,7 +37,7 @@
#include "main_menu.hpp" #include "main_menu.hpp"
#include "options_menu.hpp" #include "options_menu.hpp"
#include "lobby_menu.hpp" #include "lobby_menu.hpp"
#include "world.hpp" #include "in_world.hpp"
#include "disconnected_screen.hpp" #include "disconnected_screen.hpp"
//------------------------- //-------------------------
@@ -83,6 +83,7 @@ void ClientApplication::Init(int argc, char* argv[]) {
//debug output //debug output
//------------------------- //-------------------------
//TODO: enable/disable these with a switch
#define DEBUG_OUTPUT_VAR(x) std::cout << "\t" << #x << ": " << x << std::endl; #define DEBUG_OUTPUT_VAR(x) std::cout << "\t" << #x << ": " << x << std::endl;
std::cout << "Internal sizes:" << std::endl; std::cout << "Internal sizes:" << std::endl;
@@ -185,8 +186,8 @@ void ClientApplication::LoadScene(SceneList sceneIndex) {
case SceneList::LOBBYMENU: case SceneList::LOBBYMENU:
activeScene = new LobbyMenu(&clientIndex, &accountIndex); activeScene = new LobbyMenu(&clientIndex, &accountIndex);
break; break;
case SceneList::WORLD: case SceneList::INWORLD:
activeScene = new World(&clientIndex, &accountIndex); activeScene = new InWorld(&clientIndex, &accountIndex);
break; break;
case SceneList::DISCONNECTEDSCREEN: case SceneList::DISCONNECTEDSCREEN:
activeScene = new DisconnectedScreen(); activeScene = new DisconnectedScreen();
-23
View File
@@ -21,26 +21,3 @@
*/ */
#include "base_monster.hpp" #include "base_monster.hpp"
#include "config_utility.hpp"
void BaseMonster::CorrectSprite() {
//TODO: (9) empty
}
std::string BaseMonster::SetHandle(std::string s) {
return handle = s;
}
std::string BaseMonster::GetHandle() const {
return handle;
}
std::string BaseMonster::SetAvatar(std::string s) {
avatar = s;
sprite.LoadSurface(ConfigUtility::GetSingleton()["dir.sprites"] + avatar, 4, 1);
return avatar;
}
std::string BaseMonster::GetAvatar() const {
return avatar;
}
+1 -10
View File
@@ -29,17 +29,8 @@ public:
BaseMonster() = default; BaseMonster() = default;
virtual ~BaseMonster() = default; virtual ~BaseMonster() = default;
void CorrectSprite();
std::string SetHandle(std::string s);
std::string GetHandle() const;
std::string SetAvatar(std::string s);
std::string GetAvatar() const;
protected: protected:
//metadata //
std::string handle;
std::string avatar;
}; };
#endif #endif
+49 -8
View File
@@ -23,13 +23,54 @@
#include <iostream> #include <iostream>
bool LocalCharacter::ProcessCollisionGrid(std::list<BoundingBox> boxList) { bool LocalCharacter::ProcessCollisionGrid(std::list<BoundingBox> boxList, Uint8* keyState) {
for(auto& box : boxList) { //skip this if there's no movement
if (box.CheckOverlap(origin + bounds)) { if (motion == 0) {
origin -= motion;
motion = {0, 0};
return true;
}
}
return false; return false;
} }
//determine the simple movement based on input
Vector2 newMotion = {0, 0};
if (keyState[SDLK_w]) {
newMotion.y -= CHARACTER_WALKING_SPEED;
}
if (keyState[SDLK_a]) {
newMotion.x -= CHARACTER_WALKING_SPEED;
}
if (keyState[SDLK_s]) {
newMotion.y += CHARACTER_WALKING_SPEED;
}
if (keyState[SDLK_d]) {
newMotion.x += CHARACTER_WALKING_SPEED;
}
bool ret = false;
for(auto& box : boxList) {
if (box.CheckCollision(origin + bounds)) {
//push the character to the closest non-contact position
Vector2 shift = box.CalcShift(origin + bounds);
origin += shift;
//set any motion in that direction to zero
if (shift.x != 0) {
newMotion.x = 0;
}
if (shift.y != 0) {
newMotion.y = 0;
}
ret = true;
}
}
//handle diagonals
if (newMotion.x != 0 && newMotion.y != 0) {
newMotion *= CHARACTER_WALKING_MOD;
}
//set the new motion
motion = newMotion;
//signal for updates
return ret;
}
+1 -1
View File
@@ -33,7 +33,7 @@ public:
LocalCharacter() = default; LocalCharacter() = default;
virtual ~LocalCharacter() = default; virtual ~LocalCharacter() = default;
bool ProcessCollisionGrid(std::list<BoundingBox>); bool ProcessCollisionGrid(std::list<BoundingBox>, Uint8* keyState);
private: private:
//NOTE: NO MEMBERS //NOTE: NO MEMBERS
@@ -49,11 +49,11 @@
#include <chrono> #include <chrono>
class World: public BaseScene { class InWorld : public BaseScene {
public: public:
//Public access members //Public access members
World(int* const argClientIndex, int* const argAccountIndex); InWorld(int* const argClientIndex, int* const argAccountIndex);
~World(); ~InWorld();
protected: protected:
//Frame loop //Frame loop
@@ -71,56 +71,43 @@ protected:
void KeyDown(SDL_KeyboardEvent const&); void KeyDown(SDL_KeyboardEvent const&);
void KeyUp(SDL_KeyboardEvent const&); void KeyUp(SDL_KeyboardEvent const&);
//handle incoming traffic //Basic connections
void HandlePacket(SerialPacket* const); void HandlePacket(SerialPacket* const);
void HandlePing(ServerPacket* const);
void HandlePong(ServerPacket* const);
//heartbeat system //Connection control
void hPing(ServerPacket* const); void SendLogoutRequest();
void hPong(ServerPacket* const); void SendDisconnectRequest();
void SendShutdownRequest();
void HandleLogoutResponse(ClientPacket* const);
void HandleDisconnectResponse(ClientPacket* const);
void HandleDisconnectForced(ClientPacket* const);
void CheckHeartBeat(); void CheckHeartBeat();
//basic connections
void SendLogoutRequest();
void SendDisconnectRequest();
void SendAdminDisconnectForced();
void SendAdminShutdownRequest();
void hLogoutResponse(ClientPacket* const);
void hDisconnectResponse(ClientPacket* const);
void hAdminDisconnectForced(ClientPacket* const);
//map management //map management
void SendRegionRequest(int roomIndex, int x, int y); void SendRegionRequest(int roomIndex, int x, int y);
void hRegionContent(RegionPacket* const); void HandleRegionContent(RegionPacket* const);
void UpdateMap(); void UpdateMap();
//character management //character management
void hCharacterCreate(CharacterPacket* const); void HandleCharacterCreate(CharacterPacket* const);
void hCharacterDelete(CharacterPacket* const); void HandleCharacterDelete(CharacterPacket* const);
void hQueryCharacterExists(CharacterPacket* const); void HandleCharacterQueryExists(CharacterPacket* const);
void hQueryCharacterStats(CharacterPacket* const); void HandleCharacterMovement(CharacterPacket* const);
void hQueryCharacterLocation(CharacterPacket* const); void HandleCharacterAttack(CharacterPacket* const);
void hCharacterMovement(CharacterPacket* const);
void hCharacterAttack(CharacterPacket* const);
void hCharacterDamage(CharacterPacket* const);
//monster management //monster management
void hMonsterCreate(MonsterPacket* const); void HandleMonsterCreate(MonsterPacket* const);
void hMonsterDelete(MonsterPacket* const); void HandleMonsterDelete(MonsterPacket* const);
void hQueryMonsterExists(MonsterPacket* const); void HandleMonsterQueryExists(MonsterPacket* const);
void hQueryMonsterStats(MonsterPacket* const); void HandleMonsterMovement(MonsterPacket* const);
void hQueryMonsterLocation(MonsterPacket* const); void HandleMonsterAttack(MonsterPacket* const);
void hMonsterMovement(MonsterPacket* const);
void hMonsterAttack(MonsterPacket* const);
void hMonsterDamage(MonsterPacket* const);
//chat //player movement
void hTextBroadcast(TextPacket* const); void ProcessLocalCharacterMovement();
void hTextSpeech(TextPacket* const);
void hTextWhisper(TextPacket* const);
//general gameplay
void SendLocalCharacterMovement(); void SendLocalCharacterMovement();
std::list<BoundingBox> GenerateCollisionGrid(Entity*, int tileWidth, int tileHeight); std::list<BoundingBox> GenerateCollisionGrid(Entity*, int tileWidth, int tileHeight);
@@ -156,7 +143,7 @@ protected:
LocalCharacter* localCharacter = nullptr; LocalCharacter* localCharacter = nullptr;
//heartbeat //heartbeat
//TODO: (2) Heartbeat needs it's own utility //TODO: Heartbeat needs it's own utility
typedef std::chrono::steady_clock Clock; typedef std::chrono::steady_clock Clock;
Clock::time_point lastBeat = Clock::now(); Clock::time_point lastBeat = Clock::now();
int attemptedBeats = 0; int attemptedBeats = 0;
@@ -164,6 +151,7 @@ protected:
//ugly references; I hate this //ugly references; I hate this
ConfigUtility& config = ConfigUtility::GetSingleton(); ConfigUtility& config = ConfigUtility::GetSingleton();
UDPNetworkUtility& network = UDPNetworkUtility::GetSingleton(); UDPNetworkUtility& network = UDPNetworkUtility::GetSingleton();
Uint8* keyState = nullptr;
}; };
#endif #endif
@@ -19,7 +19,7 @@
* 3. This notice may not be removed or altered from any source * 3. This notice may not be removed or altered from any source
* distribution. * distribution.
*/ */
#include "world.hpp" #include "in_world.hpp"
#include "channels.hpp" #include "channels.hpp"
@@ -35,7 +35,7 @@
//DOCS: new characters will result in create messages //DOCS: new characters will result in create messages
//DOCS: this client's character will exist in both (skipped) //DOCS: this client's character will exist in both (skipped)
void World::hCharacterCreate(CharacterPacket* const argPacket) { void InWorld::HandleCharacterCreate(CharacterPacket* const argPacket) {
//prevent double message //prevent double message
if (characterMap.find(argPacket->characterIndex) != characterMap.end()) { if (characterMap.find(argPacket->characterIndex) != characterMap.end()) {
std::ostringstream msg; std::ostringstream msg;
@@ -51,7 +51,7 @@ void World::hCharacterCreate(CharacterPacket* const argPacket) {
//fill the character's info //fill the character's info
character->SetOrigin(argPacket->origin); character->SetOrigin(argPacket->origin);
character->SetMotion(argPacket->motion); character->SetMotion(argPacket->motion);
character->SetBounds({CHARACTER_BOUNDS_X, CHARACTER_BOUNDS_Y, CHARACTER_BOUNDS_WIDTH, CHARACTER_BOUNDS_HEIGHT}); //TODO: (1) send the bounds from the server character->SetBounds({CHARACTER_BOUNDS_X, CHARACTER_BOUNDS_Y, CHARACTER_BOUNDS_WIDTH, CHARACTER_BOUNDS_HEIGHT});
character->SetHandle(argPacket->handle); character->SetHandle(argPacket->handle);
character->SetAvatar(argPacket->avatar); character->SetAvatar(argPacket->avatar);
character->SetOwner(argPacket->accountIndex); character->SetOwner(argPacket->accountIndex);
@@ -71,10 +71,10 @@ void World::hCharacterCreate(CharacterPacket* const argPacket) {
} }
//debug //debug
std::cout << "Character Create, total: " << characterMap.size() << std::endl; std::cout << "Create, total: " << characterMap.size() << std::endl;
} }
void World::hCharacterDelete(CharacterPacket* const argPacket) { void InWorld::HandleCharacterDelete(CharacterPacket* const argPacket) {
//ignore if this character doesn't exist //ignore if this character doesn't exist
std::map<int, BaseCharacter>::iterator characterIt = characterMap.find(argPacket->characterIndex); std::map<int, BaseCharacter>::iterator characterIt = characterMap.find(argPacket->characterIndex);
if (characterIt == characterMap.end()) { if (characterIt == characterMap.end()) {
@@ -97,10 +97,10 @@ void World::hCharacterDelete(CharacterPacket* const argPacket) {
characterMap.erase(characterIt); characterMap.erase(characterIt);
//debug //debug
std::cout << "Character Delete, total: " << characterMap.size() << std::endl; std::cout << "Delete, total: " << characterMap.size() << std::endl;
} }
void World::hQueryCharacterExists(CharacterPacket* const argPacket) { void InWorld::HandleCharacterQueryExists(CharacterPacket* const argPacket) {
//prevent a double message about this player's character //prevent a double message about this player's character
if (argPacket->accountIndex == accountIndex) { if (argPacket->accountIndex == accountIndex) {
return; return;
@@ -124,19 +124,11 @@ void World::hQueryCharacterExists(CharacterPacket* const argPacket) {
character->CorrectSprite(); character->CorrectSprite();
//debug //debug
std::cout << "Character Query, total: " << characterMap.size() << std::endl; std::cout << "Query, total: " << characterMap.size() << std::endl;
} }
void World::hQueryCharacterStats(CharacterPacket* const argPacket) { void InWorld::HandleCharacterMovement(CharacterPacket* const argPacket) {
//TODO: (9) empty //TODO: Authentication
}
void World::hQueryCharacterLocation(CharacterPacket* const argPacket) {
//TODO: (9) empty
}
void World::hCharacterMovement(CharacterPacket* const argPacket) {
//TODO: (1) Authentication
if (argPacket->characterIndex == characterIndex) { if (argPacket->characterIndex == characterIndex) {
return; return;
} }
@@ -151,19 +143,72 @@ void World::hCharacterMovement(CharacterPacket* const argPacket) {
} }
} }
void World::hCharacterAttack(CharacterPacket* const argPacket) { void InWorld::HandleCharacterAttack(CharacterPacket* const argPacket) {
//TODO: (9) empty //TODO: attack animation
}
void World::hCharacterDamage(CharacterPacket* const argPacket) {
//TODO: (9) empty
} }
//------------------------- //-------------------------
//player movement & collision //monster management
//------------------------- //-------------------------
void World::SendLocalCharacterMovement() { void InWorld::HandleMonsterCreate(MonsterPacket* const argPacket) {
//TODO
}
void InWorld::HandleMonsterDelete(MonsterPacket* const argPacket) {
//TODO
}
void InWorld::HandleMonsterQueryExists(MonsterPacket* const argPacket) {
//TODO
}
void InWorld::HandleMonsterMovement(MonsterPacket* const argPacket) {
//TODO
}
void InWorld::HandleMonsterAttack(MonsterPacket* const argPacket) {
//TODO
}
//-------------------------
//player movement
//-------------------------
void InWorld::ProcessLocalCharacterMovement() {
//character movement
if (!localCharacter) {
return;
}
Vector2 newMotion = {0, 0};
if (keyState[SDLK_w]) {
newMotion.y -= CHARACTER_WALKING_SPEED;
}
if (keyState[SDLK_a]) {
newMotion.x -= CHARACTER_WALKING_SPEED;
}
if (keyState[SDLK_s]) {
newMotion.y += CHARACTER_WALKING_SPEED;
}
if (keyState[SDLK_d]) {
newMotion.x += CHARACTER_WALKING_SPEED;
}
//handle diagonals
if (newMotion.x != 0 && newMotion.y != 0) {
newMotion *= CHARACTER_WALKING_MOD;
}
//set the info
if (localCharacter->GetMotion() != newMotion) {
localCharacter->SetMotion(newMotion);
localCharacter->CorrectSprite();
SendLocalCharacterMovement();
}
}
void InWorld::SendLocalCharacterMovement() {
CharacterPacket newPacket; CharacterPacket newPacket;
newPacket.type = SerialPacketType::CHARACTER_MOVEMENT; newPacket.type = SerialPacketType::CHARACTER_MOVEMENT;
@@ -176,7 +221,7 @@ void World::SendLocalCharacterMovement() {
network.SendTo(Channels::SERVER, &newPacket); network.SendTo(Channels::SERVER, &newPacket);
} }
std::list<BoundingBox> World::GenerateCollisionGrid(Entity* ptr, int tileWidth, int tileHeight) { std::list<BoundingBox> InWorld::GenerateCollisionGrid(Entity* ptr, int tileWidth, int tileHeight) {
//prepare for collisions //prepare for collisions
BoundingBox wallBounds = {0, 0, tileWidth, tileHeight}; BoundingBox wallBounds = {0, 0, tileWidth, tileHeight};
std::list<BoundingBox> boxList; std::list<BoundingBox> boxList;
@@ -0,0 +1,264 @@
/* Copyright: (c) Kayne Ruse 2013-2015
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "in_world.hpp"
#include "channels.hpp"
#include "ip_operators.hpp"
#include "terminal_error.hpp"
#include <chrono>
#include <sstream>
#include <stdexcept>
//-------------------------
//Basic connections
//-------------------------
void InWorld::HandlePacket(SerialPacket* const argPacket) {
switch(argPacket->type) {
//heartbeat system
case SerialPacketType::PING:
HandlePing(static_cast<ServerPacket*>(argPacket));
break;
case SerialPacketType::PONG:
HandlePong(static_cast<ServerPacket*>(argPacket));
break;
//game server connections
case SerialPacketType::LOGOUT_RESPONSE:
HandleLogoutResponse(static_cast<ClientPacket*>(argPacket));
break;
case SerialPacketType::DISCONNECT_RESPONSE:
HandleDisconnectResponse(static_cast<ClientPacket*>(argPacket));
break;
case SerialPacketType::DISCONNECT_FORCED:
HandleDisconnectForced(static_cast<ClientPacket*>(argPacket));
break;
//map management
case SerialPacketType::REGION_CONTENT:
HandleRegionContent(static_cast<RegionPacket*>(argPacket));
break;
//character management
case SerialPacketType::CHARACTER_CREATE:
HandleCharacterCreate(static_cast<CharacterPacket*>(argPacket));
break;
case SerialPacketType::CHARACTER_DELETE:
HandleCharacterDelete(static_cast<CharacterPacket*>(argPacket));
break;
case SerialPacketType::QUERY_CHARACTER_EXISTS:
HandleCharacterQueryExists(static_cast<CharacterPacket*>(argPacket));
break;
case SerialPacketType::CHARACTER_MOVEMENT:
HandleCharacterMovement(static_cast<CharacterPacket*>(argPacket));
break;
case SerialPacketType::CHARACTER_ATTACK:
HandleCharacterAttack(static_cast<CharacterPacket*>(argPacket));
break;
//monster management
case SerialPacketType::MONSTER_CREATE:
HandleMonsterCreate(static_cast<MonsterPacket*>(argPacket));
break;
case SerialPacketType::MONSTER_DELETE:
HandleMonsterDelete(static_cast<MonsterPacket*>(argPacket));
break;
case SerialPacketType::QUERY_MONSTER_EXISTS:
HandleMonsterQueryExists(static_cast<MonsterPacket*>(argPacket));
break;
case SerialPacketType::MONSTER_MOVEMENT:
HandleMonsterMovement(static_cast<MonsterPacket*>(argPacket));
break;
case SerialPacketType::MONSTER_ATTACK:
HandleMonsterAttack(static_cast<MonsterPacket*>(argPacket));
break;
//rejection messages
case SerialPacketType::REGION_REJECTION:
case SerialPacketType::CHARACTER_REJECTION:
throw(terminal_error(static_cast<TextPacket*>(argPacket)->text));
break;
case SerialPacketType::SHUTDOWN_REJECTION:
throw(std::runtime_error(static_cast<TextPacket*>(argPacket)->text));
break;
//errors
default: {
std::ostringstream msg;
msg << "Unknown SerialPacketType encountered in InWorld: " << static_cast<int>(argPacket->type);
throw(std::runtime_error(msg.str()));
}
break;
}
}
void InWorld::HandlePing(ServerPacket* const argPacket) {
ServerPacket newPacket;
newPacket.type = SerialPacketType::PONG;
network.SendTo(argPacket->srcAddress, &newPacket);
}
void InWorld::HandlePong(ServerPacket* const argPacket) {
if (*network.GetIPAddress(Channels::SERVER) != argPacket->srcAddress) {
throw(std::runtime_error("Heartbeat message received from an unknown source"));
}
attemptedBeats = 0;
lastBeat = Clock::now();
}
//-------------------------
//Connection control
//-------------------------
void InWorld::SendLogoutRequest() {
ClientPacket newPacket;
//send a logout request
newPacket.type = SerialPacketType::LOGOUT_REQUEST;
newPacket.accountIndex = accountIndex;
network.SendTo(Channels::SERVER, &newPacket);
}
void InWorld::SendDisconnectRequest() {
ClientPacket newPacket;
//send a disconnect request
newPacket.type = SerialPacketType::DISCONNECT_REQUEST;
newPacket.clientIndex = clientIndex;
network.SendTo(Channels::SERVER, &newPacket);
}
void InWorld::SendShutdownRequest() {
ClientPacket newPacket;
//send a shutdown request
newPacket.type = SerialPacketType::SHUTDOWN_REQUEST;
newPacket.accountIndex = accountIndex;
network.SendTo(Channels::SERVER, &newPacket);
}
void InWorld::HandleLogoutResponse(ClientPacket* const argPacket) {
if (localCharacter) {
characterMap.erase(characterIndex);
localCharacter = nullptr;
}
accountIndex = -1;
characterIndex = -1;
//reset the camera
camera.marginX = camera.marginY = 0;
//because, why not? I guess...
SendDisconnectRequest();
}
void InWorld::HandleDisconnectResponse(ClientPacket* const argPacket) {
HandleLogoutResponse(argPacket);//shortcut
SetNextScene(SceneList::DISCONNECTEDSCREEN);
ConfigUtility::GetSingleton()["client.disconnectMessage"] = "You have successfully logged out";
}
void InWorld::HandleDisconnectForced(ClientPacket* const argPacket) {
HandleDisconnectResponse(argPacket);//shortcut
SetNextScene(SceneList::DISCONNECTEDSCREEN);
ConfigUtility::GetSingleton()["client.disconnectMessage"] = "You have been forcibly disconnected by the server";
}
void InWorld::CheckHeartBeat() {
//check the connection (heartbeat)
if (Clock::now() - lastBeat > std::chrono::seconds(3)) {
if (attemptedBeats > 2) {
//escape to the disconnect screen
SendDisconnectRequest();
SetNextScene(SceneList::DISCONNECTEDSCREEN);
ConfigUtility::GetSingleton()["client.disconnectMessage"] = "Error: Lost connection to the server";
}
else {
ServerPacket newPacket;
newPacket.type = SerialPacketType::PING;
network.SendTo(Channels::SERVER, &newPacket);
attemptedBeats++;
lastBeat = Clock::now();
}
}
}
//-------------------------
//map management
//-------------------------
void InWorld::SendRegionRequest(int roomIndex, int x, int y) {
RegionPacket packet;
//pack the region's data
packet.type = SerialPacketType::REGION_REQUEST;
packet.roomIndex = roomIndex;
packet.x = x;
packet.y = y;
network.SendTo(Channels::SERVER, &packet);
}
void InWorld::HandleRegionContent(RegionPacket* const argPacket) {
//replace existing regions
regionPager.UnloadIf([&](Region const& region) -> bool {
return region.GetX() == argPacket->x && region.GetY() == argPacket->y;
});
regionPager.PushRegion(argPacket->region);
//clean up after the serial code
delete argPacket->region;
argPacket->region = nullptr;
}
void InWorld::UpdateMap() {
if (roomIndex == -1) {
return;
}
//these represent the zone of regions that the client needs loaded, including the mandatory buffers (+1/-1)
int xStart = snapToBase(REGION_WIDTH, camera.x/tileSheet.GetTileW()) - REGION_WIDTH;
int xEnd = snapToBase(REGION_WIDTH, (camera.x+camera.width)/tileSheet.GetTileW()) + REGION_WIDTH;
int yStart = snapToBase(REGION_HEIGHT, camera.y/tileSheet.GetTileH()) - REGION_HEIGHT;
int yEnd = snapToBase(REGION_HEIGHT, (camera.y+camera.height)/tileSheet.GetTileH()) + REGION_HEIGHT;
//prune distant regions
regionPager.GetContainer()->remove_if([&](Region const& region) -> bool {
return region.GetX() < xStart || region.GetX() > xEnd || region.GetY() < yStart || region.GetY() > yEnd;
});
//request empty regions within this zone
for (int i = xStart; i <= xEnd; i += REGION_WIDTH) {
for (int j = yStart; j <= yEnd; j += REGION_HEIGHT) {
if (!regionPager.FindRegion(i, j)) {
SendRegionRequest(roomIndex, i, j);
}
}
}
}
+253
View File
@@ -0,0 +1,253 @@
/* Copyright: (c) Kayne Ruse 2013-2015
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "in_world.hpp"
#include "channels.hpp"
#include "terminal_error.hpp"
#include <stdexcept>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <sstream>
//-------------------------
//Public access members
//-------------------------
InWorld::InWorld(int* const argClientIndex, int* const argAccountIndex):
clientIndex(*argClientIndex),
accountIndex(*argAccountIndex),
keyState(SDL_GetKeyState(nullptr))
{
//setup the utility objects
buttonImage.LoadSurface(config["dir.interface"] + "button_menu.bmp");
buttonImage.SetClipH(buttonImage.GetClipH()/3);
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
//pass the utility objects
disconnectButton.SetImage(&buttonImage);
disconnectButton.SetFont(&font);
shutDownButton.SetImage(&buttonImage);
shutDownButton.SetFont(&font);
//set the button positions
disconnectButton.SetX(50);
disconnectButton.SetY(50 + buttonImage.GetClipH() * 0);
shutDownButton.SetX(50);
shutDownButton.SetY(50 + buttonImage.GetClipH() * 1);
//set the button texts
disconnectButton.SetText("Disconnect");
shutDownButton.SetText("Shut Down");
//load the tilesheet
//TODO: add the tilesheet to the map system
//TODO: Tile size and tile sheet should be loaded elsewhere
tileSheet.Load(config["dir.tilesets"] + "overworld.bmp", 32, 32);
//Send the character data
//TODO: login scene, prompt, etc.
CharacterPacket newPacket;
newPacket.type = SerialPacketType::CHARACTER_LOAD;
strncpy(newPacket.handle, config["client.handle"].c_str(), PACKET_STRING_SIZE);
strncpy(newPacket.avatar, config["client.avatar"].c_str(), PACKET_STRING_SIZE);
newPacket.accountIndex = accountIndex;
network.SendTo(Channels::SERVER, &newPacket);
//query the world state
memset(&newPacket, 0, MAX_PACKET_SIZE);
newPacket.type = SerialPacketType::QUERY_CHARACTER_EXISTS;
network.SendTo(Channels::SERVER, &newPacket);
//set the camera's values
camera.width = GetScreen()->w;
camera.height = GetScreen()->h;
//debug
//
}
InWorld::~InWorld() {
//unload the local data
characterMap.clear();
monsterMap.clear();
}
//-------------------------
//Frame loop
//-------------------------
void InWorld::FrameStart() {
//
}
void InWorld::Update() {
//create and zero the buffer
SerialPacket* packetBuffer = reinterpret_cast<SerialPacket*>(new char[MAX_PACKET_SIZE]);
memset(packetBuffer, 0, MAX_PACKET_SIZE);
try {
//suck in and process all waiting packets
while(network.Receive(packetBuffer)) {
HandlePacket(packetBuffer);
}
}
catch(terminal_error& e) {
throw(e);
}
catch(std::exception& e) {
std::cerr << "HandlePacket Error: " << e.what() << std::endl;
}
//free the buffer
delete reinterpret_cast<char*>(packetBuffer);
//heartbeat system
CheckHeartBeat();
//update all entities
for (auto& it : characterMap) {
it.second.Update();
}
for (auto& it : monsterMap) {
it.second.Update();
}
//update the map
UpdateMap();
//skip the rest without a local character
if (!localCharacter) {
return;
}
//get the collidable boxes
std::list<BoundingBox> boxList = GenerateCollisionGrid(localCharacter, tileSheet.GetTileW(), tileSheet.GetTileH());
//process the collisions
if (localCharacter->ProcessCollisionGrid(boxList, keyState)) {
localCharacter->CorrectSprite();
SendLocalCharacterMovement();
}
//update the camera
camera.x = localCharacter->GetOrigin().x - camera.marginX;
camera.y = localCharacter->GetOrigin().y - camera.marginY;
}
void InWorld::FrameEnd() {
//
}
void InWorld::RenderFrame() {
SDL_FillRect(GetScreen(), 0, 0);
Render(GetScreen());
SDL_Flip(GetScreen());
fps.Calculate();
}
void InWorld::Render(SDL_Surface* const screen) {
//draw the map
for (std::list<Region>::iterator it = regionPager.GetContainer()->begin(); it != regionPager.GetContainer()->end(); it++) {
tileSheet.DrawRegionTo(screen, &(*it), camera.x, camera.y);
}
//draw the entities
for (auto& it : characterMap) {
//TODO: depth ordering
it.second.DrawTo(screen, camera.x, camera.y);
}
for (auto& it : monsterMap) {
//TODO: depth ordering
it.second.DrawTo(screen, camera.x, camera.y);
}
//draw UI
disconnectButton.DrawTo(screen);
shutDownButton.DrawTo(screen);
std::ostringstream msg;
msg << fps.GetFrameRate();
font.DrawStringTo(msg.str(), screen, 0, 0);
}
//-------------------------
//Event handlers
//-------------------------
void InWorld::QuitEvent() {
//two-step logout
SendDisconnectRequest();
SetNextScene(SceneList::QUIT);
}
void InWorld::MouseMotion(SDL_MouseMotionEvent const& motion) {
disconnectButton.MouseMotion(motion);
shutDownButton.MouseMotion(motion);
}
void InWorld::MouseButtonDown(SDL_MouseButtonEvent const& button) {
disconnectButton.MouseButtonDown(button);
shutDownButton.MouseButtonDown(button);
}
void InWorld::MouseButtonUp(SDL_MouseButtonEvent const& button) {
if (disconnectButton.MouseButtonUp(button) == Button::State::HOVER && button.button == SDL_BUTTON_LEFT) {
SendLogoutRequest();
}
if (shutDownButton.MouseButtonUp(button) == Button::State::HOVER && button.button == SDL_BUTTON_LEFT) {
SendShutdownRequest();
}
}
void InWorld::KeyDown(SDL_KeyboardEvent const& key) {
//hotkeys & player input
switch(key.keysym.sym) {
case SDLK_ESCAPE:
//TODO: the escape key should actually control menus and stuff
SendLogoutRequest();
return;
case SDLK_w:
case SDLK_a:
case SDLK_s:
case SDLK_d:
ProcessLocalCharacterMovement();
break;
default:
//DOCS: prevents wrong keys screwing with character movement
return;
}
}
void InWorld::KeyUp(SDL_KeyboardEvent const& key) {
switch(key.keysym.sym) {
case SDLK_w:
case SDLK_a:
case SDLK_s:
case SDLK_d:
ProcessLocalCharacterMovement();
break;
default:
//DOCS: prevents wrong keys screwing with character movement
return;
}
}
-39
View File
@@ -1,39 +0,0 @@
/* Copyright: (c) Kayne Ruse 2013-2015
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "world.hpp"
//-------------------------
//chat
//-------------------------
void World::hTextBroadcast(TextPacket* const argPacket) {
//TODO: (9) empty
}
void World::hTextSpeech(TextPacket* const argPacket) {
//TODO: (9) empty
}
void World::hTextWhisper(TextPacket* const argPacket) {
//TODO: (9) empty
}
@@ -1,135 +0,0 @@
/* Copyright: (c) Kayne Ruse 2013-2015
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "world.hpp"
#include "channels.hpp"
#include "ip_operators.hpp"
#include <chrono>
#include <sstream>
#include <stdexcept>
//-------------------------
//heartbeat system
//-------------------------
void World::hPing(ServerPacket* const argPacket) {
ServerPacket newPacket;
newPacket.type = SerialPacketType::PONG;
network.SendTo(argPacket->srcAddress, &newPacket);
}
void World::hPong(ServerPacket* const argPacket) {
if (*network.GetIPAddress(Channels::SERVER) != argPacket->srcAddress) {
throw(std::runtime_error("Heartbeat message received from an unknown source"));
}
attemptedBeats = 0;
lastBeat = Clock::now();
}
void World::CheckHeartBeat() {
//check the connection (heartbeat)
if (Clock::now() - lastBeat > std::chrono::seconds(3)) {
if (attemptedBeats > 2) {
//escape to the disconnect screen
SendDisconnectRequest();
SetNextScene(SceneList::DISCONNECTEDSCREEN);
ConfigUtility::GetSingleton()["client.disconnectMessage"] = "Error: Lost connection to the server";
}
else {
ServerPacket newPacket;
newPacket.type = SerialPacketType::PING;
network.SendTo(Channels::SERVER, &newPacket);
attemptedBeats++;
lastBeat = Clock::now();
}
}
}
//-------------------------
//Connection control
//-------------------------
void World::SendLogoutRequest() {
ClientPacket newPacket;
//send a logout request
newPacket.type = SerialPacketType::LOGOUT_REQUEST;
newPacket.accountIndex = accountIndex;
network.SendTo(Channels::SERVER, &newPacket);
}
void World::SendDisconnectRequest() {
ClientPacket newPacket;
//send a disconnect request
newPacket.type = SerialPacketType::DISCONNECT_REQUEST;
newPacket.clientIndex = clientIndex;
network.SendTo(Channels::SERVER, &newPacket);
}
void World::SendAdminDisconnectForced() {
//TODO: (9) empty
}
void World::SendAdminShutdownRequest() {
ClientPacket newPacket;
//send a shutdown request
newPacket.type = SerialPacketType::ADMIN_SHUTDOWN_REQUEST;
newPacket.accountIndex = accountIndex;
network.SendTo(Channels::SERVER, &newPacket);
}
void World::hLogoutResponse(ClientPacket* const argPacket) {
if (localCharacter) {
characterMap.erase(characterIndex);
localCharacter = nullptr;
}
accountIndex = -1;
characterIndex = -1;
//reset the camera
camera.marginX = camera.marginY = 0;
//because, why not? I guess...
SendDisconnectRequest();
}
void World::hDisconnectResponse(ClientPacket* const argPacket) {
hLogoutResponse(argPacket);//shortcut
SetNextScene(SceneList::DISCONNECTEDSCREEN);
ConfigUtility::GetSingleton()["client.disconnectMessage"] = "You have successfully logged out";
}
void World::hAdminDisconnectForced(ClientPacket* const argPacket) {
hDisconnectResponse(argPacket);//shortcut
SetNextScene(SceneList::DISCONNECTEDSCREEN);
ConfigUtility::GetSingleton()["client.disconnectMessage"] = "You have been forcibly disconnected by the server";
}
-418
View File
@@ -1,418 +0,0 @@
/* Copyright: (c) Kayne Ruse 2013-2015
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "world.hpp"
#include "channels.hpp"
#include "terminal_error.hpp"
#include <stdexcept>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <sstream>
//-------------------------
//Public access members
//-------------------------
World::World(int* const argClientIndex, int* const argAccountIndex):
clientIndex(*argClientIndex),
accountIndex(*argAccountIndex)
{
//setup the utility objects
buttonImage.LoadSurface(config["dir.interface"] + "button_menu.bmp");
buttonImage.SetClipH(buttonImage.GetClipH()/3);
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
//pass the utility objects
disconnectButton.SetImage(&buttonImage);
disconnectButton.SetFont(&font);
shutDownButton.SetImage(&buttonImage);
shutDownButton.SetFont(&font);
//set the button positions
disconnectButton.SetX(50);
disconnectButton.SetY(50 + buttonImage.GetClipH() * 0);
shutDownButton.SetX(50);
shutDownButton.SetY(50 + buttonImage.GetClipH() * 1);
//set the button texts
disconnectButton.SetText("Disconnect");
shutDownButton.SetText("Shut Down");
//load the tilesheet
//TODO: (1) Tile size and tile sheet should be loaded elsewhere
tileSheet.Load(config["dir.tilesets"] + "overworld.bmp", 32, 32);
//Send the character data
CharacterPacket newPacket;
newPacket.type = SerialPacketType::CHARACTER_LOAD;
strncpy(newPacket.handle, config["client.handle"].c_str(), PACKET_STRING_SIZE);
strncpy(newPacket.avatar, config["client.avatar"].c_str(), PACKET_STRING_SIZE);
newPacket.accountIndex = accountIndex;
network.SendTo(Channels::SERVER, &newPacket);
//query the world state
memset(&newPacket, 0, MAX_PACKET_SIZE);
newPacket.type = SerialPacketType::QUERY_CHARACTER_EXISTS;
network.SendTo(Channels::SERVER, &newPacket);
newPacket.type = SerialPacketType::QUERY_MONSTER_EXISTS;
network.SendTo(Channels::SERVER, &newPacket);
//set the camera's values
camera.width = GetScreen()->w;
camera.height = GetScreen()->h;
//debug
//
}
World::~World() {
//unload the local data
characterMap.clear();
monsterMap.clear();
}
//-------------------------
//Frame loop
//-------------------------
void World::FrameStart() {
//
}
void World::Update() {
//create and zero the buffer
SerialPacket* packetBuffer = reinterpret_cast<SerialPacket*>(new char[MAX_PACKET_SIZE]);
memset(packetBuffer, 0, MAX_PACKET_SIZE);
try {
//suck in and process all waiting packets
while(network.Receive(packetBuffer)) {
HandlePacket(packetBuffer);
}
}
catch(terminal_error& e) {
throw(e);
}
catch(std::exception& e) {
std::cerr << "HandlePacket Error: " << e.what() << std::endl;
}
//free the buffer
delete reinterpret_cast<char*>(packetBuffer);
//heartbeat system
CheckHeartBeat();
//update all entities
for (auto& it : characterMap) {
it.second.Update();
}
for (auto& it : monsterMap) {
it.second.Update();
}
//update the map
UpdateMap();
//skip the rest without a local character
if (!localCharacter) {
return;
}
//get the collidable boxes
std::list<BoundingBox> boxList = GenerateCollisionGrid(localCharacter, tileSheet.GetTileW(), tileSheet.GetTileH());
//process the collisions
if (localCharacter->ProcessCollisionGrid(boxList)) {
localCharacter->CorrectSprite();
SendLocalCharacterMovement();
}
//update the camera
camera.x = localCharacter->GetOrigin().x - camera.marginX;
camera.y = localCharacter->GetOrigin().y - camera.marginY;
}
void World::FrameEnd() {
//
}
void World::RenderFrame() {
// SDL_FillRect(GetScreen(), 0, 0);
Render(GetScreen());
SDL_Flip(GetScreen());
fps.Calculate();
}
void World::Render(SDL_Surface* const screen) {
//draw the map
for (std::list<Region>::iterator it = regionPager.GetContainer()->begin(); it != regionPager.GetContainer()->end(); it++) {
tileSheet.DrawRegionTo(screen, &(*it), camera.x, camera.y);
}
//draw the entities
for (auto& it : characterMap) {
//TODO: (1) depth ordering
it.second.DrawTo(screen, camera.x, camera.y);
}
for (auto& it : monsterMap) {
it.second.DrawTo(screen, camera.x, camera.y);
}
//draw UI
disconnectButton.DrawTo(screen);
shutDownButton.DrawTo(screen);
std::ostringstream msg;
msg << fps.GetFrameRate();
font.DrawStringTo(msg.str(), screen, 0, 0);
}
//-------------------------
//Event handlers
//-------------------------
void World::QuitEvent() {
//two-step logout
SendDisconnectRequest();
SetNextScene(SceneList::QUIT);
}
void World::MouseMotion(SDL_MouseMotionEvent const& motion) {
disconnectButton.MouseMotion(motion);
shutDownButton.MouseMotion(motion);
}
void World::MouseButtonDown(SDL_MouseButtonEvent const& button) {
disconnectButton.MouseButtonDown(button);
shutDownButton.MouseButtonDown(button);
}
void World::MouseButtonUp(SDL_MouseButtonEvent const& button) {
if (disconnectButton.MouseButtonUp(button) == Button::State::HOVER && button.button == SDL_BUTTON_LEFT) {
SendLogoutRequest();
}
if (shutDownButton.MouseButtonUp(button) == Button::State::HOVER && button.button == SDL_BUTTON_LEFT) {
SendAdminShutdownRequest();
}
}
void World::KeyDown(SDL_KeyboardEvent const& key) {
//hotkeys
switch(key.keysym.sym) {
case SDLK_ESCAPE:
//TODO: (1) the escape key should actually control menus and stuff
SendLogoutRequest();
return;
}
//character movement
if (!localCharacter) {
return;
}
Vector2 motion = localCharacter->GetMotion();
switch(key.keysym.sym) {
case SDLK_w:
motion.y -= CHARACTER_WALKING_SPEED;
break;
case SDLK_a:
motion.x -= CHARACTER_WALKING_SPEED;
break;
case SDLK_s:
motion.y += CHARACTER_WALKING_SPEED;
break;
case SDLK_d:
motion.x += CHARACTER_WALKING_SPEED;
break;
default:
//DOCS: prevents wrong keys screwing with character movement
return;
}
//handle diagonals
if (motion.x != 0 && motion.y != 0) {
motion *= CHARACTER_WALKING_MOD;
}
//set the info
localCharacter->SetMotion(motion);
localCharacter->CorrectSprite();
SendLocalCharacterMovement();
}
void World::KeyUp(SDL_KeyboardEvent const& key) {
//character movement
if (!localCharacter) {
return;
}
Vector2 motion = localCharacter->GetMotion();
switch(key.keysym.sym) {
case SDLK_w:
motion.y = std::min(0.0, motion.y += CHARACTER_WALKING_SPEED);
break;
case SDLK_a:
motion.x = std::min(0.0, motion.x += CHARACTER_WALKING_SPEED);
break;
case SDLK_s:
motion.y = std::max(0.0, motion.y -= CHARACTER_WALKING_SPEED);
break;
case SDLK_d:
motion.x = std::max(0.0, motion.x -= CHARACTER_WALKING_SPEED);
break;
default:
//DOCS: prevents wrong keys screwing with character movement
return;
}
//BUGFIX: reset cardinal direction speed on key release
if (motion.x > 0) {
motion.x = CHARACTER_WALKING_SPEED;
}
else if (motion.x < 0) {
motion.x = -CHARACTER_WALKING_SPEED;
}
if (motion.y > 0) {
motion.y = CHARACTER_WALKING_SPEED;
}
else if (motion.y < 0) {
motion.y = -CHARACTER_WALKING_SPEED;
}
//handle diagonals
if (motion.x != 0 && motion.y != 0) {
motion *= CHARACTER_WALKING_MOD;
}
//set the info
localCharacter->SetMotion(motion);
localCharacter->CorrectSprite();
SendLocalCharacterMovement();
}
//-------------------------
//Direct incoming traffic
//-------------------------
void World::HandlePacket(SerialPacket* const argPacket) {
switch(argPacket->type) {
//heartbeat system
case SerialPacketType::PING:
hPing(static_cast<ServerPacket*>(argPacket));
break;
case SerialPacketType::PONG:
hPong(static_cast<ServerPacket*>(argPacket));
break;
//game server connections
case SerialPacketType::LOGOUT_RESPONSE:
hLogoutResponse(static_cast<ClientPacket*>(argPacket));
break;
case SerialPacketType::DISCONNECT_RESPONSE:
hDisconnectResponse(static_cast<ClientPacket*>(argPacket));
break;
case SerialPacketType::ADMIN_DISCONNECT_FORCED:
hAdminDisconnectForced(static_cast<ClientPacket*>(argPacket));
break;
//map management
case SerialPacketType::REGION_CONTENT:
hRegionContent(static_cast<RegionPacket*>(argPacket));
break;
//character management
case SerialPacketType::CHARACTER_CREATE:
hCharacterCreate(static_cast<CharacterPacket*>(argPacket));
break;
case SerialPacketType::CHARACTER_DELETE:
hCharacterDelete(static_cast<CharacterPacket*>(argPacket));
break;
case SerialPacketType::QUERY_CHARACTER_EXISTS:
hQueryCharacterExists(static_cast<CharacterPacket*>(argPacket));
break;
case SerialPacketType::QUERY_CHARACTER_STATS:
hQueryCharacterStats(static_cast<CharacterPacket*>(argPacket));
break;
case SerialPacketType::QUERY_CHARACTER_LOCATION:
hQueryCharacterLocation(static_cast<CharacterPacket*>(argPacket));
break;
case SerialPacketType::CHARACTER_MOVEMENT:
hCharacterMovement(static_cast<CharacterPacket*>(argPacket));
break;
case SerialPacketType::CHARACTER_ATTACK:
hCharacterAttack(static_cast<CharacterPacket*>(argPacket));
break;
case SerialPacketType::CHARACTER_DAMAGE:
hCharacterDamage(static_cast<CharacterPacket*>(argPacket));
break;
//monster management
case SerialPacketType::MONSTER_CREATE:
hMonsterCreate(static_cast<MonsterPacket*>(argPacket));
break;
case SerialPacketType::MONSTER_DELETE:
hMonsterDelete(static_cast<MonsterPacket*>(argPacket));
break;
case SerialPacketType::QUERY_MONSTER_EXISTS:
hQueryMonsterExists(static_cast<MonsterPacket*>(argPacket));
break;
case SerialPacketType::QUERY_MONSTER_STATS:
hQueryMonsterStats(static_cast<MonsterPacket*>(argPacket));
break;
case SerialPacketType::QUERY_MONSTER_LOCATION:
hQueryMonsterLocation(static_cast<MonsterPacket*>(argPacket));
break;
case SerialPacketType::MONSTER_MOVEMENT:
hMonsterMovement(static_cast<MonsterPacket*>(argPacket));
break;
case SerialPacketType::MONSTER_ATTACK:
hMonsterAttack(static_cast<MonsterPacket*>(argPacket));
break;
case SerialPacketType::MONSTER_DAMAGE:
hMonsterDamage(static_cast<MonsterPacket*>(argPacket));
break;
//chat
case SerialPacketType::TEXT_BROADCAST:
hTextBroadcast(static_cast<TextPacket*>(argPacket));
break;
case SerialPacketType::TEXT_SPEECH:
hTextSpeech(static_cast<TextPacket*>(argPacket));
break;
case SerialPacketType::TEXT_WHISPER:
hTextWhisper(static_cast<TextPacket*>(argPacket));
break;
//general rejection messages
case SerialPacketType::REGION_REJECTION:
case SerialPacketType::CHARACTER_REJECTION:
case SerialPacketType::QUERY_REJECTION:
throw(terminal_error(static_cast<TextPacket*>(argPacket)->text));
break;
case SerialPacketType::SHUTDOWN_REJECTION:
throw(std::runtime_error(static_cast<TextPacket*>(argPacket)->text));
break;
//errors
default: {
std::ostringstream msg;
msg << "Unknown SerialPacketType encountered in World: " << static_cast<int>(argPacket->type);
throw(std::runtime_error(msg.str()));
}
break;
}
}
-79
View File
@@ -1,79 +0,0 @@
/* Copyright: (c) Kayne Ruse 2013-2015
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "world.hpp"
#include "channels.hpp"
//-------------------------
//map management
//-------------------------
void World::SendRegionRequest(int roomIndex, int x, int y) {
RegionPacket packet;
//pack the region's data
packet.type = SerialPacketType::REGION_REQUEST;
packet.roomIndex = roomIndex;
packet.x = x;
packet.y = y;
network.SendTo(Channels::SERVER, &packet);
}
void World::hRegionContent(RegionPacket* const argPacket) {
//replace existing regions
regionPager.UnloadIf([&](Region const& region) -> bool {
return region.GetX() == argPacket->x && region.GetY() == argPacket->y;
});
regionPager.PushRegion(argPacket->region);
//clean up after the serial code
delete argPacket->region;
argPacket->region = nullptr;
}
void World::UpdateMap() {
if (roomIndex == -1) {
return;
}
//these represent the zone of regions that the client needs loaded, including the mandatory buffers (+1/-1)
int xStart = snapToBase(REGION_WIDTH, camera.x/tileSheet.GetTileW()) - REGION_WIDTH;
int xEnd = snapToBase(REGION_WIDTH, (camera.x+camera.width)/tileSheet.GetTileW()) + REGION_WIDTH;
int yStart = snapToBase(REGION_HEIGHT, camera.y/tileSheet.GetTileH()) - REGION_HEIGHT;
int yEnd = snapToBase(REGION_HEIGHT, (camera.y+camera.height)/tileSheet.GetTileH()) + REGION_HEIGHT;
//prune distant regions
regionPager.GetContainer()->remove_if([&](Region const& region) -> bool {
return region.GetX() < xStart || region.GetX() > xEnd || region.GetY() < yStart || region.GetY() > yEnd;
});
//request empty regions within this zone
for (int i = xStart; i <= xEnd; i += REGION_WIDTH) {
for (int j = yStart; j <= yEnd; j += REGION_HEIGHT) {
if (!regionPager.FindRegion(i, j)) {
SendRegionRequest(roomIndex, i, j);
}
}
}
}
-126
View File
@@ -1,126 +0,0 @@
/* Copyright: (c) Kayne Ruse 2013-2015
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "world.hpp"
#include "channels.hpp"
#include <iostream>
#include <sstream>
#include <stdexcept>
//-------------------------
//monster management
//-------------------------
void World::hMonsterCreate(MonsterPacket* const argPacket) {
//check for logic errors
if (monsterMap.find(argPacket->monsterIndex) != monsterMap.end()) {
std::ostringstream msg;
msg << "Double monster creation event; ";
msg << "Index: " << argPacket->monsterIndex << "; ";
msg << "Handle: " << argPacket->handle;
throw(std::runtime_error(msg.str()));
}
//ignore monsters from other rooms
if (roomIndex != argPacket->roomIndex) {
//temporary error checking
std::ostringstream msg;
msg << "Monster from the wrong room received: ";
msg << "monsterIndex: " << argPacket->monsterIndex << ", roomIndex: " << argPacket->roomIndex;
throw(std::runtime_error(msg.str()));
}
//implicitly create the element
BaseMonster* monster = &monsterMap[argPacket->monsterIndex];
//fill the monster's info
monster->SetHandle(argPacket->handle);
monster->SetAvatar(argPacket->avatar);
monster->SetBounds(argPacket->bounds);
monster->SetOrigin(argPacket->origin);
monster->SetMotion(argPacket->motion);
//debug
std::cout << "Monster Create, total: " << monsterMap.size() << std::endl;
}
void World::hMonsterDelete(MonsterPacket* const argPacket) {
//ignore if this monster doesn't exist
std::map<int, BaseMonster>::iterator monsterIt = monsterMap.find(argPacket->monsterIndex);
if (monsterIt == monsterMap.end()) {
return;
}
//remove this monster
monsterMap.erase(monsterIt);
//debug
std::cout << "Monster Delete, total: " << monsterMap.size() << std::endl;
}
void World::hQueryMonsterExists(MonsterPacket* const argPacket) {
//ignore monsters in a different room (sub-optimal)
if (argPacket->roomIndex != roomIndex) {
return;
}
//implicitly create the element
BaseMonster* monster = &monsterMap[argPacket->monsterIndex];
//fill the monster's info
monster->SetHandle(argPacket->handle);
monster->SetAvatar(argPacket->avatar);
monster->SetBounds(argPacket->bounds);
monster->SetOrigin(argPacket->origin);
monster->SetMotion(argPacket->motion);
//debug
std::cout << "Monster Query, total: " << monsterMap.size() << std::endl;
}
void World::hQueryMonsterStats(MonsterPacket* const argPacket) {
//TODO: (9) empty
}
void World::hQueryMonsterLocation(MonsterPacket* const argPacket) {
//TODO: (9) empty
}
void World::hMonsterMovement(MonsterPacket* const argPacket) {
//ignore if this monster doesn't exist
std::map<int, BaseMonster>::iterator monsterIt = monsterMap.find(argPacket->monsterIndex);
if (monsterIt == monsterMap.end()) {
return;
}
monsterIt->second.SetOrigin(argPacket->origin);
monsterIt->second.SetOrigin(argPacket->motion);
}
void World::hMonsterAttack(MonsterPacket* const argPacket) {
//TODO: (9) empty
}
void World::hMonsterDamage(MonsterPacket* const argPacket) {
//TODO: (9) empty
}
+8 -6
View File
@@ -100,14 +100,14 @@ void LobbyMenu::FrameEnd() {
} }
void LobbyMenu::Render(SDL_Surface* const screen) { void LobbyMenu::Render(SDL_Surface* const screen) {
//TODO: (2) I need a proper UI system for the entire client and the editor //TODO: I need a proper UI system for the entire client and the editor
//UI //UI
search.DrawTo(screen); search.DrawTo(screen);
join.DrawTo(screen); join.DrawTo(screen);
back.DrawTo(screen); back.DrawTo(screen);
//TODO: (1) draw headers for the server list //TODO: draw headers for the server list
for (int i = 0; i < serverInfo.size(); i++) { for (int i = 0; i < serverInfo.size(); i++) {
//draw the selected server's highlight //draw the selected server's highlight
if (selection == &serverInfo[i]) { if (selection == &serverInfo[i]) {
@@ -131,6 +131,8 @@ void LobbyMenu::Render(SDL_Surface* const screen) {
if (!serverInfo[i].compatible) { if (!serverInfo[i].compatible) {
font.DrawStringTo("?", screen, listBox.x - font.GetCharW(), listBox.y + i*listBox.h); font.DrawStringTo("?", screen, listBox.x - font.GetCharW(), listBox.y + i*listBox.h);
} }
//TODO: ping/delay?
} }
} }
@@ -164,7 +166,7 @@ void LobbyMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
//has the user selected a server on the list? //has the user selected a server on the list?
BoundingBox tmpBox = listBox; BoundingBox tmpBox = listBox;
tmpBox.h *= serverInfo.size(); tmpBox.h *= serverInfo.size();
if (tmpBox.CheckOverlap({button.x, button.y})) { if (tmpBox.CheckCollision({button.x, button.y, 0, 0})) {
selection = &serverInfo[(button.y - listBox.y)/listBox.h]; selection = &serverInfo[(button.y - listBox.y)/listBox.h];
} }
else { else {
@@ -248,15 +250,15 @@ void LobbyMenu::HandleLoginResponse(ClientPacket* const argPacket) {
throw(std::runtime_error("Client index invalid during login")); throw(std::runtime_error("Client index invalid during login"));
} }
accountIndex = argPacket->accountIndex; accountIndex = argPacket->accountIndex;
SetNextScene(SceneList::WORLD); SetNextScene(SceneList::INWORLD);
} }
void LobbyMenu::HandleJoinRejection(TextPacket* const argPacket) { void LobbyMenu::HandleJoinRejection(TextPacket* const argPacket) {
//TODO: (9) empty //TODO: Better output for join rejection
} }
void LobbyMenu::HandleLoginRejection(TextPacket* const argPacket) { void LobbyMenu::HandleLoginRejection(TextPacket* const argPacket) {
//TODO: (9) empty //TODO: Better output for login rejection
} }
//------------------------- //-------------------------
+4 -7
View File
@@ -88,7 +88,8 @@ void MainMenu::Render(SDL_Surface* const screen) {
//text //text
font.DrawStringTo("Thanks for playing!", screen, 50, screen->h - 50 - image.GetClipH() * 2); font.DrawStringTo("Thanks for playing!", screen, 50, screen->h - 50 - image.GetClipH() * 2);
font.DrawStringTo("You can get the latest version at: ", screen, 50, screen->h - 50 - image.GetClipH() * 1); font.DrawStringTo("You can get the latest version at: ", screen, 50, screen->h - 50 - image.GetClipH() * 1);
font.DrawStringTo("krgamestudios.com", screen, 50, screen->h - 50 - image.GetClipH() * 0); font.DrawStringTo("https://github.com/Ratstail91/Tortuga", screen, 50, screen->h - 50 - image.GetClipH() * 0);
//TODO: replace this with a website address
} }
//------------------------- //-------------------------
@@ -108,7 +109,7 @@ void MainMenu::MouseButtonDown(SDL_MouseButtonEvent const& button) {
} }
void MainMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) { void MainMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
//TODO: (2) Buttons should only register as "selected" when the left button is used //TODO: Buttons should only register as "selected" when the left button is used
if (startButton.MouseButtonUp(button) == Button::State::HOVER) { if (startButton.MouseButtonUp(button) == Button::State::HOVER) {
SetNextScene(SceneList::LOBBYMENU); SetNextScene(SceneList::LOBBYMENU);
} }
@@ -125,9 +126,5 @@ void MainMenu::KeyDown(SDL_KeyboardEvent const& key) {
} }
void MainMenu::KeyUp(SDL_KeyboardEvent const& key) { void MainMenu::KeyUp(SDL_KeyboardEvent const& key) {
switch(key.keysym.sym) { //
case SDLK_ESCAPE:
QuitEvent();
break;
}
} }
+1 -1
View File
@@ -28,7 +28,7 @@
#include "raster_font.hpp" #include "raster_font.hpp"
#include "button.hpp" #include "button.hpp"
//NOTE: The options screen needs to be USED //TODO: The options screen needs to be USED
class OptionsMenu : public BaseScene { class OptionsMenu : public BaseScene {
public: public:
//Public access members //Public access members
+1 -1
View File
@@ -33,7 +33,7 @@ enum class SceneList {
MAINMENU, MAINMENU,
OPTIONSMENU, OPTIONSMENU,
LOBBYMENU, LOBBYMENU,
WORLD, INWORLD,
DISCONNECTEDSCREEN, DISCONNECTEDSCREEN,
}; };
@@ -34,11 +34,14 @@ struct CharacterPacket : SerialPacketBase {
//the owner //the owner
int accountIndex; int accountIndex;
//TODO: Authentication token?
//location //location
int roomIndex; int roomIndex;
Vector2 origin; Vector2 origin;
Vector2 motion; Vector2 motion;
//gameplay components: equipment, items, buffs, debuffs...
}; };
void serializeCharacter(void* buffer, CharacterPacket* packet); void serializeCharacter(void* buffer, CharacterPacket* packet);
@@ -28,7 +28,6 @@ struct ClientPacket : SerialPacketBase {
int clientIndex; int clientIndex;
int accountIndex; int accountIndex;
char username[PACKET_STRING_SIZE]; char username[PACKET_STRING_SIZE];
//TODO: (9) password, auth token
}; };
void serializeClient(void* buffer, ClientPacket* packet); void serializeClient(void* buffer, ClientPacket* packet);
@@ -44,6 +44,9 @@ void serializeMonster(void* buffer, MonsterPacket* packet) {
serialCopy(&buffer, &packet->origin.y, sizeof(double)); serialCopy(&buffer, &packet->origin.y, sizeof(double));
serialCopy(&buffer, &packet->motion.x, sizeof(double)); serialCopy(&buffer, &packet->motion.x, sizeof(double));
serialCopy(&buffer, &packet->motion.y, sizeof(double)); serialCopy(&buffer, &packet->motion.y, sizeof(double));
//attack data
//TODO
} }
void deserializeMonster(void* buffer, MonsterPacket* packet) { void deserializeMonster(void* buffer, MonsterPacket* packet) {
@@ -67,4 +70,7 @@ void deserializeMonster(void* buffer, MonsterPacket* packet) {
deserialCopy(&buffer, &packet->origin.y, sizeof(double)); deserialCopy(&buffer, &packet->origin.y, sizeof(double));
deserialCopy(&buffer, &packet->motion.x, sizeof(double)); deserialCopy(&buffer, &packet->motion.x, sizeof(double));
deserialCopy(&buffer, &packet->motion.y, sizeof(double)); deserialCopy(&buffer, &packet->motion.y, sizeof(double));
//attack data
//TODO
} }
@@ -38,6 +38,8 @@ struct MonsterPacket : SerialPacketBase {
int roomIndex; int roomIndex;
Vector2 origin; Vector2 origin;
Vector2 motion; Vector2 motion;
//TODO: attack data
}; };
void serializeMonster(void* buffer, MonsterPacket* packet); void serializeMonster(void* buffer, MonsterPacket* packet);
@@ -29,12 +29,6 @@ void serializeText(void* buffer, TextPacket* packet) {
//content //content
serialCopy(&buffer, packet->name, PACKET_STRING_SIZE); serialCopy(&buffer, packet->name, PACKET_STRING_SIZE);
serialCopy(&buffer, packet->text, PACKET_STRING_SIZE); serialCopy(&buffer, packet->text, PACKET_STRING_SIZE);
//location
serialCopy(&buffer, &packet->roomIndex, sizeof(int));
serialCopy(&buffer, &packet->origin.x, sizeof(double));
serialCopy(&buffer, &packet->origin.y, sizeof(double));
serialCopy(&buffer, &packet->range, sizeof(int));
} }
void deserializeText(void* buffer, TextPacket* packet) { void deserializeText(void* buffer, TextPacket* packet) {
@@ -43,10 +37,4 @@ void deserializeText(void* buffer, TextPacket* packet) {
//content //content
deserialCopy(&buffer, packet->name, PACKET_STRING_SIZE); deserialCopy(&buffer, packet->name, PACKET_STRING_SIZE);
deserialCopy(&buffer, packet->text, PACKET_STRING_SIZE); deserialCopy(&buffer, packet->text, PACKET_STRING_SIZE);
//location
deserialCopy(&buffer, &packet->roomIndex, sizeof(int));
deserialCopy(&buffer, &packet->origin.x, sizeof(double));
deserialCopy(&buffer, &packet->origin.y, sizeof(double));
deserialCopy(&buffer, &packet->range, sizeof(int));
} }
@@ -24,14 +24,9 @@
#include "serial_packet_base.hpp" #include "serial_packet_base.hpp"
#include "vector2.hpp"
struct TextPacket : SerialPacketBase { struct TextPacket : SerialPacketBase {
char name[PACKET_STRING_SIZE]; char name[PACKET_STRING_SIZE];
char text[PACKET_STRING_SIZE]; char text[PACKET_STRING_SIZE];
int roomIndex;
Vector2 origin;
int range;
}; };
void serializeText(void* buffer, TextPacket* packet); void serializeText(void* buffer, TextPacket* packet);
+1 -1
View File
@@ -34,7 +34,7 @@
typedef SerialPacketBase SerialPacket; typedef SerialPacketBase SerialPacket;
//DOCS: NETWORK_VERSION is used to discern compatible servers and clients //DOCS: NETWORK_VERSION is used to discern compatible servers and clients
constexpr int NETWORK_VERSION = 20150214; constexpr int NETWORK_VERSION = -1;
union MaxPacket { union MaxPacket {
CharacterPacket a; CharacterPacket a;
+12 -15
View File
@@ -27,6 +27,7 @@
* valid data, but it will still be carried in that packet's format. * valid data, but it will still be carried in that packet's format.
*/ */
//TODO: This needs to be smoothed out
enum class SerialPacketType { enum class SerialPacketType {
//default: there is something wrong //default: there is something wrong
NONE, NONE,
@@ -56,7 +57,7 @@ enum class SerialPacketType {
//disconnect from the server //disconnect from the server
DISCONNECT_REQUEST, DISCONNECT_REQUEST,
DISCONNECT_RESPONSE, DISCONNECT_RESPONSE,
ADMIN_DISCONNECT_FORCED, DISCONNECT_FORCED,
//load the account //load the account
LOGIN_REQUEST, LOGIN_REQUEST,
@@ -67,7 +68,7 @@ enum class SerialPacketType {
LOGOUT_RESPONSE, LOGOUT_RESPONSE,
//shut down the server //shut down the server
ADMIN_SHUTDOWN_REQUEST, SHUTDOWN_REQUEST,
//------------------------- //-------------------------
//RegionPacket //RegionPacket
@@ -75,7 +76,7 @@ enum class SerialPacketType {
//------------------------- //-------------------------
//map data //map data
REGION_REQUEST, REGION_REQUEST, //NOTE: technically a query
REGION_CONTENT, REGION_CONTENT,
//------------------------- //-------------------------
@@ -83,7 +84,8 @@ enum class SerialPacketType {
// character index, // character index,
// handle, avatar, // handle, avatar,
// account index (owner), // account index (owner),
// room index, origin, motion // room index, origin, motion,
// statistics
//------------------------- //-------------------------
//character management //character management
@@ -100,7 +102,6 @@ enum class SerialPacketType {
//set the info in the server //set the info in the server
CHARACTER_MOVEMENT, CHARACTER_MOVEMENT,
CHARACTER_ATTACK, CHARACTER_ATTACK,
CHARACTER_DAMAGE,
//admin control //admin control
// ADMIN_SET_CHARACTER_ORIGIN, // ADMIN_SET_CHARACTER_ORIGIN,
@@ -108,21 +109,20 @@ enum class SerialPacketType {
//------------------------- //-------------------------
//MonsterPacket //MonsterPacket
// monster index, // monster index,
// handle, avatar // handle, avatar, hitbox
// bounds
// room index, origin, motion // room index, origin, motion
// TODO: attack data
//------------------------- //-------------------------
MONSTER_CREATE, MONSTER_CREATE,
MONSTER_DELETE, MONSTER_DELETE,
QUERY_MONSTER_EXISTS, QUERY_MONSTER_EXISTS, //a list of monsters in a room
QUERY_MONSTER_STATS, QUERY_MONSTER_STATS, //statistics of a specific monster type or instance
QUERY_MONSTER_LOCATION, QUERY_MONSTER_LOCATION, //umm...
MONSTER_MOVEMENT, MONSTER_MOVEMENT, //monster movement
MONSTER_ATTACK, MONSTER_ATTACK,
MONSTER_DAMAGE,
//------------------------- //-------------------------
//TextPacket //TextPacket
@@ -131,8 +131,6 @@ enum class SerialPacketType {
//general speech //general speech
TEXT_BROADCAST, TEXT_BROADCAST,
TEXT_SPEECH,
TEXT_WHISPER,
//rejection/error messages //rejection/error messages
JOIN_REJECTION, JOIN_REJECTION,
@@ -141,7 +139,6 @@ enum class SerialPacketType {
CHARACTER_REJECTION, CHARACTER_REJECTION,
MONSTER_REJECTION, MONSTER_REJECTION,
SHUTDOWN_REJECTION, SHUTDOWN_REJECTION,
QUERY_REJECTION,
//------------------------- //-------------------------
//not used //not used
+4 -14
View File
@@ -57,12 +57,12 @@ void serializePacket(void* buffer, SerialPacketBase* packet) {
case SerialPacketType::JOIN_RESPONSE: case SerialPacketType::JOIN_RESPONSE:
case SerialPacketType::DISCONNECT_REQUEST: case SerialPacketType::DISCONNECT_REQUEST:
case SerialPacketType::DISCONNECT_RESPONSE: case SerialPacketType::DISCONNECT_RESPONSE:
case SerialPacketType::ADMIN_DISCONNECT_FORCED: case SerialPacketType::DISCONNECT_FORCED:
case SerialPacketType::LOGIN_REQUEST: case SerialPacketType::LOGIN_REQUEST:
case SerialPacketType::LOGIN_RESPONSE: case SerialPacketType::LOGIN_RESPONSE:
case SerialPacketType::LOGOUT_REQUEST: case SerialPacketType::LOGOUT_REQUEST:
case SerialPacketType::LOGOUT_RESPONSE: case SerialPacketType::LOGOUT_RESPONSE:
case SerialPacketType::ADMIN_SHUTDOWN_REQUEST: case SerialPacketType::SHUTDOWN_REQUEST:
serializeClient(buffer, static_cast<ClientPacket*>(packet)); serializeClient(buffer, static_cast<ClientPacket*>(packet));
break; break;
case SerialPacketType::REGION_REQUEST: case SerialPacketType::REGION_REQUEST:
@@ -78,7 +78,6 @@ void serializePacket(void* buffer, SerialPacketBase* packet) {
case SerialPacketType::QUERY_CHARACTER_LOCATION: case SerialPacketType::QUERY_CHARACTER_LOCATION:
case SerialPacketType::CHARACTER_MOVEMENT: case SerialPacketType::CHARACTER_MOVEMENT:
case SerialPacketType::CHARACTER_ATTACK: case SerialPacketType::CHARACTER_ATTACK:
case SerialPacketType::CHARACTER_DAMAGE:
serializeCharacter(buffer, static_cast<CharacterPacket*>(packet)); serializeCharacter(buffer, static_cast<CharacterPacket*>(packet));
break; break;
case SerialPacketType::MONSTER_CREATE: case SerialPacketType::MONSTER_CREATE:
@@ -88,19 +87,15 @@ void serializePacket(void* buffer, SerialPacketBase* packet) {
case SerialPacketType::QUERY_MONSTER_LOCATION: case SerialPacketType::QUERY_MONSTER_LOCATION:
case SerialPacketType::MONSTER_MOVEMENT: case SerialPacketType::MONSTER_MOVEMENT:
case SerialPacketType::MONSTER_ATTACK: case SerialPacketType::MONSTER_ATTACK:
case SerialPacketType::MONSTER_DAMAGE:
serializeMonster(buffer, static_cast<MonsterPacket*>(packet)); serializeMonster(buffer, static_cast<MonsterPacket*>(packet));
break; break;
case SerialPacketType::TEXT_BROADCAST: case SerialPacketType::TEXT_BROADCAST:
case SerialPacketType::TEXT_SPEECH:
case SerialPacketType::TEXT_WHISPER:
case SerialPacketType::JOIN_REJECTION: case SerialPacketType::JOIN_REJECTION:
case SerialPacketType::LOGIN_REJECTION: case SerialPacketType::LOGIN_REJECTION:
case SerialPacketType::REGION_REJECTION: case SerialPacketType::REGION_REJECTION:
case SerialPacketType::CHARACTER_REJECTION: case SerialPacketType::CHARACTER_REJECTION:
case SerialPacketType::MONSTER_REJECTION: case SerialPacketType::MONSTER_REJECTION:
case SerialPacketType::SHUTDOWN_REJECTION: case SerialPacketType::SHUTDOWN_REJECTION:
case SerialPacketType::QUERY_REJECTION:
serializeText(buffer, static_cast<TextPacket*>(packet)); serializeText(buffer, static_cast<TextPacket*>(packet));
break; break;
} }
@@ -122,12 +117,12 @@ void deserializePacket(void* buffer, SerialPacketBase* packet) {
case SerialPacketType::JOIN_RESPONSE: case SerialPacketType::JOIN_RESPONSE:
case SerialPacketType::DISCONNECT_REQUEST: case SerialPacketType::DISCONNECT_REQUEST:
case SerialPacketType::DISCONNECT_RESPONSE: case SerialPacketType::DISCONNECT_RESPONSE:
case SerialPacketType::ADMIN_DISCONNECT_FORCED: case SerialPacketType::DISCONNECT_FORCED:
case SerialPacketType::LOGIN_REQUEST: case SerialPacketType::LOGIN_REQUEST:
case SerialPacketType::LOGIN_RESPONSE: case SerialPacketType::LOGIN_RESPONSE:
case SerialPacketType::LOGOUT_REQUEST: case SerialPacketType::LOGOUT_REQUEST:
case SerialPacketType::LOGOUT_RESPONSE: case SerialPacketType::LOGOUT_RESPONSE:
case SerialPacketType::ADMIN_SHUTDOWN_REQUEST: case SerialPacketType::SHUTDOWN_REQUEST:
deserializeClient(buffer, static_cast<ClientPacket*>(packet)); deserializeClient(buffer, static_cast<ClientPacket*>(packet));
break; break;
case SerialPacketType::REGION_REQUEST: case SerialPacketType::REGION_REQUEST:
@@ -143,7 +138,6 @@ void deserializePacket(void* buffer, SerialPacketBase* packet) {
case SerialPacketType::QUERY_CHARACTER_LOCATION: case SerialPacketType::QUERY_CHARACTER_LOCATION:
case SerialPacketType::CHARACTER_MOVEMENT: case SerialPacketType::CHARACTER_MOVEMENT:
case SerialPacketType::CHARACTER_ATTACK: case SerialPacketType::CHARACTER_ATTACK:
case SerialPacketType::CHARACTER_DAMAGE:
deserializeCharacter(buffer, static_cast<CharacterPacket*>(packet)); deserializeCharacter(buffer, static_cast<CharacterPacket*>(packet));
break; break;
case SerialPacketType::MONSTER_CREATE: case SerialPacketType::MONSTER_CREATE:
@@ -153,19 +147,15 @@ void deserializePacket(void* buffer, SerialPacketBase* packet) {
case SerialPacketType::QUERY_MONSTER_LOCATION: case SerialPacketType::QUERY_MONSTER_LOCATION:
case SerialPacketType::MONSTER_MOVEMENT: case SerialPacketType::MONSTER_MOVEMENT:
case SerialPacketType::MONSTER_ATTACK: case SerialPacketType::MONSTER_ATTACK:
case SerialPacketType::MONSTER_DAMAGE:
deserializeMonster(buffer, static_cast<MonsterPacket*>(packet)); deserializeMonster(buffer, static_cast<MonsterPacket*>(packet));
break; break;
case SerialPacketType::TEXT_BROADCAST: case SerialPacketType::TEXT_BROADCAST:
case SerialPacketType::TEXT_SPEECH:
case SerialPacketType::TEXT_WHISPER:
case SerialPacketType::JOIN_REJECTION: case SerialPacketType::JOIN_REJECTION:
case SerialPacketType::LOGIN_REJECTION: case SerialPacketType::LOGIN_REJECTION:
case SerialPacketType::REGION_REJECTION: case SerialPacketType::REGION_REJECTION:
case SerialPacketType::CHARACTER_REJECTION: case SerialPacketType::CHARACTER_REJECTION:
case SerialPacketType::MONSTER_REJECTION: case SerialPacketType::MONSTER_REJECTION:
case SerialPacketType::SHUTDOWN_REJECTION: case SerialPacketType::SHUTDOWN_REJECTION:
case SerialPacketType::QUERY_REJECTION:
deserializeText(buffer, static_cast<TextPacket*>(packet)); deserializeText(buffer, static_cast<TextPacket*>(packet));
break; break;
} }
+1
View File
@@ -140,6 +140,7 @@ int UDPNetworkUtility::SendToAllChannels(void* data, int len) {
return sent; return sent;
} }
//TODO: put a void* and int* parameter list here
int UDPNetworkUtility::Receive() { int UDPNetworkUtility::Receive() {
memset(packet->data, 0, packet->maxlen); memset(packet->data, 0, packet->maxlen);
int ret = SDLNet_UDP_Recv(socket, packet); int ret = SDLNet_UDP_Recv(socket, packet);
+16 -14
View File
@@ -22,6 +22,8 @@
#ifndef BOUNDINGBOX_HPP_ #ifndef BOUNDINGBOX_HPP_
#define BOUNDINGBOX_HPP_ #define BOUNDINGBOX_HPP_
#include "vector2.hpp"
#include <type_traits> #include <type_traits>
#include <algorithm> #include <algorithm>
@@ -32,16 +34,15 @@ public:
int w, h; int w, h;
BoundingBox() = default; BoundingBox() = default;
BoundingBox(int i, int j): x(i), y(j), w(0), h(0) {};
BoundingBox(int i, int j, int k, int l): x(i), y(j), w(k), h(l) {}; BoundingBox(int i, int j, int k, int l): x(i), y(j), w(k), h(l) {};
~BoundingBox() = default; ~BoundingBox() = default;
BoundingBox& operator=(BoundingBox const&) = default; BoundingBox& operator=(BoundingBox const&) = default;
int Size() { int Size() {
return std::max(w*h,0); return (w-x) * (h-y);
} }
bool CheckOverlap(BoundingBox rhs) { bool CheckCollision(BoundingBox rhs) {
return !( return !(
x >= rhs.x + rhs.w || x >= rhs.x + rhs.w ||
y >= rhs.y + rhs.h || y >= rhs.y + rhs.h ||
@@ -49,24 +50,25 @@ public:
rhs.y >= y + h); rhs.y >= y + h);
} }
BoundingBox CalcOverlap(BoundingBox rhs) { Vector2 CalcShift(BoundingBox rhs) {
if (!CheckOverlap(rhs)) { if (!CheckCollision(rhs)) {
return {0, 0, 0, 0}; return {0, 0};
} }
BoundingBox ret;
ret.x = std::max(x, rhs.x); //DOCS: Given two BoundingBox objects, how does the other have to move so that they are no longer colliding?
ret.y = std::max(y, rhs.y); Vector2 horizontal = {0, 0};
ret.w = std::min(x+w, rhs.x+rhs.w) - ret.x; Vector2 vertical = {0, 0};
ret.h = std::min(y+h, rhs.y+rhs.h) - ret.y;
return ret; horizontal.x = std::abs(x + w - rhs.x) < std::abs(rhs.x + rhs.w - x) ? x + w - rhs.x -1 : -(rhs.x + rhs.w - x -1);
vertical.y = std::abs(y + h - rhs.x) < std::abs(rhs.y + rhs.h - y) ? y + h - rhs.y -1 : -(rhs.y + rhs.h - y -1);
return std::abs(vertical.y) < std::abs(horizontal.x) ? vertical : horizontal;
} }
}; };
//This is explicitly a POD //This is explicitly a POD
static_assert(std::is_pod<BoundingBox>::value, "BoundingBox is not a POD"); static_assert(std::is_pod<BoundingBox>::value, "BoundingBox is not a POD");
#include "vector2.hpp"
//operators //operators
inline BoundingBox operator+(BoundingBox b, Vector2 v) { inline BoundingBox operator+(BoundingBox b, Vector2 v) {
return {b.x + (int)v.x, b.y + (int)v.y, b.w, b.h}; return {b.x + (int)v.x, b.y + (int)v.y, b.w, b.h};
+1 -1
View File
@@ -11,5 +11,5 @@ function mapSaver.Save(r)
io.write("map_saver:Save(", Region.GetX(r), ", ", Region.GetY(r), ")\n") io.write("map_saver:Save(", Region.GetX(r), ", ", Region.GetY(r), ")\n")
end end
--TODO: (9) create a flexible saving & loading system --TODO: create a flexible saving & loading system
return mapSaver return mapSaver
+4 -4
View File
@@ -1,10 +1,10 @@
--TODO: (9) An archive table of all dead characters --TODO: An archive table of all dead characters
CREATE TABLE IF NOT EXISTS Accounts ( CREATE TABLE IF NOT EXISTS Accounts (
uid INTEGER PRIMARY KEY AUTOINCREMENT, uid INTEGER PRIMARY KEY AUTOINCREMENT,
username varchar(100) UNIQUE, --TODO: (9) Swap username for email address username varchar(100) UNIQUE,
--server-client security --TODO: server-client security
-- passhash varchar(100), -- passhash varchar(100),
-- passsalt varchar(100), -- passsalt varchar(100),
@@ -101,5 +101,5 @@ CREATE TABLE IF NOT EXISTS WornEquipment (
--unique information --unique information
durability INTEGER DEFAULT 0, durability INTEGER DEFAULT 0,
stats INTEGER REFERENCES StatisticSets(uid) stats INTEGER REFERENCES StatisticSets(uid)
--attached script? --TODO: attached script?
); );
+1 -1
View File
@@ -47,7 +47,7 @@ private:
int clientIndex; int clientIndex;
std::string username; std::string username;
//password/auth token //TODO: password
//bit fields? //bit fields?
bool blackListed = false; bool blackListed = false;
+11 -11
View File
@@ -30,45 +30,45 @@ MonsterManager::~MonsterManager() {
} }
int MonsterManager::Create(std::string) { int MonsterManager::Create(std::string) {
//Create //TODO
} }
void MonsterManager::Unload(int uid) { void MonsterManager::Unload(int uid) {
//Unload //TODO
} }
void MonsterManager::UnloadAll() { void MonsterManager::UnloadAll() {
//UnloadAll //TODO
} }
void MonsterManager::UnloadIf(std::function<bool(std::pair<const int, MonsterData const&>)> fn) { void MonsterManager::UnloadIf(std::function<bool(std::pair<const int, MonsterData const&>)> fn) {
//UnloadIf //TODO
} }
MonsterData* MonsterManager::Get(int uid) { MonsterData* MonsterManager::Get(int uid) {
//Get //TODO
} }
int MonsterManager::GetLoadedCount() { int MonsterManager::GetLoadedCount() {
//GetLoadedCount //TODO
} }
std::map<int, MonsterData>* MonsterManager::GetContainer() { std::map<int, MonsterData>* MonsterManager::GetContainer() {
//GetContainer //TODO
} }
lua_State* MonsterManager::SetLuaState(lua_State* L) { lua_State* MonsterManager::SetLuaState(lua_State* L) {
//SetLuaState //TODO
} }
lua_State* MonsterManager::GetLuaState() { lua_State* MonsterManager::GetLuaState() {
//GetLuaState //TODO
} }
sqlite3* MonsterManager::SetDatabase(sqlite3* db) { sqlite3* MonsterManager::SetDatabase(sqlite3* db) {
//SetDatabase //TODO
} }
sqlite3* MonsterManager::GetDatabase() { sqlite3* MonsterManager::GetDatabase() {
//GetDatabase //TODO
} }
+1
View File
@@ -66,6 +66,7 @@ static int getWaypointMgr(lua_State* L) {
} }
static int initialize(lua_State* L) { static int initialize(lua_State* L) {
//TODO: This could fit into the room system's globals
RoomData* room = static_cast<RoomData*>(lua_touserdata(L, 1)); RoomData* room = static_cast<RoomData*>(lua_touserdata(L, 1));
//set the refs of these parameters (backwards, since it pops from the top of the stack) //set the refs of these parameters (backwards, since it pops from the top of the stack)
+1 -1
View File
@@ -71,7 +71,7 @@ int unloadRoom(lua_State* L) {
} }
int getRoom(lua_State* L) { int getRoom(lua_State* L) {
//integer vs name for getRoom() //TODO: integer vs name for getRoom()
RoomManager& roomMgr = RoomManager::GetSingleton(); RoomManager& roomMgr = RoomManager::GetSingleton();
RoomData* room = nullptr; RoomData* room = nullptr;
+27 -37
View File
@@ -34,7 +34,6 @@
#include "udp_network_utility.hpp" #include "udp_network_utility.hpp"
//common utilities //common utilities
#include "ip_operators.hpp"
#include "serial_packet.hpp" #include "serial_packet.hpp"
#include "singleton.hpp" #include "singleton.hpp"
@@ -48,6 +47,10 @@
#include <map> #include <map>
#include <string> #include <string>
//global utility functions
bool operator==(IPaddress lhs, IPaddress rhs);
bool operator!=(IPaddress lhs, IPaddress rhs);
//The main application class //The main application class
class ServerApplication: public Singleton<ServerApplication> { class ServerApplication: public Singleton<ServerApplication> {
public: public:
@@ -65,59 +68,46 @@ private:
//handle incoming traffic //handle incoming traffic
void HandlePacket(SerialPacket* const); void HandlePacket(SerialPacket* const);
//heartbeat system //heartbeat sustem
void hPing(ServerPacket* const); void HandlePing(ServerPacket* const);
void hPong(ServerPacket* const); void HandlePong(ServerPacket* const);
//basic connections //basic connections
void hBroadcastRequest(ServerPacket* const); void HandleBroadcastRequest(ServerPacket* const);
void hJoinRequest(ClientPacket* const); void HandleJoinRequest(ClientPacket* const);
void hLoginRequest(ClientPacket* const); void HandleLoginRequest(ClientPacket* const);
//client disconnections //client disconnections
void hLogoutRequest(ClientPacket* const); void HandleLogoutRequest(ClientPacket* const);
void hDisconnectRequest(ClientPacket* const); void HandleDisconnectRequest(ClientPacket* const);
//server commands //server commands
void hAdminDisconnectForced(ClientPacket* const); void HandleDisconnectForced(ClientPacket* const);
void hAdminShutdownRequest(ClientPacket* const); void HandleShutdownRequest(ClientPacket* const);
//data management //data management
void hRegionRequest(RegionPacket* const); void HandleRegionRequest(RegionPacket* const);
void hQueryCharacterExists(CharacterPacket* const); void HandleCharacterExists(CharacterPacket* const);
void hQueryCharacterStats(CharacterPacket* const);
void hQueryCharacterLocation(CharacterPacket* const); void SaveServerState();
void hQueryMonsterExists(MonsterPacket* const); void FullClientUnload(int index);
void hQueryMonsterStats(MonsterPacket* const); void FullAccountUnload(int index);
void hQueryMonsterLocation(MonsterPacket* const); void FullCharacterUnload(int index);
//character management //character management
void hCharacterCreate(CharacterPacket* const); void HandleCharacterCreate(CharacterPacket* const);
void hCharacterDelete(CharacterPacket* const); void HandleCharacterDelete(CharacterPacket* const);
void hCharacterLoad(CharacterPacket* const); void HandleCharacterLoad(CharacterPacket* const);
void hCharacterUnload(CharacterPacket* const); void HandleCharacterUnload(CharacterPacket* const);
//character movement //character movement
void hCharacterMovement(CharacterPacket* const); void HandleCharacterMovement(CharacterPacket* const);
void hCharacterAttack(CharacterPacket* const); void HandleCharacterAttack(CharacterPacket* const);
void hCharacterDamage(CharacterPacket* const);
//character management
void hMonsterDamage(MonsterPacket* const);
//chat
void hTextBroadcast(TextPacket* const);
void hTextSpeech(TextPacket* const);
void hTextWhisper(TextPacket* const);
//utility methods //utility methods
void PumpPacket(SerialPacket* const); void PumpPacket(SerialPacket* const);
void PumpPacketProximity(SerialPacket* const argPacket, int roomIndex, Vector2 position, int distance); void PumpPacketProximity(SerialPacket* const argPacket, int roomIndex, Vector2 position, int distance);
void CopyCharacterToPacket(CharacterPacket* const packet, int characterIndex); void CopyCharacterToPacket(CharacterPacket* const packet, int characterIndex);
void SaveServerState();
void FullClientUnload(int index);
void FullAccountUnload(int index);
void FullCharacterUnload(int index);
//APIs and utilities //APIs and utilities
sqlite3* database = nullptr; sqlite3* database = nullptr;
+11 -15
View File
@@ -28,7 +28,7 @@
//Character Management //Character Management
//------------------------- //-------------------------
void ServerApplication::hCharacterCreate(CharacterPacket* const argPacket) { void ServerApplication::HandleCharacterCreate(CharacterPacket* const argPacket) {
int characterIndex = characterMgr.Create(argPacket->accountIndex, argPacket->handle, argPacket->avatar); int characterIndex = characterMgr.Create(argPacket->accountIndex, argPacket->handle, argPacket->avatar);
if (characterIndex < 0) { if (characterIndex < 0) {
@@ -55,7 +55,7 @@ void ServerApplication::hCharacterCreate(CharacterPacket* const argPacket) {
PumpPacket(&newPacket); PumpPacket(&newPacket);
} }
void ServerApplication::hCharacterDelete(CharacterPacket* const argPacket) { void ServerApplication::HandleCharacterDelete(CharacterPacket* const argPacket) {
//get the user's data //get the user's data
AccountData* accountData = accountMgr.Get(argPacket->accountIndex); AccountData* accountData = accountMgr.Get(argPacket->accountIndex);
if (!accountData) { if (!accountData) {
@@ -102,7 +102,7 @@ void ServerApplication::hCharacterDelete(CharacterPacket* const argPacket) {
PumpPacket(static_cast<SerialPacket*>(&newPacket)); PumpPacket(static_cast<SerialPacket*>(&newPacket));
} }
void ServerApplication::hCharacterLoad(CharacterPacket* const argPacket) { void ServerApplication::HandleCharacterLoad(CharacterPacket* const argPacket) {
int characterIndex = characterMgr.Load(argPacket->accountIndex, argPacket->handle, argPacket->avatar); int characterIndex = characterMgr.Load(argPacket->accountIndex, argPacket->handle, argPacket->avatar);
if (characterIndex < 0) { if (characterIndex < 0) {
@@ -135,7 +135,7 @@ void ServerApplication::hCharacterLoad(CharacterPacket* const argPacket) {
PumpPacket(&newPacket); PumpPacket(&newPacket);
} }
void ServerApplication::hCharacterUnload(CharacterPacket* const argPacket) { void ServerApplication::HandleCharacterUnload(CharacterPacket* const argPacket) {
//get the entries //get the entries
CharacterData* characterData = characterMgr.Get(argPacket->characterIndex); CharacterData* characterData = characterMgr.Get(argPacket->characterIndex);
if (!characterData) { if (!characterData) {
@@ -144,12 +144,12 @@ void ServerApplication::hCharacterUnload(CharacterPacket* const argPacket) {
AccountData* accountData = accountMgr.Get(characterData->GetOwner()); AccountData* accountData = accountMgr.Get(characterData->GetOwner());
if (!accountData) { if (!accountData) {
return; return; //TODO: logic_error
} }
ClientData* clientData = clientMgr.Get(accountData->GetClientIndex()); ClientData* clientData = clientMgr.Get(accountData->GetClientIndex());
if (!clientData) { if (!clientData) {
return; return; //TODO: logic_error
} }
//check for fraud //check for fraud
@@ -175,9 +175,9 @@ void ServerApplication::hCharacterUnload(CharacterPacket* const argPacket) {
//character movement //character movement
//------------------------- //-------------------------
//TODO: (2) Could replace this verbosity with a "verify" method, taking a client, account and character ptr as arguments //TODO: Could replace this verbosity with a "verify" method, taking a client, account and character ptr as arguments
void ServerApplication::hCharacterMovement(CharacterPacket* const argPacket) { void ServerApplication::HandleCharacterMovement(CharacterPacket* const argPacket) {
//get the specified objects //get the specified objects
AccountData* accountData = accountMgr.Get(argPacket->accountIndex); AccountData* accountData = accountMgr.Get(argPacket->accountIndex);
CharacterData* characterData = characterMgr.Get(argPacket->characterIndex); CharacterData* characterData = characterMgr.Get(argPacket->characterIndex);
@@ -197,7 +197,7 @@ void ServerApplication::hCharacterMovement(CharacterPacket* const argPacket) {
//check if allowed //check if allowed
if (characterData->GetOwner() != argPacket->accountIndex && !accountData->GetModerator() && !accountData->GetAdministrator()) { if (characterData->GetOwner() != argPacket->accountIndex && !accountData->GetModerator() && !accountData->GetAdministrator()) {
//TODO: (2) send to the client? //TODO: send to the client?
std::cerr << "Failed to set character motion due to lack of permissions targeting uid(" << argPacket->characterIndex << ")" << std::endl; std::cerr << "Failed to set character motion due to lack of permissions targeting uid(" << argPacket->characterIndex << ")" << std::endl;
return; return;
} }
@@ -234,10 +234,6 @@ void ServerApplication::hCharacterMovement(CharacterPacket* const argPacket) {
} }
} }
void ServerApplication::hCharacterAttack(CharacterPacket* const argPacket) { void ServerApplication::HandleCharacterAttack(CharacterPacket* const) {
//TODO: (9) empty //TODO: bounce graphical attack data
}
void ServerApplication::hCharacterDamage(CharacterPacket* const argPacket) {
//TODO: (9) empty
} }
-34
View File
@@ -1,34 +0,0 @@
/* Copyright: (c) Kayne Ruse 2013-2015
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "server_application.hpp"
void ServerApplication::hTextBroadcast(TextPacket* const argPacket) {
//TODO: (9) empty
}
void ServerApplication::hTextSpeech(TextPacket* const argPacket) {
//TODO: (9) empty
}
void ServerApplication::hTextWhisper(TextPacket* const argPacket) {
//TODO: (9) empty
}
+11 -7
View File
@@ -28,13 +28,13 @@
//heartbeat system //heartbeat system
//------------------------- //-------------------------
void ServerApplication::hPing(ServerPacket* const argPacket) { void ServerApplication::HandlePing(ServerPacket* const argPacket) {
ServerPacket newPacket; ServerPacket newPacket;
newPacket.type = SerialPacketType::PONG; newPacket.type = SerialPacketType::PONG;
network.SendTo(argPacket->srcAddress, &newPacket); network.SendTo(argPacket->srcAddress, &newPacket);
} }
void ServerApplication::hPong(ServerPacket* const argPacket) { void ServerApplication::HandlePong(ServerPacket* const argPacket) {
clientMgr.HandlePong(argPacket); clientMgr.HandlePong(argPacket);
} }
@@ -42,7 +42,7 @@ void ServerApplication::hPong(ServerPacket* const argPacket) {
//basic connections //basic connections
//------------------------- //-------------------------
void ServerApplication::hBroadcastRequest(ServerPacket* const argPacket) { void ServerApplication::HandleBroadcastRequest(ServerPacket* const argPacket) {
//send the server's data //send the server's data
ServerPacket newPacket; ServerPacket newPacket;
@@ -54,7 +54,7 @@ void ServerApplication::hBroadcastRequest(ServerPacket* const argPacket) {
network.SendTo(argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket)); network.SendTo(argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket));
} }
void ServerApplication::hJoinRequest(ClientPacket* const argPacket) { void ServerApplication::HandleJoinRequest(ClientPacket* const argPacket) {
//register the client //register the client
int clientIndex = clientMgr.Create(argPacket->srcAddress); int clientIndex = clientMgr.Create(argPacket->srcAddress);
@@ -69,7 +69,7 @@ void ServerApplication::hJoinRequest(ClientPacket* const argPacket) {
std::cout << "New join, " << clientMgr.GetLoadedCount() << " clients and " << accountMgr.GetLoadedCount() << " accounts total" << std::endl; std::cout << "New join, " << clientMgr.GetLoadedCount() << " clients and " << accountMgr.GetLoadedCount() << " accounts total" << std::endl;
} }
void ServerApplication::hLoginRequest(ClientPacket* const argPacket) { void ServerApplication::HandleLoginRequest(ClientPacket* const argPacket) {
//get the client data //get the client data
ClientData* clientData = clientMgr.Get(argPacket->clientIndex); ClientData* clientData = clientMgr.Get(argPacket->clientIndex);
@@ -110,7 +110,7 @@ void ServerApplication::hLoginRequest(ClientPacket* const argPacket) {
std::cout << "New login, " << clientMgr.GetLoadedCount() << " clients and " << accountMgr.GetLoadedCount() << " accounts total" << std::endl; std::cout << "New login, " << clientMgr.GetLoadedCount() << " clients and " << accountMgr.GetLoadedCount() << " accounts total" << std::endl;
} }
void ServerApplication::hLogoutRequest(ClientPacket* const argPacket) { void ServerApplication::HandleLogoutRequest(ClientPacket* const argPacket) {
//get the account and client data //get the account and client data
AccountData* accountData = accountMgr.Get(argPacket->accountIndex); AccountData* accountData = accountMgr.Get(argPacket->accountIndex);
if (!accountData) { if (!accountData) {
@@ -144,7 +144,7 @@ void ServerApplication::hLogoutRequest(ClientPacket* const argPacket) {
std::cout << "New logout, " << clientMgr.GetLoadedCount() << " clients and " << accountMgr.GetLoadedCount() << " accounts total" << std::endl; std::cout << "New logout, " << clientMgr.GetLoadedCount() << " clients and " << accountMgr.GetLoadedCount() << " accounts total" << std::endl;
} }
void ServerApplication::hDisconnectRequest(ClientPacket* const argPacket) { void ServerApplication::HandleDisconnectRequest(ClientPacket* const argPacket) {
//get the client data //get the client data
ClientData* clientData = clientMgr.Get(argPacket->clientIndex); ClientData* clientData = clientMgr.Get(argPacket->clientIndex);
if (!clientData) { if (!clientData) {
@@ -170,3 +170,7 @@ void ServerApplication::hDisconnectRequest(ClientPacket* const argPacket) {
//finished this routine //finished this routine
std::cout << "New disconnection, " << clientMgr.GetLoadedCount() << " clients and " << accountMgr.GetLoadedCount() << " accounts total" << std::endl; std::cout << "New disconnection, " << clientMgr.GetLoadedCount() << " clients and " << accountMgr.GetLoadedCount() << " accounts total" << std::endl;
} }
void ServerApplication::HandleDisconnectForced(ClientPacket* const argPacket) {
//TODO: HandleDisconnectForced
}
@@ -25,10 +25,20 @@
#include <sstream> #include <sstream>
//------------------------- //-------------------------
//Queries //General data management
//------------------------- //-------------------------
void ServerApplication::hRegionRequest(RegionPacket* const argPacket) { //TODO: Queries
void ServerApplication::SaveServerState() {
//TODO: SaveServerState
}
//-------------------------
//Map management
//-------------------------
void ServerApplication::HandleRegionRequest(RegionPacket* const argPacket) {
//get the region object, send a rejection on error //get the region object, send a rejection on error
RoomData* room = roomMgr.Get(argPacket->roomIndex); RoomData* room = roomMgr.Get(argPacket->roomIndex);
if (!room) { if (!room) {
@@ -61,7 +71,7 @@ void ServerApplication::hRegionRequest(RegionPacket* const argPacket) {
network.SendTo(argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket)); network.SendTo(argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket));
} }
void ServerApplication::hQueryCharacterExists(CharacterPacket* const argPacket) { void ServerApplication::HandleCharacterExists(CharacterPacket* const argPacket) {
//respond with all character data //respond with all character data
CharacterPacket newPacket; CharacterPacket newPacket;
@@ -74,23 +84,3 @@ void ServerApplication::hQueryCharacterExists(CharacterPacket* const argPacket)
network.SendTo(argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket)); network.SendTo(argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket));
} }
} }
void ServerApplication::hQueryCharacterStats(CharacterPacket* const argPacket) {
//TODO: (9) empty
}
void ServerApplication::hQueryCharacterLocation(CharacterPacket* const argPacket) {
//TODO: (9) empty
}
void ServerApplication::hQueryMonsterExists(MonsterPacket* const argPacket) {
//TODO: (9) empty
}
void ServerApplication::hQueryMonsterStats(MonsterPacket* const argPacket) {
//TODO: (9) empty
}
void ServerApplication::hQueryMonsterLocation(MonsterPacket* const argPacket) {
//TODO: (9) empty
}
+38 -58
View File
@@ -128,6 +128,7 @@ void ServerApplication::Init(int argc, char* argv[]) {
//debug output //debug output
//------------------------- //-------------------------
//TODO: enable/disable these with a switch
#define DEBUG_OUTPUT_VAR(x) std::cout << "\t" << #x << ": " << x << std::endl; #define DEBUG_OUTPUT_VAR(x) std::cout << "\t" << #x << ": " << x << std::endl;
std::cout << "Internal sizes:" << std::endl; std::cout << "Internal sizes:" << std::endl;
@@ -194,8 +195,7 @@ void ServerApplication::Proc() {
void ServerApplication::Quit() { void ServerApplication::Quit() {
std::cout << "Shutting down" << std::endl; std::cout << "Shutting down" << std::endl;
//save the server state //TODO: save the server state
SaveServerState();
//close the managers //close the managers
accountMgr.UnloadAll(); accountMgr.UnloadAll();
@@ -214,111 +214,91 @@ void ServerApplication::Quit() {
} }
//------------------------- //-------------------------
//handle incoming traffic //direct incoming traffic
//------------------------- //-------------------------
void ServerApplication::HandlePacket(SerialPacket* const argPacket) { void ServerApplication::HandlePacket(SerialPacket* const argPacket) {
switch(argPacket->type) { switch(argPacket->type) {
//heartbeat system //heartbeat system
case SerialPacketType::PING: case SerialPacketType::PING:
hPing(static_cast<ServerPacket*>(argPacket)); HandlePing(static_cast<ServerPacket*>(argPacket));
break; break;
case SerialPacketType::PONG: case SerialPacketType::PONG:
hPong(static_cast<ServerPacket*>(argPacket)); HandlePong(static_cast<ServerPacket*>(argPacket));
break; break;
//client connections //client connections
case SerialPacketType::BROADCAST_REQUEST: case SerialPacketType::BROADCAST_REQUEST:
hBroadcastRequest(static_cast<ServerPacket*>(argPacket)); HandleBroadcastRequest(static_cast<ServerPacket*>(argPacket));
break; break;
case SerialPacketType::JOIN_REQUEST: case SerialPacketType::JOIN_REQUEST:
hJoinRequest(static_cast<ClientPacket*>(argPacket)); HandleJoinRequest(static_cast<ClientPacket*>(argPacket));
break; break;
case SerialPacketType::LOGIN_REQUEST: case SerialPacketType::LOGIN_REQUEST:
hLoginRequest(static_cast<ClientPacket*>(argPacket)); HandleLoginRequest(static_cast<ClientPacket*>(argPacket));
break; break;
//client disconnections //client disconnections
case SerialPacketType::LOGOUT_REQUEST: case SerialPacketType::LOGOUT_REQUEST:
hLogoutRequest(static_cast<ClientPacket*>(argPacket)); HandleLogoutRequest(static_cast<ClientPacket*>(argPacket));
break; break;
case SerialPacketType::DISCONNECT_REQUEST: case SerialPacketType::DISCONNECT_REQUEST:
hDisconnectRequest(static_cast<ClientPacket*>(argPacket)); HandleDisconnectRequest(static_cast<ClientPacket*>(argPacket));
break; break;
//server commands //server commands
case SerialPacketType::ADMIN_DISCONNECT_FORCED: // case SerialPacketType::DISCONNECT_FORCED:
hAdminDisconnectForced(static_cast<ClientPacket*>(argPacket)); // HandleDisconnectForced(static_cast<ClientPacket*>(argPacket));
break; // break;
case SerialPacketType::ADMIN_SHUTDOWN_REQUEST: case SerialPacketType::SHUTDOWN_REQUEST:
hAdminShutdownRequest(static_cast<ClientPacket*>(argPacket)); HandleShutdownRequest(static_cast<ClientPacket*>(argPacket));
break; break;
//data management & queries //data management & queries
case SerialPacketType::REGION_REQUEST: case SerialPacketType::REGION_REQUEST:
hRegionRequest(static_cast<RegionPacket*>(argPacket)); HandleRegionRequest(static_cast<RegionPacket*>(argPacket));
break; break;
case SerialPacketType::QUERY_CHARACTER_EXISTS: case SerialPacketType::QUERY_CHARACTER_EXISTS:
hQueryCharacterExists(static_cast<CharacterPacket*>(argPacket)); HandleCharacterExists(static_cast<CharacterPacket*>(argPacket));
break;
case SerialPacketType::QUERY_CHARACTER_STATS:
hQueryCharacterStats(static_cast<CharacterPacket*>(argPacket));
break;
case SerialPacketType::QUERY_CHARACTER_LOCATION:
hQueryCharacterLocation(static_cast<CharacterPacket*>(argPacket));
break;
case SerialPacketType::QUERY_MONSTER_EXISTS:
hQueryMonsterExists(static_cast<MonsterPacket*>(argPacket));
break;
case SerialPacketType::QUERY_MONSTER_STATS:
hQueryMonsterStats(static_cast<MonsterPacket*>(argPacket));
break;
case SerialPacketType::QUERY_MONSTER_LOCATION:
hQueryMonsterLocation(static_cast<MonsterPacket*>(argPacket));
break; break;
//character management //character management
case SerialPacketType::CHARACTER_CREATE: case SerialPacketType::CHARACTER_CREATE:
hCharacterCreate(static_cast<CharacterPacket*>(argPacket)); HandleCharacterCreate(static_cast<CharacterPacket*>(argPacket));
break; break;
case SerialPacketType::CHARACTER_DELETE: case SerialPacketType::CHARACTER_DELETE:
hCharacterDelete(static_cast<CharacterPacket*>(argPacket)); HandleCharacterDelete(static_cast<CharacterPacket*>(argPacket));
break; break;
case SerialPacketType::CHARACTER_LOAD: case SerialPacketType::CHARACTER_LOAD:
hCharacterLoad(static_cast<CharacterPacket*>(argPacket)); HandleCharacterLoad(static_cast<CharacterPacket*>(argPacket));
break; break;
case SerialPacketType::CHARACTER_UNLOAD: case SerialPacketType::CHARACTER_UNLOAD:
hCharacterUnload(static_cast<CharacterPacket*>(argPacket)); HandleCharacterUnload(static_cast<CharacterPacket*>(argPacket));
break; break;
/* case SerialPacketType::QUERY_CHARACTER_EXISTS:
//
break;
case SerialPacketType::QUERY_CHARACTER_STATS:
//
break;
case SerialPacketType::QUERY_CHARACTER_LOCATION:
//
break;
*/
//character movement //character movement
case SerialPacketType::CHARACTER_MOVEMENT: case SerialPacketType::CHARACTER_MOVEMENT:
hCharacterMovement(static_cast<CharacterPacket*>(argPacket)); HandleCharacterMovement(static_cast<CharacterPacket*>(argPacket));
break; break;
case SerialPacketType::CHARACTER_ATTACK: case SerialPacketType::CHARACTER_ATTACK:
hCharacterAttack(static_cast<CharacterPacket*>(argPacket)); HandleCharacterAttack(static_cast<CharacterPacket*>(argPacket));
break;
case SerialPacketType::CHARACTER_DAMAGE:
hCharacterDamage(static_cast<CharacterPacket*>(argPacket));
break;
//monster management
case SerialPacketType::MONSTER_DAMAGE:
hMonsterDamage(static_cast<MonsterPacket*>(argPacket));
break;
//chat
case SerialPacketType::TEXT_BROADCAST:
hTextBroadcast(static_cast<TextPacket*>(argPacket));
break;
case SerialPacketType::TEXT_SPEECH:
hTextSpeech(static_cast<TextPacket*>(argPacket));
break;
case SerialPacketType::TEXT_WHISPER:
hTextWhisper(static_cast<TextPacket*>(argPacket));
break; break;
/*
//enemy management
//TODO: enemy management
//TODO: text
*/
//handle errors //handle errors
default: { default: {
std::ostringstream msg; std::ostringstream msg;
+14 -10
View File
@@ -25,15 +25,23 @@
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
//-------------------------
//these should've come standard
//-------------------------
bool operator==(IPaddress lhs, IPaddress rhs) {
return lhs.host == rhs.host && lhs.port == rhs.port;
}
bool operator!=(IPaddress lhs, IPaddress rhs) {
return !(lhs == rhs);
}
//------------------------- //-------------------------
//server commands //server commands
//------------------------- //-------------------------
void ServerApplication::hAdminDisconnectForced(ClientPacket* const argPacket) { void ServerApplication::HandleShutdownRequest(ClientPacket* const argPacket) {
//TODO: (9) empty
}
void ServerApplication::hAdminShutdownRequest(ClientPacket* const argPacket) {
//get the account and client data //get the account and client data
AccountData* accountData = accountMgr.Get(argPacket->accountIndex); AccountData* accountData = accountMgr.Get(argPacket->accountIndex);
if (!accountData) { if (!accountData) {
@@ -76,7 +84,7 @@ void ServerApplication::hAdminShutdownRequest(ClientPacket* const argPacket) {
//disconnect all clients //disconnect all clients
TextPacket newPacket; TextPacket newPacket;
newPacket.type = SerialPacketType::ADMIN_DISCONNECT_FORCED; newPacket.type = SerialPacketType::DISCONNECT_FORCED;
strncpy(newPacket.text, "Server shutdown", PACKET_STRING_SIZE); strncpy(newPacket.text, "Server shutdown", PACKET_STRING_SIZE);
PumpPacket(&newPacket); PumpPacket(&newPacket);
@@ -84,10 +92,6 @@ void ServerApplication::hAdminShutdownRequest(ClientPacket* const argPacket) {
std::cout << "Shutdown signal accepted" << std::endl; std::cout << "Shutdown signal accepted" << std::endl;
} }
void ServerApplication::SaveServerState() {
//TODO: (9) empty
}
//------------------------- //-------------------------
//full unload methods //full unload methods
//------------------------- //-------------------------
-26
View File
@@ -1,26 +0,0 @@
/* Copyright: (c) Kayne Ruse 2013-2015
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "server_application.hpp"
void ServerApplication::hMonsterDamage(MonsterPacket* const argPacket) {
//TODO: (9) empty
}
@@ -27,10 +27,12 @@
static int create(lua_State* L) { static int create(lua_State* L) {
WaypointManager* mgr = static_cast<WaypointManager*>(lua_touserdata(L, 1)); WaypointManager* mgr = static_cast<WaypointManager*>(lua_touserdata(L, 1));
//TODO
} }
static int unload(lua_State* L) { static int unload(lua_State* L) {
WaypointManager* mgr = static_cast<WaypointManager*>(lua_touserdata(L, 1)); WaypointManager* mgr = static_cast<WaypointManager*>(lua_touserdata(L, 1));
//TODO
} }
static int getWaypoint(lua_State* L) { static int getWaypoint(lua_State* L) {
+12 -18
View File
@@ -7,21 +7,15 @@ TODO: Account passwords (list)
* ... * ...
* salts & hashes * salts & hashes
TODO: Features TODO: Split config.cfg in two, one for the server and the client
* Make sure login errors are sent to the client TODO: Add the "home" parameter to the server's config file
* Split config.cfg in two, one for the server and the client TODO: Waypoints, with positions and trigger zones (collision areas) for doors, monster spawns, etc.
* Add the "home" parameter to the server's config file TODO: Fix shoddy movement
* Waypoints, with positions and trigger zones (collision areas) for doors, monster spawns, etc. TODO: Periodic mass server saves
* Fix shoddy movement TODO: Remove the big "Shut Down" button (currently broken...)
* Periodic mass server saves TODO: Make a way for the server owner to control the server directly
* Remove the big "Shut Down" button (currently broken...) TODO: The TileSheet class should implement the surface itself
* Make a way for the server owner to control the server directly TODO: Time delay for requesting region packets
* The TileSheet class should implement the surface itself TODO: A proper logging system
* Time delay for requesting region packets TODO: Fix the const-ness of accessors
* A proper logging system TODO: Add a screenshot of the game to README.md
* Fix the const-ness of accessors
* Add a screenshot of the game to README.md
* joystick/gamepad support
* add the tilesheet to the map system
* ping/delay displayed in the lobby
* login screen prompting for username & password