Compare commits
69 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f82b0a8843 | |||
| 210bccbe0d | |||
| 68429806d1 | |||
| a8cf0a6947 | |||
| 822d0636cc | |||
| 164a3e18d9 | |||
| 3498b5d154 | |||
| 96c10da527 | |||
| 3856b3cdd2 | |||
| 661f6db82c | |||
| 99b35483f8 | |||
| 102ba18b7b | |||
| 07faf1b96b | |||
| 1d70e271b6 | |||
| 0bf5ccee4d | |||
| 35e7d0cf61 | |||
| 27fd810cfd | |||
| 8903b1e28d | |||
| c1ace69e19 | |||
| 5c404c572e | |||
| 878d502b8b | |||
| 2a1ee4acbf | |||
| 0e149acc62 | |||
| 63e4394583 | |||
| 7aeabf0d14 | |||
| 9d5a668045 | |||
| 0efb541074 | |||
| 4ae58550b5 | |||
| d82e3a8b79 | |||
| 954213f1ff | |||
| d2bb3575fc | |||
| ca6afb72ad | |||
| 670ab22e96 | |||
| 4d71d4cc40 | |||
| 81b3769188 | |||
| c3c6d42a80 | |||
| 3d8ee25ae7 | |||
| decc77e21c | |||
| 501b1e9814 | |||
| 01502372c9 | |||
| a8c309ec9d | |||
| 41d6314beb | |||
| 74ed93ddc7 | |||
| 18a7143926 | |||
| bd68af5875 | |||
| b8806cc209 | |||
| edcb6f05ce | |||
| cb63c9b07c | |||
| a00ddb3142 | |||
| 3431d323e5 | |||
| 84c4dd0497 | |||
| 3e6a05307e | |||
| c45bda645b | |||
| 1210d2d24f | |||
| 894b53e760 | |||
| 4630b7e403 | |||
| 067bf40be7 | |||
| d8045ae339 | |||
| eff23352aa | |||
| 46df0f17b7 | |||
| ddedc06e47 | |||
| 6a999a8a72 | |||
| 8a97cb8c2c | |||
| e011e6bdc5 | |||
| a106134dd1 | |||
| a538cf73d5 | |||
| b273b4c04a | |||
| 248d142c2b | |||
| 2cc7260552 |
@@ -9,6 +9,9 @@
|
|||||||
Release/
|
Release/
|
||||||
Debug/
|
Debug/
|
||||||
Out/
|
Out/
|
||||||
|
release/
|
||||||
|
debug/
|
||||||
|
out/
|
||||||
|
|
||||||
#Project generated files
|
#Project generated files
|
||||||
*.db
|
*.db
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
## Outline
|
## Outline
|
||||||
|
|
||||||
Tortuga is a 2D multiplayer JRPG featuring permadeath, with an emphasis on multiplayer cooperation, exploration and customization. The game runs on customizable public and private servers.
|
Tortuga is a 2D MMORPG featuring permadeath, with an emphasis on multiplayer cooperation, exploration and customization. The game runs on customizable public and private servers.
|
||||||
|
|
||||||
This game is inspired by classic 2D RPGs (Final Fantasy, The Legend of Zelda), as well as more modern sandboxes amd MMOs (Minecraft, EVE Online). This project is currently independently created and funded, with the goal of creating a game that will engage the players and inspire a large community.
|
This game is inspired by classic 2D RPGs (Final Fantasy, The Legend of Zelda), as well as more modern sandboxes and MMOs (Minecraft, EVE Online). This project is currently independently created and funded, with the goal of creating a game that will engage the players and inspire a large community.
|
||||||
|
|
||||||
## Releases
|
## Releases
|
||||||
|
|
||||||
The most recent stable build for Windows can be found [here](https://dl.dropboxusercontent.com/u/46669050/Tortuga.rar).
|
* The most recent stable build for Windows can be found [here](https://dl.dropboxusercontent.com/u/46669050/Tortuga-win.rar).
|
||||||
|
* The most recent stable build for Linux can be found [here](https://dl.dropboxusercontent.com/u/46669050/Tortuga-linux.tar).
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
@@ -16,13 +17,14 @@ The most recent stable build for Windows can be found [here](https://dl.dropboxu
|
|||||||
## External Dependencies
|
## External Dependencies
|
||||||
|
|
||||||
* [SDL 1.2](http://www.libsdl.org/) - Simple DirectMedia Layer API
|
* [SDL 1.2](http://www.libsdl.org/) - Simple DirectMedia Layer API
|
||||||
* [SDL_net 1.2](http://www.libsdl.org/projects/SDL_net/) - SDL's networking extension
|
* [SDL_net 2.0](http://www.libsdl.org/projects/SDL_net/) - SDL's networking extension
|
||||||
* [lua 5.2](http://www.lua.org/) - The lua programming language
|
* [lua 5.2](http://www.lua.org/) - The lua programming language
|
||||||
* [SQLite3](http://www.sqlite.org/) - A lightweight SQL database engine
|
* [SQLite3](http://www.sqlite.org/) - A lightweight SQL database engine
|
||||||
|
|
||||||
## Tools
|
## Tools
|
||||||
|
|
||||||
* [WinRAR](http://www.rarlab.com/) - The best compression tool available IMO; only needed for distribution
|
* [WinRAR](http://www.rarlab.com/) - The best compression tool available IMO; only needed for Windows distribution
|
||||||
|
* [Dropbox](https://www.dropbox.com/) - For hosting and distribution
|
||||||
|
|
||||||
## Copyright
|
## Copyright
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//Scene headers
|
//Scene headers
|
||||||
@@ -57,7 +58,9 @@ void ClientApplication::Init(int argc, char* argv[]) {
|
|||||||
|
|
||||||
//initialize SDL
|
//initialize SDL
|
||||||
if (SDL_Init(SDL_INIT_VIDEO)) {
|
if (SDL_Init(SDL_INIT_VIDEO)) {
|
||||||
throw(std::runtime_error("Failed to initialize SDL"));
|
std::ostringstream os;
|
||||||
|
os << "Failed to initialize SDL: " << SDL_GetError();
|
||||||
|
throw(std::runtime_error(os.str()));
|
||||||
}
|
}
|
||||||
std::cout << "Initialized SDL" << std::endl;
|
std::cout << "Initialized SDL" << std::endl;
|
||||||
|
|
||||||
@@ -169,6 +172,7 @@ void ClientApplication::Quit() {
|
|||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
void ClientApplication::LoadScene(SceneList sceneIndex) {
|
void ClientApplication::LoadScene(SceneList sceneIndex) {
|
||||||
|
//BUG: #16 Resources are being reloaded between scenes
|
||||||
UnloadScene();
|
UnloadScene();
|
||||||
switch(sceneIndex) {
|
switch(sceneIndex) {
|
||||||
//add scene creation calls here
|
//add scene creation calls here
|
||||||
|
|||||||
@@ -30,8 +30,3 @@ $(OUTDIR):
|
|||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o *.a *.exe
|
|
||||||
|
|
||||||
rebuild: clean all
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
#include "config_utility.hpp"
|
#include "config_utility.hpp"
|
||||||
|
|
||||||
void BaseMonster::CorrectSprite() {
|
void BaseMonster::CorrectSprite() {
|
||||||
//TODO: (9) empty
|
//TODO: (9) BaseMonster::CorrectSprite()
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string BaseMonster::SetHandle(std::string s) {
|
std::string BaseMonster::SetHandle(std::string s) {
|
||||||
|
|||||||
@@ -30,8 +30,3 @@ $(OUTDIR):
|
|||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o *.a *.exe
|
|
||||||
|
|
||||||
rebuild: clean all
|
|
||||||
|
|||||||
@@ -30,8 +30,3 @@ $(OUTDIR):
|
|||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o *.a *.exe
|
|
||||||
|
|
||||||
rebuild: clean all
|
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ protected:
|
|||||||
void UpdateMap();
|
void UpdateMap();
|
||||||
|
|
||||||
//character management
|
//character management
|
||||||
|
void hCharacterUpdate(CharacterPacket* const);
|
||||||
void hCharacterCreate(CharacterPacket* const);
|
void hCharacterCreate(CharacterPacket* const);
|
||||||
void hCharacterDelete(CharacterPacket* const);
|
void hCharacterDelete(CharacterPacket* const);
|
||||||
void hQueryCharacterExists(CharacterPacket* const);
|
void hQueryCharacterExists(CharacterPacket* const);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include "channels.hpp"
|
#include "channels.hpp"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@@ -35,6 +36,24 @@
|
|||||||
//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::hCharacterUpdate(CharacterPacket* const argPacket) {
|
||||||
|
//TODO: (1) Authentication
|
||||||
|
//NOTE: applies to the local character too
|
||||||
|
|
||||||
|
//check that this character exists
|
||||||
|
std::map<int, BaseCharacter>::iterator characterIt = characterMap.find(argPacket->characterIndex);
|
||||||
|
if (characterIt != characterMap.end()) {
|
||||||
|
//update the origin and motion, if there's a difference
|
||||||
|
if (characterIt->second.GetOrigin() != argPacket->origin) {
|
||||||
|
characterIt->second.SetOrigin(argPacket->origin);
|
||||||
|
}
|
||||||
|
if (characterIt->second.GetMotion() != argPacket->motion) {
|
||||||
|
characterIt->second.SetMotion(argPacket->motion);
|
||||||
|
characterIt->second.CorrectSprite(); //only correct the sprite if the motion changes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void World::hCharacterCreate(CharacterPacket* const argPacket) {
|
void World::hCharacterCreate(CharacterPacket* const argPacket) {
|
||||||
//prevent double message
|
//prevent double message
|
||||||
if (characterMap.find(argPacket->characterIndex) != characterMap.end()) {
|
if (characterMap.find(argPacket->characterIndex) != characterMap.end()) {
|
||||||
@@ -49,25 +68,35 @@ void World::hCharacterCreate(CharacterPacket* const argPacket) {
|
|||||||
BaseCharacter* character = &characterMap[argPacket->characterIndex];
|
BaseCharacter* character = &characterMap[argPacket->characterIndex];
|
||||||
|
|
||||||
//fill the character's info
|
//fill the character's info
|
||||||
character->SetOrigin(argPacket->origin);
|
|
||||||
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->SetHandle(argPacket->handle);
|
character->SetHandle(argPacket->handle);
|
||||||
character->SetAvatar(argPacket->avatar);
|
character->SetAvatar(argPacket->avatar);
|
||||||
character->SetOwner(argPacket->accountIndex);
|
character->SetOwner(argPacket->accountIndex);
|
||||||
|
character->SetOrigin(argPacket->origin);
|
||||||
|
character->SetMotion(argPacket->motion);
|
||||||
|
character->SetBounds(argPacket->bounds);
|
||||||
|
|
||||||
character->CorrectSprite();
|
character->CorrectSprite();
|
||||||
|
|
||||||
//check for this player's character
|
//check for this player's character
|
||||||
if (character->GetOwner() == accountIndex) {
|
if (character->GetOwner() == accountIndex) {
|
||||||
localCharacter = static_cast<LocalCharacter*>(character);
|
localCharacter = static_cast<LocalCharacter*>(character);
|
||||||
|
|
||||||
//focus the camera on this character
|
//focus the camera on this character's sprite
|
||||||
camera.marginX = (camera.width / 2 - localCharacter->GetSprite()->GetImage()->GetClipW() / 2);
|
camera.marginX = (camera.width / 2 - localCharacter->GetSprite()->GetImage()->GetClipW() / 2);
|
||||||
camera.marginY = (camera.height/ 2 - localCharacter->GetSprite()->GetImage()->GetClipH() / 2);
|
camera.marginY = (camera.height/ 2 - localCharacter->GetSprite()->GetImage()->GetClipH() / 2);
|
||||||
|
|
||||||
//focus on this character's info
|
//focus on this character's info
|
||||||
characterIndex = argPacket->characterIndex;
|
characterIndex = argPacket->characterIndex;
|
||||||
roomIndex = argPacket->roomIndex;
|
roomIndex = argPacket->roomIndex;
|
||||||
|
|
||||||
|
//query the world state (room)
|
||||||
|
CharacterPacket newPacket;
|
||||||
|
memset(&newPacket, 0, MAX_PACKET_SIZE);
|
||||||
|
newPacket.type = SerialPacketType::QUERY_CHARACTER_EXISTS;
|
||||||
|
newPacket.roomIndex = roomIndex;
|
||||||
|
network.SendTo(Channels::SERVER, &newPacket);
|
||||||
|
newPacket.type = SerialPacketType::QUERY_MONSTER_EXISTS;
|
||||||
|
network.SendTo(Channels::SERVER, &newPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
//debug
|
//debug
|
||||||
@@ -91,10 +120,14 @@ void World::hCharacterDelete(CharacterPacket* const argPacket) {
|
|||||||
|
|
||||||
//clear the room
|
//clear the room
|
||||||
roomIndex = -1;
|
roomIndex = -1;
|
||||||
|
regionPager.UnloadAll();
|
||||||
|
characterMap.clear();
|
||||||
|
monsterMap.clear();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//remove this character
|
||||||
|
characterMap.erase(characterIt);
|
||||||
}
|
}
|
||||||
|
|
||||||
//remove this character
|
|
||||||
characterMap.erase(characterIt);
|
|
||||||
|
|
||||||
//debug
|
//debug
|
||||||
std::cout << "Character Delete, total: " << characterMap.size() << std::endl;
|
std::cout << "Character Delete, total: " << characterMap.size() << std::endl;
|
||||||
@@ -102,9 +135,9 @@ void World::hCharacterDelete(CharacterPacket* const argPacket) {
|
|||||||
|
|
||||||
void World::hQueryCharacterExists(CharacterPacket* const argPacket) {
|
void World::hQueryCharacterExists(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;
|
||||||
}
|
// }
|
||||||
|
|
||||||
//ignore characters in a different room (sub-optimal)
|
//ignore characters in a different room (sub-optimal)
|
||||||
if (argPacket->roomIndex != roomIndex) {
|
if (argPacket->roomIndex != roomIndex) {
|
||||||
@@ -128,11 +161,11 @@ void World::hQueryCharacterExists(CharacterPacket* const argPacket) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void World::hQueryCharacterStats(CharacterPacket* const argPacket) {
|
void World::hQueryCharacterStats(CharacterPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) World::hQueryCharacterStats()
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::hQueryCharacterLocation(CharacterPacket* const argPacket) {
|
void World::hQueryCharacterLocation(CharacterPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) World::hQueryCharacterLocation()
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::hCharacterMovement(CharacterPacket* const argPacket) {
|
void World::hCharacterMovement(CharacterPacket* const argPacket) {
|
||||||
@@ -152,11 +185,11 @@ void World::hCharacterMovement(CharacterPacket* const argPacket) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void World::hCharacterAttack(CharacterPacket* const argPacket) {
|
void World::hCharacterAttack(CharacterPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) World::hCharacterAttack()
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::hCharacterDamage(CharacterPacket* const argPacket) {
|
void World::hCharacterDamage(CharacterPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) World::hCharacterDamage()
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|||||||
@@ -26,14 +26,14 @@
|
|||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
void World::hTextBroadcast(TextPacket* const argPacket) {
|
void World::hTextBroadcast(TextPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) World::hTextBroadcast()
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::hTextSpeech(TextPacket* const argPacket) {
|
void World::hTextSpeech(TextPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) World::hTextSpeech()
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::hTextWhisper(TextPacket* const argPacket) {
|
void World::hTextWhisper(TextPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) World::hTextWhisper()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -91,10 +91,9 @@ void World::SendDisconnectRequest() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void World::SendAdminDisconnectForced() {
|
void World::SendAdminDisconnectForced() {
|
||||||
//TODO: (9) empty
|
//TODO: (9) World::SendAdminDisconnectForced()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void World::SendAdminShutdownRequest() {
|
void World::SendAdminShutdownRequest() {
|
||||||
ClientPacket newPacket;
|
ClientPacket newPacket;
|
||||||
|
|
||||||
|
|||||||
@@ -22,11 +22,12 @@
|
|||||||
#include "world.hpp"
|
#include "world.hpp"
|
||||||
|
|
||||||
#include "channels.hpp"
|
#include "channels.hpp"
|
||||||
|
|
||||||
#include "terminal_error.hpp"
|
#include "terminal_error.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
@@ -60,7 +61,7 @@ World::World(int* const argClientIndex, int* const argAccountIndex):
|
|||||||
shutDownButton.SetText("Shut Down");
|
shutDownButton.SetText("Shut Down");
|
||||||
|
|
||||||
//load the tilesheet
|
//load the tilesheet
|
||||||
//TODO: (1) Tile size and tile sheet should be loaded elsewhere
|
//TODO: (2) Tile size and tile sheet should be loaded elsewhere
|
||||||
tileSheet.Load(config["dir.tilesets"] + "overworld.bmp", 32, 32);
|
tileSheet.Load(config["dir.tilesets"] + "overworld.bmp", 32, 32);
|
||||||
|
|
||||||
//Send the character data
|
//Send the character data
|
||||||
@@ -71,13 +72,6 @@ World::World(int* const argClientIndex, int* const argAccountIndex):
|
|||||||
newPacket.accountIndex = accountIndex;
|
newPacket.accountIndex = accountIndex;
|
||||||
network.SendTo(Channels::SERVER, &newPacket);
|
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
|
//set the camera's values
|
||||||
camera.width = GetScreen()->w;
|
camera.width = GetScreen()->w;
|
||||||
camera.height = GetScreen()->h;
|
camera.height = GetScreen()->h;
|
||||||
@@ -132,8 +126,16 @@ void World::Update() {
|
|||||||
it.second.Update();
|
it.second.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
//update the map
|
try {
|
||||||
UpdateMap();
|
//update the map
|
||||||
|
UpdateMap();
|
||||||
|
}
|
||||||
|
catch(terminal_error& e) {
|
||||||
|
throw(e);
|
||||||
|
}
|
||||||
|
catch(std::exception& e) {
|
||||||
|
std::cerr << "UpdateMap Error: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
//skip the rest without a local character
|
//skip the rest without a local character
|
||||||
if (!localCharacter) {
|
if (!localCharacter) {
|
||||||
@@ -169,11 +171,16 @@ void World::Render(SDL_Surface* const screen) {
|
|||||||
//draw the map
|
//draw the map
|
||||||
for (std::list<Region>::iterator it = regionPager.GetContainer()->begin(); it != regionPager.GetContainer()->end(); it++) {
|
for (std::list<Region>::iterator it = regionPager.GetContainer()->begin(); it != regionPager.GetContainer()->end(); it++) {
|
||||||
tileSheet.DrawRegionTo(screen, &(*it), camera.x, camera.y);
|
tileSheet.DrawRegionTo(screen, &(*it), camera.x, camera.y);
|
||||||
|
|
||||||
|
//debugging
|
||||||
|
// std::ostringstream msg;
|
||||||
|
// msg << it->GetX() << ", " << it->GetY();
|
||||||
|
// font.DrawStringTo(msg.str(), screen, it->GetX() * tileSheet.GetImage()->GetClipW() - camera.x, it->GetY() * tileSheet.GetImage()->GetClipH() - camera.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
//draw the entities
|
//draw the entities
|
||||||
for (auto& it : characterMap) {
|
for (auto& it : characterMap) {
|
||||||
//TODO: (1) depth ordering
|
//BUG: #29 Characters (and other entities) are drawn out of order
|
||||||
it.second.DrawTo(screen, camera.x, camera.y);
|
it.second.DrawTo(screen, camera.x, camera.y);
|
||||||
}
|
}
|
||||||
for (auto& it : monsterMap) {
|
for (auto& it : monsterMap) {
|
||||||
@@ -221,7 +228,7 @@ void World::KeyDown(SDL_KeyboardEvent const& key) {
|
|||||||
//hotkeys
|
//hotkeys
|
||||||
switch(key.keysym.sym) {
|
switch(key.keysym.sym) {
|
||||||
case SDLK_ESCAPE:
|
case SDLK_ESCAPE:
|
||||||
//TODO: (1) the escape key should actually control menus and stuff
|
//TODO: (3) the escape key should actually control menus and stuff
|
||||||
SendLogoutRequest();
|
SendLogoutRequest();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -335,6 +342,9 @@ void World::HandlePacket(SerialPacket* const argPacket) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
//character management
|
//character management
|
||||||
|
case SerialPacketType::CHARACTER_UPDATE:
|
||||||
|
hCharacterUpdate(static_cast<CharacterPacket*>(argPacket));
|
||||||
|
break;
|
||||||
case SerialPacketType::CHARACTER_CREATE:
|
case SerialPacketType::CHARACTER_CREATE:
|
||||||
hCharacterCreate(static_cast<CharacterPacket*>(argPacket));
|
hCharacterCreate(static_cast<CharacterPacket*>(argPacket));
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -23,6 +23,24 @@
|
|||||||
|
|
||||||
#include "channels.hpp"
|
#include "channels.hpp"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//static functions
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
static int regionChecksum(Region* const region) {
|
||||||
|
int sum = 0;
|
||||||
|
for(int i = 0; i < REGION_WIDTH; i++) {
|
||||||
|
for (int j = 0; j < REGION_HEIGHT; j++) {
|
||||||
|
for (int k = 0; k < REGION_DEPTH; k++) {
|
||||||
|
sum += region->GetTile(i, j, k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//map management
|
//map management
|
||||||
//-------------------------
|
//-------------------------
|
||||||
@@ -40,6 +58,13 @@ void World::SendRegionRequest(int roomIndex, int x, int y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void World::hRegionContent(RegionPacket* const argPacket) {
|
void World::hRegionContent(RegionPacket* const argPacket) {
|
||||||
|
//checksum
|
||||||
|
if (regionChecksum(argPacket->region) == 0) {
|
||||||
|
std::ostringstream msg;
|
||||||
|
msg << "Received region checksum failed: " << argPacket->x << ", " << argPacket->y;
|
||||||
|
throw(std::runtime_error(msg.str()));
|
||||||
|
}
|
||||||
|
|
||||||
//replace existing regions
|
//replace existing regions
|
||||||
regionPager.UnloadIf([&](Region const& region) -> bool {
|
regionPager.UnloadIf([&](Region const& region) -> bool {
|
||||||
return region.GetX() == argPacket->x && region.GetY() == argPacket->y;
|
return region.GetX() == argPacket->x && region.GetY() == argPacket->y;
|
||||||
@@ -71,9 +96,23 @@ void World::UpdateMap() {
|
|||||||
//request empty regions within this zone
|
//request empty regions within this zone
|
||||||
for (int i = xStart; i <= xEnd; i += REGION_WIDTH) {
|
for (int i = xStart; i <= xEnd; i += REGION_WIDTH) {
|
||||||
for (int j = yStart; j <= yEnd; j += REGION_HEIGHT) {
|
for (int j = yStart; j <= yEnd; j += REGION_HEIGHT) {
|
||||||
if (!regionPager.FindRegion(i, j)) {
|
Region* region = regionPager.FindRegion(i, j);
|
||||||
|
if (!region) {
|
||||||
|
//request absent region
|
||||||
SendRegionRequest(roomIndex, i, j);
|
SendRegionRequest(roomIndex, i, j);
|
||||||
}
|
}
|
||||||
|
else if (regionChecksum(region) == 0) {
|
||||||
|
//checksum failed
|
||||||
|
//NOTE: this patches bug #45, but does not resolve it
|
||||||
|
regionPager.UnloadIf([region](Region const& ref) -> bool {
|
||||||
|
//remove the erroneous region
|
||||||
|
return region == &ref;
|
||||||
|
});
|
||||||
|
SendRegionRequest(roomIndex, i, j);
|
||||||
|
std::ostringstream msg;
|
||||||
|
msg << "Existing region checksum failed: " << roomIndex << ", " << i << ", " << j;
|
||||||
|
throw(std::runtime_error(msg.str()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,11 +99,11 @@ void World::hQueryMonsterExists(MonsterPacket* const argPacket) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void World::hQueryMonsterStats(MonsterPacket* const argPacket) {
|
void World::hQueryMonsterStats(MonsterPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) World::hQueryMonsterStats()
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::hQueryMonsterLocation(MonsterPacket* const argPacket) {
|
void World::hQueryMonsterLocation(MonsterPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) World::hQueryMonsterLocation()
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::hMonsterMovement(MonsterPacket* const argPacket) {
|
void World::hMonsterMovement(MonsterPacket* const argPacket) {
|
||||||
@@ -118,9 +118,9 @@ void World::hMonsterMovement(MonsterPacket* const argPacket) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void World::hMonsterAttack(MonsterPacket* const argPacket) {
|
void World::hMonsterAttack(MonsterPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) World::hMonsterAttack()
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::hMonsterDamage(MonsterPacket* const argPacket) {
|
void World::hMonsterDamage(MonsterPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) World::hMonsterDamage()
|
||||||
}
|
}
|
||||||
+7
-1
@@ -1,5 +1,5 @@
|
|||||||
#include directories
|
#include directories
|
||||||
INCLUDES+=. client_utilities entities gameplay_scenes menu_scenes ../common/debugging ../common/gameplay ../common/graphics ../common/map ../common/network ../common/network/packet_types ../common/ui ../common/utilities
|
INCLUDES+=SDL . client_utilities entities gameplay_scenes menu_scenes ../common/debugging ../common/gameplay ../common/graphics ../common/map ../common/network ../common/network/packet_types ../common/ui ../common/utilities
|
||||||
|
|
||||||
#libraries
|
#libraries
|
||||||
#the order of the $(LIBS) is important, at least for MinGW
|
#the order of the $(LIBS) is important, at least for MinGW
|
||||||
@@ -45,6 +45,12 @@ $(OBJDIR)/%.o: %.cpp
|
|||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
$(RM) *.o *.a *.exe
|
$(RM) *.o *.a *.exe
|
||||||
|
else ifeq ($(shell uname), Linux)
|
||||||
|
find . -type f -name *.o -exec rm -f -r -v {} \;
|
||||||
|
find . -type f -name *.a -exec rm -f -r -v {} \;
|
||||||
|
rm -f -v out/client out/server
|
||||||
|
endif
|
||||||
|
|
||||||
rebuild: clean all
|
rebuild: clean all
|
||||||
|
|||||||
@@ -107,7 +107,8 @@ void LobbyMenu::Render(SDL_Surface* const screen) {
|
|||||||
join.DrawTo(screen);
|
join.DrawTo(screen);
|
||||||
back.DrawTo(screen);
|
back.DrawTo(screen);
|
||||||
|
|
||||||
//TODO: (1) draw headers for the server list
|
//TODO: (3) draw headers for the server list
|
||||||
|
//TODO: (3) ping/delay displayed in 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]) {
|
||||||
@@ -252,11 +253,11 @@ void LobbyMenu::HandleLoginResponse(ClientPacket* const argPacket) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LobbyMenu::HandleJoinRejection(TextPacket* const argPacket) {
|
void LobbyMenu::HandleJoinRejection(TextPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) LobbyMenu::HandleJoinRejection()
|
||||||
}
|
}
|
||||||
|
|
||||||
void LobbyMenu::HandleLoginRejection(TextPacket* const argPacket) {
|
void LobbyMenu::HandleLoginRejection(TextPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) LobbyMenu::HandleLoginRejection
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|||||||
@@ -30,8 +30,3 @@ $(OUTDIR):
|
|||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o *.a *.exe
|
|
||||||
|
|
||||||
rebuild: clean all
|
|
||||||
|
|||||||
@@ -30,8 +30,3 @@ $(OUTDIR):
|
|||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o *.a *.exe
|
|
||||||
|
|
||||||
rebuild: clean all
|
|
||||||
|
|||||||
@@ -30,8 +30,3 @@ $(OUTDIR):
|
|||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o *.a *.exe
|
|
||||||
|
|
||||||
rebuild: clean all
|
|
||||||
|
|||||||
@@ -30,8 +30,3 @@ $(OUTDIR):
|
|||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o *.a *.exe
|
|
||||||
|
|
||||||
rebuild: clean all
|
|
||||||
|
|||||||
@@ -6,8 +6,3 @@ all:
|
|||||||
$(MAKE) -C network
|
$(MAKE) -C network
|
||||||
$(MAKE) -C ui
|
$(MAKE) -C ui
|
||||||
$(MAKE) -C utilities
|
$(MAKE) -C utilities
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o *.a *.exe
|
|
||||||
|
|
||||||
rebuild: clean all
|
|
||||||
|
|||||||
@@ -30,8 +30,3 @@ $(OUTDIR):
|
|||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o *.a *.exe
|
|
||||||
|
|
||||||
rebuild: clean all
|
|
||||||
|
|||||||
@@ -1,55 +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 "map_system_api.hpp"
|
|
||||||
|
|
||||||
//all map API headers
|
|
||||||
#include "region_api.hpp"
|
|
||||||
#include "region_pager_api.hpp"
|
|
||||||
|
|
||||||
//useful "globals"
|
|
||||||
//...
|
|
||||||
|
|
||||||
//This mimics linit.c to create a nested collection of all map modules.
|
|
||||||
static const luaL_Reg funcs[] = {
|
|
||||||
{nullptr, nullptr}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const luaL_Reg libs[] = {
|
|
||||||
{"Region", openRegionAPI},
|
|
||||||
{"RegionPager", openRegionPagerAPI},
|
|
||||||
{nullptr, nullptr}
|
|
||||||
};
|
|
||||||
|
|
||||||
int openMapSystemAPI(lua_State* L) {
|
|
||||||
//create the table
|
|
||||||
luaL_newlibtable(L, libs);
|
|
||||||
|
|
||||||
//push the "global" functions
|
|
||||||
luaL_setfuncs(L, funcs, 0);
|
|
||||||
|
|
||||||
//push the substable
|
|
||||||
for (const luaL_Reg* lib = libs; lib->func; lib++) {
|
|
||||||
lib->func(L);
|
|
||||||
lua_setfield(L, -2, lib->name);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
#include "lua.hpp"
|
#include "lua.hpp"
|
||||||
|
|
||||||
#define TORTUGA_REGION_NAME "region"
|
#define TORTUGA_REGION_API "region"
|
||||||
LUAMOD_API int openRegionAPI(lua_State* L);
|
LUAMOD_API int openRegionAPI(lua_State* L);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include "region.hpp"
|
#include "region.hpp"
|
||||||
|
|
||||||
//DOCS: These glue functions simply wrap RegionPagerLua's methods
|
//DOCS: These glue functions simply wrap RegionPagerLua's methods
|
||||||
|
//NOTE: zero indexing is used here, but not in the region API
|
||||||
|
|
||||||
static int setTile(lua_State* L) {
|
static int setTile(lua_State* L) {
|
||||||
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
|
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
#include "lua.hpp"
|
#include "lua.hpp"
|
||||||
|
|
||||||
#define TORTUGA_REGION_PAGER_NAME "region_pager"
|
#define TORTUGA_REGION_PAGER_API "region_pager"
|
||||||
LUAMOD_API int openRegionPagerAPI(lua_State* L);
|
LUAMOD_API int openRegionPagerAPI(lua_State* L);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ Region* RegionPagerBase::FindRegion(int x, int y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Region* RegionPagerBase::PushRegion(Region* const ptr) {
|
Region* RegionPagerBase::PushRegion(Region* const ptr) {
|
||||||
|
//BUG: #45 Some regions are occasionally losing their tile data
|
||||||
regionList.push_front(*ptr);
|
regionList.push_front(*ptr);
|
||||||
return ®ionList.front();
|
return ®ionList.front();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,8 +31,3 @@ $(OUTDIR):
|
|||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o *.a *.exe
|
|
||||||
|
|
||||||
rebuild: clean all
|
|
||||||
|
|||||||
@@ -36,11 +36,18 @@ void serializeCharacter(void* buffer, CharacterPacket* packet) {
|
|||||||
|
|
||||||
//location
|
//location
|
||||||
serialCopy(&buffer, &packet->roomIndex, sizeof(int));
|
serialCopy(&buffer, &packet->roomIndex, sizeof(int));
|
||||||
|
|
||||||
serialCopy(&buffer, &packet->origin.x, sizeof(double));
|
serialCopy(&buffer, &packet->origin.x, sizeof(double));
|
||||||
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));
|
||||||
|
|
||||||
|
serialCopy(&buffer, &packet->bounds.x, sizeof(int));
|
||||||
|
serialCopy(&buffer, &packet->bounds.y, sizeof(int));
|
||||||
|
serialCopy(&buffer, &packet->bounds.w, sizeof(int));
|
||||||
|
serialCopy(&buffer, &packet->bounds.h, sizeof(int));
|
||||||
|
|
||||||
//gameplay components: equipment, items, buffs, debuffs...
|
//gameplay components: equipment, items, buffs, debuffs...
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,10 +64,17 @@ void deserializeCharacter(void* buffer, CharacterPacket* packet) {
|
|||||||
|
|
||||||
//location
|
//location
|
||||||
deserialCopy(&buffer, &packet->roomIndex, sizeof(int));
|
deserialCopy(&buffer, &packet->roomIndex, sizeof(int));
|
||||||
|
|
||||||
deserialCopy(&buffer, &packet->origin.x, sizeof(double));
|
deserialCopy(&buffer, &packet->origin.x, sizeof(double));
|
||||||
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));
|
||||||
|
|
||||||
|
deserialCopy(&buffer, &packet->bounds.x, sizeof(int));
|
||||||
|
deserialCopy(&buffer, &packet->bounds.y, sizeof(int));
|
||||||
|
deserialCopy(&buffer, &packet->bounds.w, sizeof(int));
|
||||||
|
deserialCopy(&buffer, &packet->bounds.h, sizeof(int));
|
||||||
|
|
||||||
//gameplay components: equipment, items, buffs, debuffs...
|
//gameplay components: equipment, items, buffs, debuffs...
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "serial_packet_base.hpp"
|
#include "serial_packet_base.hpp"
|
||||||
|
|
||||||
|
#include "bounding_box.hpp"
|
||||||
#include "vector2.hpp"
|
#include "vector2.hpp"
|
||||||
|
|
||||||
struct CharacterPacket : SerialPacketBase {
|
struct CharacterPacket : SerialPacketBase {
|
||||||
@@ -39,6 +40,7 @@ struct CharacterPacket : SerialPacketBase {
|
|||||||
int roomIndex;
|
int roomIndex;
|
||||||
Vector2 origin;
|
Vector2 origin;
|
||||||
Vector2 motion;
|
Vector2 motion;
|
||||||
|
BoundingBox bounds;
|
||||||
};
|
};
|
||||||
|
|
||||||
void serializeCharacter(void* buffer, CharacterPacket* packet);
|
void serializeCharacter(void* buffer, CharacterPacket* packet);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ 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
|
//TODO: (3) password, auth token
|
||||||
};
|
};
|
||||||
|
|
||||||
void serializeClient(void* buffer, ClientPacket* packet);
|
void serializeClient(void* buffer, ClientPacket* packet);
|
||||||
|
|||||||
@@ -30,8 +30,3 @@ $(OUTDIR):
|
|||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o *.a *.exe
|
|
||||||
|
|
||||||
rebuild: clean all
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
#include "serial_packet_type.hpp"
|
#include "serial_packet_type.hpp"
|
||||||
|
|
||||||
#include "SDL/SDL_net.h"
|
#include "SDL_net.h"
|
||||||
|
|
||||||
constexpr int PACKET_STRING_SIZE = 100;
|
constexpr int PACKET_STRING_SIZE = 100;
|
||||||
|
|
||||||
|
|||||||
@@ -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 = 20150304;
|
||||||
|
|
||||||
union MaxPacket {
|
union MaxPacket {
|
||||||
CharacterPacket a;
|
CharacterPacket a;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
/* DOCS: The headers indicate what packet type is used for each message
|
/* DOCS: The headers indicate what packet type is used for each message
|
||||||
* different messages under the same header will carry different amounts of
|
* different messages under the same header will carry different amounts of
|
||||||
* 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.
|
||||||
|
* FORMAT_* is for internal use, deviding the different format bounds.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum class SerialPacketType {
|
enum class SerialPacketType {
|
||||||
@@ -36,6 +37,8 @@ enum class SerialPacketType {
|
|||||||
// name, player count, version
|
// name, player count, version
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
|
FORMAT_SERVER,
|
||||||
|
|
||||||
//heartbeat
|
//heartbeat
|
||||||
PING,
|
PING,
|
||||||
PONG,
|
PONG,
|
||||||
@@ -44,11 +47,15 @@ enum class SerialPacketType {
|
|||||||
BROADCAST_REQUEST,
|
BROADCAST_REQUEST,
|
||||||
BROADCAST_RESPONSE,
|
BROADCAST_RESPONSE,
|
||||||
|
|
||||||
|
FORMAT_END_SERVER,
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//ClientPacket
|
//ClientPacket
|
||||||
// client index, account index, username
|
// client index, account index, username
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
|
FORMAT_CLIENT,
|
||||||
|
|
||||||
//Connecting to a server as a client
|
//Connecting to a server as a client
|
||||||
JOIN_REQUEST,
|
JOIN_REQUEST,
|
||||||
JOIN_RESPONSE,
|
JOIN_RESPONSE,
|
||||||
@@ -69,15 +76,21 @@ enum class SerialPacketType {
|
|||||||
//shut down the server
|
//shut down the server
|
||||||
ADMIN_SHUTDOWN_REQUEST,
|
ADMIN_SHUTDOWN_REQUEST,
|
||||||
|
|
||||||
|
FORMAT_END_CLIENT,
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//RegionPacket
|
//RegionPacket
|
||||||
// room index, x, y, raw data
|
// room index, x, y, raw data
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
|
FORMAT_REGION,
|
||||||
|
|
||||||
//map data
|
//map data
|
||||||
REGION_REQUEST,
|
REGION_REQUEST,
|
||||||
REGION_CONTENT,
|
REGION_CONTENT,
|
||||||
|
|
||||||
|
FORMAT_END_REGION,
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//CharacterPacket
|
//CharacterPacket
|
||||||
// character index,
|
// character index,
|
||||||
@@ -86,6 +99,11 @@ enum class SerialPacketType {
|
|||||||
// room index, origin, motion
|
// room index, origin, motion
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
|
FORMAT_CHARACTER,
|
||||||
|
|
||||||
|
//full data update
|
||||||
|
CHARACTER_UPDATE,
|
||||||
|
|
||||||
//character management
|
//character management
|
||||||
CHARACTER_CREATE,
|
CHARACTER_CREATE,
|
||||||
CHARACTER_DELETE,
|
CHARACTER_DELETE,
|
||||||
@@ -97,7 +115,7 @@ enum class SerialPacketType {
|
|||||||
QUERY_CHARACTER_STATS,
|
QUERY_CHARACTER_STATS,
|
||||||
QUERY_CHARACTER_LOCATION,
|
QUERY_CHARACTER_LOCATION,
|
||||||
|
|
||||||
//set the info in the server
|
//actions taken
|
||||||
CHARACTER_MOVEMENT,
|
CHARACTER_MOVEMENT,
|
||||||
CHARACTER_ATTACK,
|
CHARACTER_ATTACK,
|
||||||
CHARACTER_DAMAGE,
|
CHARACTER_DAMAGE,
|
||||||
@@ -105,6 +123,8 @@ enum class SerialPacketType {
|
|||||||
//admin control
|
//admin control
|
||||||
// ADMIN_SET_CHARACTER_ORIGIN,
|
// ADMIN_SET_CHARACTER_ORIGIN,
|
||||||
|
|
||||||
|
FORMAT_END_CHARACTER,
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//MonsterPacket
|
//MonsterPacket
|
||||||
// monster index,
|
// monster index,
|
||||||
@@ -113,22 +133,34 @@ enum class SerialPacketType {
|
|||||||
// room index, origin, motion
|
// room index, origin, motion
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
|
FORMAT_MONSTER,
|
||||||
|
|
||||||
|
//full data update
|
||||||
|
MONSTER_UPDATE,
|
||||||
|
|
||||||
|
//character management
|
||||||
MONSTER_CREATE,
|
MONSTER_CREATE,
|
||||||
MONSTER_DELETE,
|
MONSTER_DELETE,
|
||||||
|
|
||||||
|
//find out info from the server
|
||||||
QUERY_MONSTER_EXISTS,
|
QUERY_MONSTER_EXISTS,
|
||||||
QUERY_MONSTER_STATS,
|
QUERY_MONSTER_STATS,
|
||||||
QUERY_MONSTER_LOCATION,
|
QUERY_MONSTER_LOCATION,
|
||||||
|
|
||||||
|
//actions taken
|
||||||
MONSTER_MOVEMENT,
|
MONSTER_MOVEMENT,
|
||||||
MONSTER_ATTACK,
|
MONSTER_ATTACK,
|
||||||
MONSTER_DAMAGE,
|
MONSTER_DAMAGE,
|
||||||
|
|
||||||
|
FORMAT_END_MONSTER,
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//TextPacket
|
//TextPacket
|
||||||
// name, text
|
// name, text
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
|
FORMAT_TEXT,
|
||||||
|
|
||||||
//general speech
|
//general speech
|
||||||
TEXT_BROADCAST,
|
TEXT_BROADCAST,
|
||||||
TEXT_SPEECH,
|
TEXT_SPEECH,
|
||||||
@@ -143,6 +175,8 @@ enum class SerialPacketType {
|
|||||||
SHUTDOWN_REJECTION,
|
SHUTDOWN_REJECTION,
|
||||||
QUERY_REJECTION,
|
QUERY_REJECTION,
|
||||||
|
|
||||||
|
FORMAT_END_TEXT,
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//not used
|
//not used
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|||||||
@@ -31,6 +31,9 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
//macros
|
||||||
|
#define BOUNDS(type, lower, upper) ((type) > (lower) && (type) < (upper))
|
||||||
|
|
||||||
//raw memory copy
|
//raw memory copy
|
||||||
void serialCopy(void** buffer, void* data, int size) {
|
void serialCopy(void** buffer, void* data, int size) {
|
||||||
memcpy(*buffer, data, size);
|
memcpy(*buffer, data, size);
|
||||||
@@ -46,63 +49,28 @@ void deserialCopy(void** buffer, void* data, int size) {
|
|||||||
|
|
||||||
//main switch functions
|
//main switch functions
|
||||||
void serializePacket(void* buffer, SerialPacketBase* packet) {
|
void serializePacket(void* buffer, SerialPacketBase* packet) {
|
||||||
switch(packet->type) {
|
if (BOUNDS(packet->type, SerialPacketType::FORMAT_SERVER, SerialPacketType::FORMAT_END_SERVER)) {
|
||||||
case SerialPacketType::PING:
|
serializeServer(buffer, static_cast<ServerPacket*>(packet));
|
||||||
case SerialPacketType::PONG:
|
}
|
||||||
case SerialPacketType::BROADCAST_REQUEST:
|
|
||||||
case SerialPacketType::BROADCAST_RESPONSE:
|
if (BOUNDS(packet->type, SerialPacketType::FORMAT_CLIENT, SerialPacketType::FORMAT_END_CLIENT)) {
|
||||||
serializeServer(buffer, static_cast<ServerPacket*>(packet));
|
serializeClient(buffer, static_cast<ClientPacket*>(packet));
|
||||||
break;
|
}
|
||||||
case SerialPacketType::JOIN_REQUEST:
|
|
||||||
case SerialPacketType::JOIN_RESPONSE:
|
if (BOUNDS(packet->type, SerialPacketType::FORMAT_REGION, SerialPacketType::FORMAT_END_REGION)) {
|
||||||
case SerialPacketType::DISCONNECT_REQUEST:
|
serializeRegion(buffer, static_cast<RegionPacket*>(packet));
|
||||||
case SerialPacketType::DISCONNECT_RESPONSE:
|
}
|
||||||
case SerialPacketType::ADMIN_DISCONNECT_FORCED:
|
|
||||||
case SerialPacketType::LOGIN_REQUEST:
|
if (BOUNDS(packet->type, SerialPacketType::FORMAT_CHARACTER, SerialPacketType::FORMAT_END_CHARACTER)) {
|
||||||
case SerialPacketType::LOGIN_RESPONSE:
|
serializeCharacter(buffer, static_cast<CharacterPacket*>(packet));
|
||||||
case SerialPacketType::LOGOUT_REQUEST:
|
}
|
||||||
case SerialPacketType::LOGOUT_RESPONSE:
|
|
||||||
case SerialPacketType::ADMIN_SHUTDOWN_REQUEST:
|
if (BOUNDS(packet->type, SerialPacketType::FORMAT_MONSTER, SerialPacketType::FORMAT_END_MONSTER)) {
|
||||||
serializeClient(buffer, static_cast<ClientPacket*>(packet));
|
serializeMonster(buffer, static_cast<MonsterPacket*>(packet));
|
||||||
break;
|
}
|
||||||
case SerialPacketType::REGION_REQUEST:
|
|
||||||
case SerialPacketType::REGION_CONTENT:
|
if (BOUNDS(packet->type, SerialPacketType::FORMAT_TEXT, SerialPacketType::FORMAT_END_TEXT)) {
|
||||||
serializeRegion(buffer, static_cast<RegionPacket*>(packet));
|
serializeText(buffer, static_cast<TextPacket*>(packet));
|
||||||
break;
|
|
||||||
case SerialPacketType::CHARACTER_CREATE:
|
|
||||||
case SerialPacketType::CHARACTER_DELETE:
|
|
||||||
case SerialPacketType::CHARACTER_LOAD:
|
|
||||||
case SerialPacketType::CHARACTER_UNLOAD:
|
|
||||||
case SerialPacketType::QUERY_CHARACTER_EXISTS:
|
|
||||||
case SerialPacketType::QUERY_CHARACTER_STATS:
|
|
||||||
case SerialPacketType::QUERY_CHARACTER_LOCATION:
|
|
||||||
case SerialPacketType::CHARACTER_MOVEMENT:
|
|
||||||
case SerialPacketType::CHARACTER_ATTACK:
|
|
||||||
case SerialPacketType::CHARACTER_DAMAGE:
|
|
||||||
serializeCharacter(buffer, static_cast<CharacterPacket*>(packet));
|
|
||||||
break;
|
|
||||||
case SerialPacketType::MONSTER_CREATE:
|
|
||||||
case SerialPacketType::MONSTER_DELETE:
|
|
||||||
case SerialPacketType::QUERY_MONSTER_EXISTS:
|
|
||||||
case SerialPacketType::QUERY_MONSTER_STATS:
|
|
||||||
case SerialPacketType::QUERY_MONSTER_LOCATION:
|
|
||||||
case SerialPacketType::MONSTER_MOVEMENT:
|
|
||||||
case SerialPacketType::MONSTER_ATTACK:
|
|
||||||
case SerialPacketType::MONSTER_DAMAGE:
|
|
||||||
serializeMonster(buffer, static_cast<MonsterPacket*>(packet));
|
|
||||||
break;
|
|
||||||
case SerialPacketType::TEXT_BROADCAST:
|
|
||||||
case SerialPacketType::TEXT_SPEECH:
|
|
||||||
case SerialPacketType::TEXT_WHISPER:
|
|
||||||
case SerialPacketType::JOIN_REJECTION:
|
|
||||||
case SerialPacketType::LOGIN_REJECTION:
|
|
||||||
case SerialPacketType::REGION_REJECTION:
|
|
||||||
case SerialPacketType::CHARACTER_REJECTION:
|
|
||||||
case SerialPacketType::MONSTER_REJECTION:
|
|
||||||
case SerialPacketType::SHUTDOWN_REJECTION:
|
|
||||||
case SerialPacketType::QUERY_REJECTION:
|
|
||||||
serializeText(buffer, static_cast<TextPacket*>(packet));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,62 +79,27 @@ void deserializePacket(void* buffer, SerialPacketBase* packet) {
|
|||||||
SerialPacketType type;
|
SerialPacketType type;
|
||||||
memcpy(&type, buffer, sizeof(SerialPacketType));
|
memcpy(&type, buffer, sizeof(SerialPacketType));
|
||||||
|
|
||||||
switch(type) {
|
if (BOUNDS(type, SerialPacketType::FORMAT_SERVER, SerialPacketType::FORMAT_END_SERVER)) {
|
||||||
case SerialPacketType::PING:
|
deserializeServer(buffer, static_cast<ServerPacket*>(packet));
|
||||||
case SerialPacketType::PONG:
|
}
|
||||||
case SerialPacketType::BROADCAST_REQUEST:
|
|
||||||
case SerialPacketType::BROADCAST_RESPONSE:
|
if (BOUNDS(type, SerialPacketType::FORMAT_CLIENT, SerialPacketType::FORMAT_END_CLIENT)) {
|
||||||
deserializeServer(buffer, static_cast<ServerPacket*>(packet));
|
deserializeClient(buffer, static_cast<ClientPacket*>(packet));
|
||||||
break;
|
}
|
||||||
case SerialPacketType::JOIN_REQUEST:
|
|
||||||
case SerialPacketType::JOIN_RESPONSE:
|
if (BOUNDS(type, SerialPacketType::FORMAT_REGION, SerialPacketType::FORMAT_END_REGION)) {
|
||||||
case SerialPacketType::DISCONNECT_REQUEST:
|
deserializeRegion(buffer, static_cast<RegionPacket*>(packet));
|
||||||
case SerialPacketType::DISCONNECT_RESPONSE:
|
}
|
||||||
case SerialPacketType::ADMIN_DISCONNECT_FORCED:
|
|
||||||
case SerialPacketType::LOGIN_REQUEST:
|
if (BOUNDS(type, SerialPacketType::FORMAT_CHARACTER, SerialPacketType::FORMAT_END_CHARACTER)) {
|
||||||
case SerialPacketType::LOGIN_RESPONSE:
|
deserializeCharacter(buffer, static_cast<CharacterPacket*>(packet));
|
||||||
case SerialPacketType::LOGOUT_REQUEST:
|
}
|
||||||
case SerialPacketType::LOGOUT_RESPONSE:
|
|
||||||
case SerialPacketType::ADMIN_SHUTDOWN_REQUEST:
|
if (BOUNDS(type, SerialPacketType::FORMAT_MONSTER, SerialPacketType::FORMAT_END_MONSTER)) {
|
||||||
deserializeClient(buffer, static_cast<ClientPacket*>(packet));
|
deserializeMonster(buffer, static_cast<MonsterPacket*>(packet));
|
||||||
break;
|
}
|
||||||
case SerialPacketType::REGION_REQUEST:
|
|
||||||
case SerialPacketType::REGION_CONTENT:
|
if (BOUNDS(type, SerialPacketType::FORMAT_TEXT, SerialPacketType::FORMAT_END_TEXT)) {
|
||||||
deserializeRegion(buffer, static_cast<RegionPacket*>(packet));
|
deserializeText(buffer, static_cast<TextPacket*>(packet));
|
||||||
break;
|
|
||||||
case SerialPacketType::CHARACTER_CREATE:
|
|
||||||
case SerialPacketType::CHARACTER_DELETE:
|
|
||||||
case SerialPacketType::CHARACTER_LOAD:
|
|
||||||
case SerialPacketType::CHARACTER_UNLOAD:
|
|
||||||
case SerialPacketType::QUERY_CHARACTER_EXISTS:
|
|
||||||
case SerialPacketType::QUERY_CHARACTER_STATS:
|
|
||||||
case SerialPacketType::QUERY_CHARACTER_LOCATION:
|
|
||||||
case SerialPacketType::CHARACTER_MOVEMENT:
|
|
||||||
case SerialPacketType::CHARACTER_ATTACK:
|
|
||||||
case SerialPacketType::CHARACTER_DAMAGE:
|
|
||||||
deserializeCharacter(buffer, static_cast<CharacterPacket*>(packet));
|
|
||||||
break;
|
|
||||||
case SerialPacketType::MONSTER_CREATE:
|
|
||||||
case SerialPacketType::MONSTER_DELETE:
|
|
||||||
case SerialPacketType::QUERY_MONSTER_EXISTS:
|
|
||||||
case SerialPacketType::QUERY_MONSTER_STATS:
|
|
||||||
case SerialPacketType::QUERY_MONSTER_LOCATION:
|
|
||||||
case SerialPacketType::MONSTER_MOVEMENT:
|
|
||||||
case SerialPacketType::MONSTER_ATTACK:
|
|
||||||
case SerialPacketType::MONSTER_DAMAGE:
|
|
||||||
deserializeMonster(buffer, static_cast<MonsterPacket*>(packet));
|
|
||||||
break;
|
|
||||||
case SerialPacketType::TEXT_BROADCAST:
|
|
||||||
case SerialPacketType::TEXT_SPEECH:
|
|
||||||
case SerialPacketType::TEXT_WHISPER:
|
|
||||||
case SerialPacketType::JOIN_REJECTION:
|
|
||||||
case SerialPacketType::LOGIN_REJECTION:
|
|
||||||
case SerialPacketType::REGION_REJECTION:
|
|
||||||
case SerialPacketType::CHARACTER_REJECTION:
|
|
||||||
case SerialPacketType::MONSTER_REJECTION:
|
|
||||||
case SerialPacketType::SHUTDOWN_REJECTION:
|
|
||||||
case SerialPacketType::QUERY_REJECTION:
|
|
||||||
deserializeText(buffer, static_cast<TextPacket*>(packet));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
#include "singleton.hpp"
|
#include "singleton.hpp"
|
||||||
|
|
||||||
//APIs
|
//APIs
|
||||||
#include "SDL/SDL_net.h"
|
#include "SDL_net.h"
|
||||||
|
|
||||||
class UDPNetworkUtility : public Singleton<UDPNetworkUtility> {
|
class UDPNetworkUtility : public Singleton<UDPNetworkUtility> {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -30,8 +30,3 @@ $(OUTDIR):
|
|||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o *.a *.exe
|
|
||||||
|
|
||||||
rebuild: clean all
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
#ifndef IPOPERATORS_HPP_
|
#ifndef IPOPERATORS_HPP_
|
||||||
#define IPOPERATORS_HPP_
|
#define IPOPERATORS_HPP_
|
||||||
|
|
||||||
#include "SDL/SDL_net.h"
|
#include "SDL_net.h"
|
||||||
|
|
||||||
//these should've come standard
|
//these should've come standard
|
||||||
bool operator==(IPaddress lhs, IPaddress rhs);
|
bool operator==(IPaddress lhs, IPaddress rhs);
|
||||||
|
|||||||
@@ -30,8 +30,3 @@ $(OUTDIR):
|
|||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o *.a *.exe
|
|
||||||
|
|
||||||
rebuild: clean all
|
|
||||||
|
|||||||
@@ -19,13 +19,23 @@ release: clean all package
|
|||||||
|
|
||||||
#For use on my machine ONLY
|
#For use on my machine ONLY
|
||||||
package:
|
package:
|
||||||
rar a -r -ep Tortuga.rar $(OUTDIR)/*.exe $(OUTDIR)/*.dll
|
ifeq ($(OS),Windows_NT)
|
||||||
rar a -r Tortuga.rar rsc/* copyright.txt README.txt
|
rar a -r -ep Tortuga-win.rar $(OUTDIR)/*.exe $(OUTDIR)/*.dll
|
||||||
|
rar a -r Tortuga-win.rar rsc/* copyright.txt instructions.txt
|
||||||
|
else ifeq ($(shell uname), Linux)
|
||||||
|
tar -C $(OUTDIR) -zcvf Tortuga-linux.tar client server ../rsc ../copyright.txt ../instructions.txt
|
||||||
|
endif
|
||||||
|
|
||||||
$(OUTDIR):
|
$(OUTDIR):
|
||||||
mkdir $(OUTDIR)
|
mkdir $(OUTDIR)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
$(RM) *.o *.a *.exe
|
$(RM) *.o *.a *.exe
|
||||||
|
else ifeq ($(shell uname), Linux)
|
||||||
|
find . -type f -name *.o -exec rm -f -r -v {} \;
|
||||||
|
find . -type f -name *.a -exec rm -f -r -v {} \;
|
||||||
|
rm -f -v out/client out/server
|
||||||
|
endif
|
||||||
|
|
||||||
rebuild: clean all
|
rebuild: clean all
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
--[[
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
--]]
|
||||||
|
|
||||||
|
--DOCS: a placeholder door utility
|
||||||
|
|
||||||
|
local doorUtility = {}
|
||||||
|
|
||||||
|
roomAPI = require("room")
|
||||||
|
regionPagerAPI = require("region_pager")
|
||||||
|
|
||||||
|
triggerAPI = require("trigger")
|
||||||
|
triggerManagerAPI = require("trigger_manager")
|
||||||
|
|
||||||
|
entityAPI = require("entity")
|
||||||
|
characterAPI = require("character")
|
||||||
|
|
||||||
|
networkAPI = require("network")
|
||||||
|
|
||||||
|
function doorUtility.createTrigger(handle, room, x, y, script)
|
||||||
|
local pager = roomAPI.GetPager(room)
|
||||||
|
|
||||||
|
--place the indicator tile
|
||||||
|
regionPagerAPI.SetTile(pager, x / 32, y / 32, 0, mapMaker.dirt)
|
||||||
|
regionPagerAPI.SetTile(pager, x / 32, y / 32, 1, mapMaker.blank)
|
||||||
|
regionPagerAPI.SetTile(pager, x / 32, y / 32, 2, mapMaker.blank)
|
||||||
|
|
||||||
|
--create the trigger object
|
||||||
|
triggerManagerAPI.Create(
|
||||||
|
roomAPI.GetTriggerMgr(room), handle, x, y,
|
||||||
|
0, 0, 32, 32, --size of the tiles
|
||||||
|
script
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
function doorUtility.createDoorPair(handle, roomOne, Xone, Yone, roomTwo, Xtwo, Ytwo)
|
||||||
|
--create the scripts
|
||||||
|
local function scriptOne(entity)
|
||||||
|
if entityAPI.GetType(entity) ~= "character" then return end
|
||||||
|
|
||||||
|
--move the character
|
||||||
|
characterAPI.SetRoom(entity, roomTwo)
|
||||||
|
characterAPI.SetOrigin(entity, Xtwo, Ytwo-16)
|
||||||
|
networkAPI.PumpCharacterUpdate(entity)
|
||||||
|
|
||||||
|
--disable the other trigger
|
||||||
|
local triggerTwo = triggerManagerAPI.GetTrigger(roomAPI.GetTriggerMgr(roomTwo), handle)
|
||||||
|
triggerAPI.PushExclusionEntity(triggerTwo, entity)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function scriptTwo(entity)
|
||||||
|
if entityAPI.GetType(entity) ~= "character" then return end
|
||||||
|
|
||||||
|
--move the character
|
||||||
|
characterAPI.SetRoom(entity, roomOne)
|
||||||
|
characterAPI.SetOrigin(entity, Xone, Yone-16) --NOTE: the 16 pixel margin for presentation
|
||||||
|
networkAPI.PumpCharacterUpdate(entity)
|
||||||
|
|
||||||
|
--disable the other trigger
|
||||||
|
local triggerOne = triggerManagerAPI.GetTrigger(roomAPI.GetTriggerMgr(roomOne), handle)
|
||||||
|
triggerAPI.PushExclusionEntity(triggerOne, entity)
|
||||||
|
end
|
||||||
|
|
||||||
|
--create the triggers proper
|
||||||
|
doorUtility.createTrigger(handle, roomOne, Xone, Yone, scriptOne)
|
||||||
|
doorUtility.createTrigger(handle, roomTwo, Xtwo, Ytwo, scriptTwo)
|
||||||
|
end
|
||||||
|
|
||||||
|
return doorUtility
|
||||||
+71
-25
@@ -1,4 +1,30 @@
|
|||||||
local Region = require("map_system").Region
|
--[[
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
--]]
|
||||||
|
|
||||||
|
--DOCS: a placeholder map generator
|
||||||
|
|
||||||
|
local regionAPI = require("region")
|
||||||
|
|
||||||
local mapMaker = {}
|
local mapMaker = {}
|
||||||
|
|
||||||
@@ -7,6 +33,7 @@ function mapMaker.Sqr(x) return x*x end
|
|||||||
function mapMaker.Dist(x, y, i, j) return math.sqrt(mapMaker.Sqr(x - i) + mapMaker.Sqr(y - j)) end
|
function mapMaker.Dist(x, y, i, j) return math.sqrt(mapMaker.Sqr(x - i) + mapMaker.Sqr(y - j)) end
|
||||||
|
|
||||||
--tile macros, mapped to the tilesheet "overworld.bmp"
|
--tile macros, mapped to the tilesheet "overworld.bmp"
|
||||||
|
mapMaker.blank = 0
|
||||||
mapMaker.water = 18 + 3 * 0
|
mapMaker.water = 18 + 3 * 0
|
||||||
mapMaker.sand = 18 + 3 * 1
|
mapMaker.sand = 18 + 3 * 1
|
||||||
mapMaker.plains = 18 + 3 * 2
|
mapMaker.plains = 18 + 3 * 2
|
||||||
@@ -20,42 +47,43 @@ mapMaker.edges.south = 16
|
|||||||
mapMaker.edges.east = 1
|
mapMaker.edges.east = 1
|
||||||
mapMaker.edges.west = -1
|
mapMaker.edges.west = -1
|
||||||
|
|
||||||
|
--TODO: (1) path system
|
||||||
--use these macros (mapped to "overworld.bmp" for now) to smooth the region's edges
|
--use these macros (mapped to "overworld.bmp" for now) to smooth the region's edges
|
||||||
function mapMaker.SmoothEdgesSimple(r)
|
function mapMaker.SmoothEdgesSimple(r)
|
||||||
--make and pad an array to use
|
--make and pad an array to use
|
||||||
local shiftArray = {}
|
local shiftArray = {}
|
||||||
for i = 1, Region.GetWidth(r) do
|
for i = 1, regionAPI.GetWidth(r) do
|
||||||
shiftArray[i] = {}
|
shiftArray[i] = {}
|
||||||
for j = 1, Region.GetHeight(r) do
|
for j = 1, regionAPI.GetHeight(r) do
|
||||||
shiftArray[i][j] = 0
|
shiftArray[i][j] = 0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--build the array
|
--build the array
|
||||||
for i = 1, Region.GetWidth(r) do
|
for i = 1, regionAPI.GetWidth(r) do
|
||||||
for j = 1, Region.GetHeight(r) do
|
for j = 1, regionAPI.GetHeight(r) do
|
||||||
--if (not region edge) and (west tile < this tile), etc.
|
--if (not regionAPI edge) and (west tile < this tile), etc.
|
||||||
if i > 1 and Region.GetTile(r, i - 1, j, 1) < Region.GetTile(r, i, j, 1) then
|
if i > 1 and regionAPI.GetTile(r, i - 1, j, 1) < regionAPI.GetTile(r, i, j, 1) then
|
||||||
shiftArray[i][j] = shiftArray[i][j] + mapMaker.edges.west
|
shiftArray[i][j] = shiftArray[i][j] + mapMaker.edges.west
|
||||||
end
|
end
|
||||||
if j > 1 and Region.GetTile(r, i, j - 1, 1) < Region.GetTile(r, i, j, 1) then
|
if j > 1 and regionAPI.GetTile(r, i, j - 1, 1) < regionAPI.GetTile(r, i, j, 1) then
|
||||||
shiftArray[i][j] = shiftArray[i][j] + mapMaker.edges.north
|
shiftArray[i][j] = shiftArray[i][j] + mapMaker.edges.north
|
||||||
end
|
end
|
||||||
if i < Region.GetWidth(r) and Region.GetTile(r, i + 1, j, 1) < Region.GetTile(r, i, j, 1) then
|
if i < regionAPI.GetWidth(r) and regionAPI.GetTile(r, i + 1, j, 1) < regionAPI.GetTile(r, i, j, 1) then
|
||||||
shiftArray[i][j] = shiftArray[i][j] + mapMaker.edges.east
|
shiftArray[i][j] = shiftArray[i][j] + mapMaker.edges.east
|
||||||
end
|
end
|
||||||
if j < Region.GetHeight(r) and Region.GetTile(r, i, j + 1, 1) < Region.GetTile(r, i, j, 1) then
|
if j < regionAPI.GetHeight(r) and regionAPI.GetTile(r, i, j + 1, 1) < regionAPI.GetTile(r, i, j, 1) then
|
||||||
shiftArray[i][j] = shiftArray[i][j] + mapMaker.edges.south
|
shiftArray[i][j] = shiftArray[i][j] + mapMaker.edges.south
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--finally apply this
|
--finally apply this
|
||||||
for i = 1, Region.GetWidth(r) do
|
for i = 1, regionAPI.GetWidth(r) do
|
||||||
for j = 1, Region.GetHeight(r) do
|
for j = 1, regionAPI.GetHeight(r) do
|
||||||
if shiftArray[i][j] ~= 0 then
|
if shiftArray[i][j] ~= 0 then
|
||||||
Region.SetTile(r, i, j, 2, Region.GetTile(r, i, j, 1) + shiftArray[i][j])
|
regionAPI.SetTile(r, i, j, 2, regionAPI.GetTile(r, i, j, 1) + shiftArray[i][j])
|
||||||
Region.SetTile(r, i, j, 1, Region.GetTile(r, i, j, 1) - 3)
|
regionAPI.SetTile(r, i, j, 1, regionAPI.GetTile(r, i, j, 1) - 3)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -63,28 +91,31 @@ end
|
|||||||
|
|
||||||
--custom generation systems here
|
--custom generation systems here
|
||||||
function mapMaker.DebugIsland(r)
|
function mapMaker.DebugIsland(r)
|
||||||
|
--debug
|
||||||
|
io.write("map_maker:DebugIsland(", regionAPI.GetX(r), ", ", regionAPI.GetY(r), ")\n")
|
||||||
|
|
||||||
--basic distance check for each tile, placing an island around the world origin
|
--basic distance check for each tile, placing an island around the world origin
|
||||||
for i = 1, Region.GetWidth(r) do
|
for i = 1, regionAPI.GetWidth(r) do
|
||||||
for j = 1, Region.GetHeight(r) do
|
for j = 1, regionAPI.GetHeight(r) do
|
||||||
local dist = mapMaker.Dist(0, 0, i + Region.GetX(r) -1, j + Region.GetY(r) -1)
|
local dist = mapMaker.Dist(0, 0, i + regionAPI.GetX(r) -1, j + regionAPI.GetY(r) -1)
|
||||||
if dist < 10 then
|
if dist < 10 then
|
||||||
Region.SetTile(r, i, j, 1, mapMaker.plains)
|
regionAPI.SetTile(r, i, j, 1, mapMaker.plains)
|
||||||
elseif dist < 12 then
|
elseif dist < 12 then
|
||||||
Region.SetTile(r, i, j, 1, mapMaker.sand)
|
regionAPI.SetTile(r, i, j, 1, mapMaker.sand)
|
||||||
else
|
else
|
||||||
Region.SetTile(r, i, j, 1, mapMaker.water)
|
regionAPI.SetTile(r, i, j, 1, mapMaker.water)
|
||||||
Region.SetSolid(r, i, j, true)
|
regionAPI.SetSolid(r, i, j, true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--examples of the smoothing function NOT working correctly
|
--examples of the smoothing function NOT working correctly
|
||||||
--[[
|
--[[
|
||||||
for j = 1, Region.GetHeight(r) do
|
for j = 1, regionAPI.GetHeight(r) do
|
||||||
Region.SetTile(r, 3, j, 1, mapMaker.dirt)
|
regionAPI.SetTile(r, 3, j, 1, mapMaker.dirt)
|
||||||
Region.SetTile(r, 4, j, 1, mapMaker.dirt)
|
regionAPI.SetTile(r, 4, j, 1, mapMaker.dirt)
|
||||||
|
|
||||||
Region.SetTile(r, 10, j, 1, mapMaker.dirt)
|
regionAPI.SetTile(r, 10, j, 1, mapMaker.dirt)
|
||||||
end
|
end
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
@@ -92,4 +123,19 @@ function mapMaker.DebugIsland(r)
|
|||||||
mapMaker.SmoothEdgesSimple(r)
|
mapMaker.SmoothEdgesSimple(r)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function mapMaker.DebugGrassland(r)
|
||||||
|
--debug
|
||||||
|
io.write("map_maker:DebugGrassland(", regionAPI.GetX(r), ", ", regionAPI.GetY(r), ")\n")
|
||||||
|
|
||||||
|
--all dirt
|
||||||
|
for i = 1, regionAPI.GetWidth(r) do
|
||||||
|
for j = 1, regionAPI.GetHeight(r) do
|
||||||
|
regionAPI.SetTile(r, i, j, 1, mapMaker.grass)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--A generic edge system
|
||||||
|
-- mapMaker.SmoothEdgesSimple(r)
|
||||||
|
end
|
||||||
|
|
||||||
return mapMaker
|
return mapMaker
|
||||||
@@ -1,15 +1,39 @@
|
|||||||
local Region = require("map_system").Region
|
--[[
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
--]]
|
||||||
|
|
||||||
|
local region = require("region")
|
||||||
|
|
||||||
local mapSaver = {}
|
local mapSaver = {}
|
||||||
|
|
||||||
function mapSaver.Load(r)
|
function mapSaver.Load(r)
|
||||||
--empty
|
--empty
|
||||||
io.write("map_saver:Load(", Region.GetX(r), ", ", Region.GetY(r), ")\n")
|
-- io.write("map_saver:Load(", region.GetX(r), ", ", region.GetY(r), ")\n")
|
||||||
end
|
end
|
||||||
function mapSaver.Save(r)
|
function mapSaver.Save(r)
|
||||||
--empty
|
--empty
|
||||||
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: (3) create a flexible saving & loading system
|
||||||
return mapSaver
|
return mapSaver
|
||||||
@@ -1,18 +1,61 @@
|
|||||||
|
--[[
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
--]]
|
||||||
|
|
||||||
|
--DOCS: This script is run by the server on startup
|
||||||
|
|
||||||
print("Lua script check")
|
print("Lua script check")
|
||||||
|
|
||||||
|
--requirements
|
||||||
|
roomManagerAPI = require("room_manager")
|
||||||
|
roomAPI = require("room")
|
||||||
|
|
||||||
mapMaker = require("map_maker")
|
mapMaker = require("map_maker")
|
||||||
mapSaver = require("map_saver")
|
mapSaver = require("map_saver")
|
||||||
roomSystem = require("room_system")
|
|
||||||
|
|
||||||
local function dumpTable(t)
|
doorUtility = require("door_utility")
|
||||||
print(t)
|
|
||||||
for k, v in pairs(t) do
|
--test the room hooks
|
||||||
print("",k,v)
|
roomManagerAPI.SetOnCreate(function(room, index)
|
||||||
end
|
print("", "Creating room: ", roomAPI.GetName(room), index)
|
||||||
end
|
|
||||||
|
roomAPI.SetOnTick(room, function(room)
|
||||||
|
roomAPI.ForEachCharacter(room, function(character)
|
||||||
|
--
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
roomManagerAPI.SetOnUnload(function(room, index)
|
||||||
|
print("", "Unloading room: ", roomAPI.GetName(room), index)
|
||||||
|
end)
|
||||||
|
|
||||||
--NOTE: room 0 is the first that the client asks for, therefore it must exist
|
--NOTE: room 0 is the first that the client asks for, therefore it must exist
|
||||||
local overworld, uid = roomSystem.RoomManager.CreateRoom("overworld", "overworld.bmp")
|
local overworld, uidOne = roomManagerAPI.CreateRoom("overworld", "overworld.bmp")
|
||||||
roomSystem.Room.Initialize(overworld, mapSaver.Load, mapSaver.Save, mapMaker.DebugIsland, mapSaver.Save)
|
roomAPI.Initialize(overworld, mapSaver.Load, mapSaver.Save, mapMaker.DebugIsland, mapSaver.Save)
|
||||||
|
|
||||||
print("Finished the lua script")
|
local underworld, uidTwo = roomManagerAPI.CreateRoom("underworld", "overworld.bmp")
|
||||||
|
roomAPI.Initialize(underworld, mapSaver.Load, mapSaver.Save, mapMaker.DebugGrassland, mapSaver.Save)
|
||||||
|
|
||||||
|
--call the monstrosity
|
||||||
|
doorUtility.createDoorPair("pair 1", overworld, -64, -64, underworld, 64, 64)
|
||||||
|
|||||||
@@ -1,8 +1,28 @@
|
|||||||
--TODO: (9) An archive table of all dead characters
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS Accounts (
|
CREATE TABLE IF NOT EXISTS UserAccounts (
|
||||||
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, --TODO: (3) Swap username for email address
|
||||||
|
|
||||||
--server-client security
|
--server-client security
|
||||||
-- passhash varchar(100),
|
-- passhash varchar(100),
|
||||||
@@ -15,7 +35,7 @@ CREATE TABLE IF NOT EXISTS Accounts (
|
|||||||
admin BIT DEFAULT 0
|
admin BIT DEFAULT 0
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS Characters (
|
CREATE TABLE IF NOT EXISTS LiveCharacters (
|
||||||
uid INTEGER PRIMARY KEY AUTOINCREMENT,
|
uid INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
|
||||||
--metadata
|
--metadata
|
||||||
@@ -24,19 +44,52 @@ CREATE TABLE IF NOT EXISTS Characters (
|
|||||||
avatar varchar(100),
|
avatar varchar(100),
|
||||||
birth timestamp NOT NULL DEFAULT (datetime()),
|
birth timestamp NOT NULL DEFAULT (datetime()),
|
||||||
|
|
||||||
--position in the world
|
--physically exists in the world
|
||||||
roomIndex INTEGER DEFAULT 0,
|
roomIndex INTEGER DEFAULT 0,
|
||||||
originX INTEGER DEFAULT 0,
|
originX INTEGER DEFAULT 0,
|
||||||
originY INTEGER DEFAULT 0,
|
originY INTEGER DEFAULT 0,
|
||||||
|
boundsX INTEGER DEFAULT 0,
|
||||||
|
boundsY INTEGER DEFAULT 0,
|
||||||
|
boundsW INTEGER DEFAULT 0,
|
||||||
|
boundsH INTEGER DEFAULT 0
|
||||||
|
);
|
||||||
|
|
||||||
--statistics
|
CREATE TABLE IF NOT EXISTS DeadCharacters (
|
||||||
baseStats INTEGER REFERENCES StatisticSets(uid),
|
uid INTEGER PRIMARY KEY,
|
||||||
|
|
||||||
--equipment
|
--metadata
|
||||||
weapon INTEGER REFERENCES WornEquipment(uid),
|
owner INTEGER REFERENCES Accounts(uid),
|
||||||
helmet INTEGER REFERENCES WornEquipment(uid),
|
handle varchar(100),
|
||||||
armour INTEGER REFERENCES WornEquipment(uid)
|
avatar varchar(100),
|
||||||
--etc.
|
birth timestamp NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS LiveMonsters (
|
||||||
|
uid INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
|
||||||
|
--metadata
|
||||||
|
handle varchar(100) UNIQUE,
|
||||||
|
avatar varchar(100),
|
||||||
|
|
||||||
|
--actions
|
||||||
|
-- script
|
||||||
|
|
||||||
|
--physically exists in the world
|
||||||
|
roomIndex INTEGER DEFAULT 0,
|
||||||
|
originX INTEGER DEFAULT 0,
|
||||||
|
originY INTEGER DEFAULT 0,
|
||||||
|
boundsX INTEGER DEFAULT 0,
|
||||||
|
boundsY INTEGER DEFAULT 0,
|
||||||
|
boundsW INTEGER DEFAULT 0,
|
||||||
|
boundsH INTEGER DEFAULT 0
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS DeadMonsters (
|
||||||
|
uid INTEGER PRIMARY KEY,
|
||||||
|
|
||||||
|
--metadata
|
||||||
|
handle varchar(100) UNIQUE,
|
||||||
|
avatar varchar(100)
|
||||||
);
|
);
|
||||||
|
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|||||||
@@ -27,16 +27,32 @@
|
|||||||
//Define the queries
|
//Define the queries
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
static const char* CREATE_USER_ACCOUNT = "INSERT INTO Accounts (username) VALUES (?);";
|
static const char* CREATE_USER_ACCOUNT = "INSERT INTO UserAccounts (username) VALUES (?);";
|
||||||
static const char* LOAD_USER_ACCOUNT = "SELECT * FROM Accounts WHERE username = ?;";
|
|
||||||
static const char* SAVE_USER_ACCOUNT = "UPDATE OR FAIL Accounts SET blacklisted = ?2, whitelisted = ?3, mod = ?4, admin = ?5 WHERE uid = ?1;";
|
static const char* LOAD_USER_ACCOUNT = "SELECT "
|
||||||
static const char* DELETE_USER_ACCOUNT = "DELETE FROM Accounts WHERE uid = ?;";
|
"uid, "
|
||||||
static const char* COUNT_USER_ACCOUNT_RECORDS = "SELECT COUNT(*) FROM Accounts;";
|
"blacklisted, "
|
||||||
|
"whitelisted, "
|
||||||
|
"mod, "
|
||||||
|
"admin "
|
||||||
|
" FROM UserAccounts WHERE username = ?;";
|
||||||
|
|
||||||
|
static const char* SAVE_USER_ACCOUNT = "UPDATE OR FAIL UserAccounts SET "
|
||||||
|
"blacklisted = ?2, "
|
||||||
|
"whitelisted = ?3, "
|
||||||
|
"mod = ?4, "
|
||||||
|
"admin = ?5 "
|
||||||
|
"WHERE uid = ?1;";
|
||||||
|
|
||||||
|
static const char* DELETE_USER_ACCOUNT = "DELETE FROM UserAccounts WHERE uid = ?;";
|
||||||
|
|
||||||
|
static const char* COUNT_USER_ACCOUNT_RECORDS = "SELECT COUNT(*) FROM UserAccounts;";
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//Define the public methods
|
//Define the public methods
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
|
//TODO: (1) block blacklisted accounts
|
||||||
int AccountManager::Create(std::string username, int clientIndex) {
|
int AccountManager::Create(std::string username, int clientIndex) {
|
||||||
//create this user account, failing if it exists, leave this account in memory
|
//create this user account, failing if it exists, leave this account in memory
|
||||||
sqlite3_stmt* statement = nullptr;
|
sqlite3_stmt* statement = nullptr;
|
||||||
@@ -94,11 +110,11 @@ int AccountManager::Load(std::string username, int clientIndex) {
|
|||||||
|
|
||||||
//extract the data into memory
|
//extract the data into memory
|
||||||
AccountData& newAccount = elementMap[uid];
|
AccountData& newAccount = elementMap[uid];
|
||||||
newAccount.username = reinterpret_cast<const char*>(sqlite3_column_text(statement, 1));
|
newAccount.username = username;
|
||||||
newAccount.blackListed = sqlite3_column_int(statement, 2);
|
newAccount.blackListed = sqlite3_column_int(statement, 1);
|
||||||
newAccount.whiteListed = sqlite3_column_int(statement, 3);
|
newAccount.whiteListed = sqlite3_column_int(statement, 2);
|
||||||
newAccount.mod = sqlite3_column_int(statement, 4);
|
newAccount.mod = sqlite3_column_int(statement, 3);
|
||||||
newAccount.admin = sqlite3_column_int(statement, 5);
|
newAccount.admin = sqlite3_column_int(statement, 4);
|
||||||
newAccount.clientIndex = clientIndex;
|
newAccount.clientIndex = clientIndex;
|
||||||
|
|
||||||
//finish the routine
|
//finish the routine
|
||||||
|
|||||||
@@ -30,8 +30,3 @@ $(OUTDIR):
|
|||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o *.a *.exe
|
|
||||||
|
|
||||||
rebuild: clean all
|
|
||||||
|
|||||||
@@ -22,12 +22,108 @@
|
|||||||
#include "character_api.hpp"
|
#include "character_api.hpp"
|
||||||
|
|
||||||
#include "character_data.hpp"
|
#include "character_data.hpp"
|
||||||
|
#include "character_manager.hpp"
|
||||||
|
#include "entity_api.hpp"
|
||||||
|
#include "room_manager.hpp"
|
||||||
|
#include "server_utilities.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
static int setRoom(lua_State* L) {
|
||||||
|
//reverse engineer the character index
|
||||||
|
int characterIndex = -1;
|
||||||
|
CharacterData* character = static_cast<CharacterData*>(lua_touserdata(L, 1));
|
||||||
|
CharacterManager& characterMgr = CharacterManager::GetSingleton();
|
||||||
|
|
||||||
|
for (auto& it : *characterMgr.GetContainer()) {
|
||||||
|
if (character == &it.second) {
|
||||||
|
characterIndex = it.first;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//error checking
|
||||||
|
if (characterIndex == -1) {
|
||||||
|
throw(std::runtime_error("Lua Error: Failed to find character index by reference"));
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the room index, depending on the parameter type
|
||||||
|
int roomIndex = -1;
|
||||||
|
RoomManager& roomMgr = RoomManager::GetSingleton();
|
||||||
|
switch(lua_type(L, 2)) {
|
||||||
|
case LUA_TNUMBER:
|
||||||
|
roomIndex = lua_tointeger(L, 2);
|
||||||
|
break;
|
||||||
|
case LUA_TLIGHTUSERDATA:
|
||||||
|
//reverse engineer the room index
|
||||||
|
for (auto& it : *roomMgr.GetContainer()) {
|
||||||
|
if (lua_touserdata(L, 2) == &it.second) {
|
||||||
|
roomIndex = it.first;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//error checking
|
||||||
|
if (roomIndex == -1) {
|
||||||
|
throw(std::runtime_error("Lua Error: Failed to find room index by reference"));
|
||||||
|
}
|
||||||
|
|
||||||
|
//send the delete & create messages
|
||||||
|
pumpAndChangeRooms(character, roomIndex, characterIndex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getOwner(lua_State* L) {
|
||||||
|
CharacterData* character = static_cast<CharacterData*>(lua_touserdata(L, 1));
|
||||||
|
lua_pushinteger(L, character->GetOwner());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getHandle(lua_State* L) {
|
||||||
|
CharacterData* character = static_cast<CharacterData*>(lua_touserdata(L, 1));
|
||||||
|
lua_pushstring(L, character->GetHandle().c_str());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getAvatar(lua_State* L) {
|
||||||
|
CharacterData* character = static_cast<CharacterData*>(lua_touserdata(L, 1));
|
||||||
|
lua_pushstring(L, character->GetAvatar().c_str());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static const luaL_Reg characterLib[] = {
|
static const luaL_Reg characterLib[] = {
|
||||||
|
{"SetRoom", setRoom},
|
||||||
|
// {"GetOwner", getOwner}, //unusable without account API
|
||||||
|
{"GetHandle", getHandle},
|
||||||
|
{"GetAvatar", getAvatar},
|
||||||
{nullptr, nullptr}
|
{nullptr, nullptr}
|
||||||
};
|
};
|
||||||
|
|
||||||
LUAMOD_API int openCharacterAPI(lua_State* L) {
|
LUAMOD_API int openCharacterAPI(lua_State* L) {
|
||||||
|
//get the parent table
|
||||||
|
luaL_requiref(L, TORTUGA_ENTITY_API, openEntityAPI, false);
|
||||||
|
|
||||||
|
//the local table
|
||||||
luaL_newlib(L, characterLib);
|
luaL_newlib(L, characterLib);
|
||||||
|
|
||||||
|
//merge the local table into the parent table
|
||||||
|
lua_pushnil(L); //first key
|
||||||
|
while(lua_next(L, -2)) {
|
||||||
|
//copy the key-value pair
|
||||||
|
lua_pushvalue(L, -2);
|
||||||
|
lua_pushvalue(L, -2);
|
||||||
|
|
||||||
|
//push the copy to the parent table
|
||||||
|
lua_settable(L, -6);
|
||||||
|
|
||||||
|
//pop the original value before continuing
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//remove the local table, leaving the expanded parent table
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -21,6 +21,10 @@
|
|||||||
*/
|
*/
|
||||||
#include "character_data.hpp"
|
#include "character_data.hpp"
|
||||||
|
|
||||||
|
CharacterData::CharacterData(): Entity("character") {
|
||||||
|
//EMPTY
|
||||||
|
}
|
||||||
|
|
||||||
int CharacterData::GetOwner() {
|
int CharacterData::GetOwner() {
|
||||||
return owner;
|
return owner;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,12 +32,9 @@
|
|||||||
|
|
||||||
class CharacterData: public Entity {
|
class CharacterData: public Entity {
|
||||||
public:
|
public:
|
||||||
CharacterData() = default;
|
CharacterData();
|
||||||
~CharacterData() = default;
|
~CharacterData() = default;
|
||||||
|
|
||||||
//accessors and mutators
|
|
||||||
//...
|
|
||||||
|
|
||||||
//database stuff
|
//database stuff
|
||||||
int GetOwner();
|
int GetOwner();
|
||||||
std::string GetHandle();
|
std::string GetHandle();
|
||||||
@@ -46,7 +43,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
friend class CharacterManager;
|
friend class CharacterManager;
|
||||||
|
|
||||||
int owner;
|
int owner = -1;
|
||||||
std::string handle;
|
std::string handle;
|
||||||
std::string avatar;
|
std::string avatar;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,18 +23,56 @@
|
|||||||
|
|
||||||
#include "sqlite3.h"
|
#include "sqlite3.h"
|
||||||
|
|
||||||
|
#include "character_defines.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//Define the queries
|
//Define the queries
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
static const char* CREATE_CHARACTER = "INSERT INTO Characters (owner, handle, avatar) VALUES (?, ?, ?);";
|
//NOTE: Programmer set variables are NOT zero-indexed
|
||||||
static const char* LOAD_CHARACTER = "SELECT * FROM Characters WHERE handle = ?;";
|
//NOTE: SQLite3 returned variables (i.e. loading) ARE zero-indexed
|
||||||
static const char* SAVE_CHARACTER = "UPDATE OR FAIL Characters SET roomIndex = ?2, originX = ?3, originY = ?4 WHERE uid = ?1;";
|
|
||||||
static const char* DELETE_CHARACTER = "DELETE FROM Characters WHERE uid = ?;";
|
static const char* CREATE_CHARACTER = "INSERT INTO LiveCharacters ("
|
||||||
static const char* COUNT_CHARACTER_RECORDS = "SELECT COUNT(*) FROM Characters;";
|
"owner, "
|
||||||
|
"handle, "
|
||||||
|
"avatar, "
|
||||||
|
"boundsX, "
|
||||||
|
"boundsY, "
|
||||||
|
"boundsW, "
|
||||||
|
"boundsH"
|
||||||
|
") VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7);";
|
||||||
|
|
||||||
|
static const char* LOAD_CHARACTER = "SELECT "
|
||||||
|
"uid, "
|
||||||
|
"owner, "
|
||||||
|
"handle, "
|
||||||
|
"avatar, "
|
||||||
|
"roomIndex, "
|
||||||
|
"originX, "
|
||||||
|
"originY, "
|
||||||
|
"boundsX, "
|
||||||
|
"boundsY, "
|
||||||
|
"boundsW, "
|
||||||
|
"boundsH "
|
||||||
|
"FROM LiveCharacters WHERE handle = ?;";
|
||||||
|
|
||||||
|
static const char* SAVE_CHARACTER = "UPDATE OR FAIL LiveCharacters SET "
|
||||||
|
"roomIndex = ?2, "
|
||||||
|
"originX = ?3, "
|
||||||
|
"originY = ?4, "
|
||||||
|
"boundsX = ?5, "
|
||||||
|
"boundsY = ?6, "
|
||||||
|
"boundsW = ?7, "
|
||||||
|
"boundsH = ?8 "
|
||||||
|
"WHERE uid = ?1;";
|
||||||
|
|
||||||
|
static const char* DELETE_CHARACTER = "DELETE FROM LiveCharacters WHERE uid = ?;";
|
||||||
|
|
||||||
|
static const char* COUNT_CHARACTER_RECORDS = "SELECT COUNT(*) FROM LiveCharacters;";
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//Define the methods
|
//Define the methods
|
||||||
@@ -55,6 +93,10 @@ int CharacterManager::Create(int owner, std::string handle, std::string avatar)
|
|||||||
ret |= sqlite3_bind_int(statement, 1, owner);
|
ret |= sqlite3_bind_int(statement, 1, owner);
|
||||||
ret |= sqlite3_bind_text(statement, 2, handle.c_str(), handle.size() + 1, SQLITE_STATIC);
|
ret |= sqlite3_bind_text(statement, 2, handle.c_str(), handle.size() + 1, SQLITE_STATIC);
|
||||||
ret |= sqlite3_bind_text(statement, 3, avatar.c_str(), avatar.size() + 1, SQLITE_STATIC);
|
ret |= sqlite3_bind_text(statement, 3, avatar.c_str(), avatar.size() + 1, SQLITE_STATIC);
|
||||||
|
ret |= sqlite3_bind_int(statement, 4, CHARACTER_BOUNDS_X);
|
||||||
|
ret |= sqlite3_bind_int(statement, 5, CHARACTER_BOUNDS_Y);
|
||||||
|
ret |= sqlite3_bind_int(statement, 6, CHARACTER_BOUNDS_WIDTH);
|
||||||
|
ret |= sqlite3_bind_int(statement, 7, CHARACTER_BOUNDS_HEIGHT);
|
||||||
|
|
||||||
//check for binding errors
|
//check for binding errors
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@@ -121,9 +163,14 @@ int CharacterManager::Load(int owner, std::string handle, std::string avatar) {
|
|||||||
//Don't cache the birth
|
//Don't cache the birth
|
||||||
|
|
||||||
//world origin
|
//world origin
|
||||||
newChar.roomIndex = sqlite3_column_int(statement, 5);
|
newChar.roomIndex = sqlite3_column_int(statement, 4);
|
||||||
newChar.origin.x = (double)sqlite3_column_int(statement, 6);
|
newChar.origin.x = (double)sqlite3_column_int(statement, 5);
|
||||||
newChar.origin.y = (double)sqlite3_column_int(statement, 7);
|
newChar.origin.y = (double)sqlite3_column_int(statement, 6);
|
||||||
|
//bounds
|
||||||
|
newChar.bounds.x = (int)sqlite3_column_int(statement, 7);
|
||||||
|
newChar.bounds.y = (int)sqlite3_column_int(statement, 8);
|
||||||
|
newChar.bounds.w = (int)sqlite3_column_int(statement, 9);
|
||||||
|
newChar.bounds.h = (int)sqlite3_column_int(statement, 10);
|
||||||
|
|
||||||
//gameplay components: equipment, items, buffs, debuffs...
|
//gameplay components: equipment, items, buffs, debuffs...
|
||||||
|
|
||||||
@@ -165,6 +212,10 @@ int CharacterManager::Save(int uid) {
|
|||||||
ret |= sqlite3_bind_int(statement, 2, character.roomIndex) != SQLITE_OK;
|
ret |= sqlite3_bind_int(statement, 2, character.roomIndex) != SQLITE_OK;
|
||||||
ret |= sqlite3_bind_int(statement, 3, (int)character.origin.x) != SQLITE_OK;
|
ret |= sqlite3_bind_int(statement, 3, (int)character.origin.x) != SQLITE_OK;
|
||||||
ret |= sqlite3_bind_int(statement, 4, (int)character.origin.y) != SQLITE_OK;
|
ret |= sqlite3_bind_int(statement, 4, (int)character.origin.y) != SQLITE_OK;
|
||||||
|
ret |= sqlite3_bind_int(statement, 5, character.bounds.x) != SQLITE_OK;
|
||||||
|
ret |= sqlite3_bind_int(statement, 6, character.bounds.y) != SQLITE_OK;
|
||||||
|
ret |= sqlite3_bind_int(statement, 7, character.bounds.w) != SQLITE_OK;
|
||||||
|
ret |= sqlite3_bind_int(statement, 8, character.bounds.h) != SQLITE_OK;
|
||||||
|
|
||||||
//gameplay components: equipment, items, buffs, debuffs...
|
//gameplay components: equipment, items, buffs, debuffs...
|
||||||
|
|
||||||
@@ -193,6 +244,7 @@ void CharacterManager::Unload(int uid) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CharacterManager::Delete(int uid) {
|
void CharacterManager::Delete(int uid) {
|
||||||
|
//TODO: when deleting a character, move it to an archive table
|
||||||
//delete this character from the database, then remove it from memory
|
//delete this character from the database, then remove it from memory
|
||||||
sqlite3_stmt* statement = nullptr;
|
sqlite3_stmt* statement = nullptr;
|
||||||
|
|
||||||
@@ -252,6 +304,15 @@ CharacterData* CharacterManager::Get(int uid) {
|
|||||||
return &it->second;
|
return &it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CharacterData* CharacterManager::Get(std::string handle) {
|
||||||
|
for (std::map<int, CharacterData>::iterator it = elementMap.begin(); it != elementMap.end(); ++it) {
|
||||||
|
if (it->second.GetHandle() == handle) {
|
||||||
|
return &it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
int CharacterManager::GetLoadedCount() {
|
int CharacterManager::GetLoadedCount() {
|
||||||
return elementMap.size();
|
return elementMap.size();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,13 +44,18 @@ public:
|
|||||||
|
|
||||||
//accessors and mutators
|
//accessors and mutators
|
||||||
CharacterData* Get(int uid);
|
CharacterData* Get(int uid);
|
||||||
|
CharacterData* Get(std::string handle);
|
||||||
int GetLoadedCount();
|
int GetLoadedCount();
|
||||||
int GetTotalCount();
|
int GetTotalCount();
|
||||||
std::map<int, CharacterData>* GetContainer();
|
std::map<int, CharacterData>* GetContainer();
|
||||||
|
|
||||||
|
//API interface
|
||||||
sqlite3* SetDatabase(sqlite3* db);
|
sqlite3* SetDatabase(sqlite3* db);
|
||||||
sqlite3* GetDatabase();
|
sqlite3* GetDatabase();
|
||||||
|
|
||||||
|
//hooks
|
||||||
|
//TODO: character hooks
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend Singleton<CharacterManager>;
|
friend Singleton<CharacterManager>;
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,88 @@
|
|||||||
|
|
||||||
#include "character_manager.hpp"
|
#include "character_manager.hpp"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
//TODO: (1) character hooks?
|
||||||
|
|
||||||
|
static int setOnCreate(lua_State* L) {
|
||||||
|
//TODO: (9) setOnCreate()
|
||||||
|
}
|
||||||
|
|
||||||
|
static int setOnLoad(lua_State* L) {
|
||||||
|
//TODO: (9) setOnLoad()
|
||||||
|
}
|
||||||
|
|
||||||
|
static int setOnSave(lua_State* L) {
|
||||||
|
//TODO: (9) setOnSave()
|
||||||
|
}
|
||||||
|
|
||||||
|
static int setOnUnload(lua_State* L) {
|
||||||
|
//TODO: (9) setOnUnload()
|
||||||
|
}
|
||||||
|
|
||||||
|
static int setOnDelete(lua_State* L) {
|
||||||
|
//TODO: (9) setOnDelete()
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getCharacter(lua_State* L) {
|
||||||
|
//integer vs name
|
||||||
|
CharacterManager& characterMgr = CharacterManager::GetSingleton();
|
||||||
|
CharacterData* characterData = nullptr;
|
||||||
|
|
||||||
|
switch(lua_type(L, 1)) {
|
||||||
|
case LUA_TNUMBER:
|
||||||
|
characterData = characterMgr.Get(lua_tointeger(L, 1));
|
||||||
|
break;
|
||||||
|
case LUA_TSTRING:
|
||||||
|
//access characters via their handles
|
||||||
|
characterData = characterMgr.Get(lua_tostring(L, 1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (characterData) {
|
||||||
|
lua_pushlightuserdata(L, static_cast<void*>(characterData));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lua_pushnil(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getLoadedCount(lua_State* L) {
|
||||||
|
CharacterManager& characterMgr = CharacterManager::GetSingleton();
|
||||||
|
lua_pushinteger(L, characterMgr.GetLoadedCount());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int forEach(lua_State* L) {
|
||||||
|
CharacterManager& characterMgr = CharacterManager::GetSingleton();
|
||||||
|
//pass each character to the given function
|
||||||
|
for (auto& it : *characterMgr.GetContainer()) {
|
||||||
|
lua_pushvalue(L, -1);
|
||||||
|
lua_pushlightuserdata(L, static_cast<void*>(&it.second));
|
||||||
|
//call each iteration, throwing an exception if something happened
|
||||||
|
if (lua_pcall(L, 1, 0, 0) != LUA_OK) {
|
||||||
|
std::ostringstream os;
|
||||||
|
os << "Lua error: ";
|
||||||
|
os << lua_tostring(L, -1);
|
||||||
|
throw(std::runtime_error(os.str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const luaL_Reg characterManagerLib[] = {
|
static const luaL_Reg characterManagerLib[] = {
|
||||||
|
// {"SetOnCreate", setOnCreate},
|
||||||
|
// {"SetOnLoad", setOnLoad},
|
||||||
|
// {"SetOnSave", setOnSave},
|
||||||
|
// {"SetOnUnload", setOnUnload},
|
||||||
|
// {"SetOnDelete", setOnDelete},
|
||||||
|
{"GetCharacter", getCharacter},
|
||||||
|
{"GetLoadedCount", getLoadedCount},
|
||||||
|
{"ForEach", forEach},
|
||||||
{nullptr, nullptr}
|
{nullptr, nullptr}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#config
|
#config
|
||||||
INCLUDES+=. ../entities ../server_utilities ../../common/gameplay ../../common/utilities
|
INCLUDES+=. ../entities ../monsters ../rooms ../server_utilities ../triggers ../../common/gameplay ../../common/map ../../common/network ../../common/network/packet_types ../../common/utilities
|
||||||
LIBS+=
|
LIBS+=
|
||||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||||
|
|
||||||
@@ -30,8 +30,3 @@ $(OUTDIR):
|
|||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o *.a *.exe
|
|
||||||
|
|
||||||
rebuild: clean all
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
#ifndef CLIENTDATA_HPP_
|
#ifndef CLIENTDATA_HPP_
|
||||||
#define CLIENTDATA_HPP_
|
#define CLIENTDATA_HPP_
|
||||||
|
|
||||||
#include "SDL/SDL_net.h"
|
#include "SDL_net.h"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
|
|||||||
@@ -21,11 +21,15 @@
|
|||||||
*/
|
*/
|
||||||
#include "client_manager.hpp"
|
#include "client_manager.hpp"
|
||||||
|
|
||||||
|
#include "ip_operators.hpp"
|
||||||
#include "udp_network_utility.hpp"
|
#include "udp_network_utility.hpp"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
int ClientManager::CheckConnections() {
|
std::list<int> ClientManager::CheckConnections() {
|
||||||
|
//list of clients to disconnect
|
||||||
|
std::list<int> returnList;
|
||||||
|
|
||||||
for (auto& it : elementMap) {
|
for (auto& it : elementMap) {
|
||||||
//3 seconds between beats
|
//3 seconds between beats
|
||||||
if (ClientData::Clock::now() - it.second.GetLastBeat() > std::chrono::seconds(3)) {
|
if (ClientData::Clock::now() - it.second.GetLastBeat() > std::chrono::seconds(3)) {
|
||||||
@@ -38,21 +42,17 @@ int ClientManager::CheckConnections() {
|
|||||||
|
|
||||||
for (auto& it : elementMap) {
|
for (auto& it : elementMap) {
|
||||||
if (it.second.GetAttempts() > 2) {
|
if (it.second.GetAttempts() > 2) {
|
||||||
int ret = it.first;
|
returnList.push_back(it.first);
|
||||||
// elementMap.erase(it.first);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return returnList;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientManager::HandlePong(ServerPacket* const argPacket) {
|
void ClientManager::HandlePong(ServerPacket* const argPacket) {
|
||||||
//find and update the specified client
|
//find and update the specified client
|
||||||
for (auto& it : elementMap) {
|
for (auto& it : elementMap) {
|
||||||
if (it.second.GetAddress().host == argPacket->srcAddress.host &&
|
if (it.second.GetAddress() == argPacket->srcAddress) {
|
||||||
it.second.GetAddress().port == argPacket->srcAddress.port
|
|
||||||
) {
|
|
||||||
it.second.ResetAttempts();
|
it.second.ResetAttempts();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,15 +26,16 @@
|
|||||||
#include "server_packet.hpp"
|
#include "server_packet.hpp"
|
||||||
#include "singleton.hpp"
|
#include "singleton.hpp"
|
||||||
|
|
||||||
#include "SDL/SDL_net.h"
|
#include "SDL_net.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
class ClientManager: public Singleton<ClientManager> {
|
class ClientManager: public Singleton<ClientManager> {
|
||||||
public:
|
public:
|
||||||
//methods
|
//methods
|
||||||
int CheckConnections();
|
std::list<int> CheckConnections();
|
||||||
void HandlePong(ServerPacket* const argPacket);
|
void HandlePong(ServerPacket* const argPacket);
|
||||||
|
|
||||||
//common public methods
|
//common public methods
|
||||||
|
|||||||
@@ -30,8 +30,3 @@ $(OUTDIR):
|
|||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o *.a *.exe
|
|
||||||
|
|
||||||
rebuild: clean all
|
|
||||||
|
|||||||
@@ -21,6 +21,14 @@
|
|||||||
*/
|
*/
|
||||||
#include "entity.hpp"
|
#include "entity.hpp"
|
||||||
|
|
||||||
|
Entity::Entity(const char* _type): type(_type) {
|
||||||
|
//EMPTY
|
||||||
|
}
|
||||||
|
|
||||||
|
void Entity::Update() {
|
||||||
|
origin += motion;
|
||||||
|
}
|
||||||
|
|
||||||
int Entity::SetRoomIndex(int i) {
|
int Entity::SetRoomIndex(int i) {
|
||||||
return roomIndex = i;
|
return roomIndex = i;
|
||||||
}
|
}
|
||||||
@@ -33,6 +41,10 @@ Vector2 Entity::SetMotion(Vector2 v) {
|
|||||||
return motion = v;
|
return motion = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BoundingBox Entity::SetBounds(BoundingBox b) {
|
||||||
|
return bounds = b;
|
||||||
|
}
|
||||||
|
|
||||||
int Entity::GetRoomIndex() const {
|
int Entity::GetRoomIndex() const {
|
||||||
return roomIndex;
|
return roomIndex;
|
||||||
}
|
}
|
||||||
@@ -44,3 +56,11 @@ Vector2 Entity::GetOrigin() const {
|
|||||||
Vector2 Entity::GetMotion() const {
|
Vector2 Entity::GetMotion() const {
|
||||||
return motion;
|
return motion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BoundingBox Entity::GetBounds() const {
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* Entity::GetType() const {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
@@ -22,27 +22,38 @@
|
|||||||
#ifndef ENTITY_HPP_
|
#ifndef ENTITY_HPP_
|
||||||
#define ENTITY_HPP_
|
#define ENTITY_HPP_
|
||||||
|
|
||||||
|
#include "bounding_box.hpp"
|
||||||
#include "vector2.hpp"
|
#include "vector2.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
//The base class for all objects in the world
|
//The base class for all objects in the world
|
||||||
class Entity {
|
class Entity {
|
||||||
public:
|
public:
|
||||||
|
virtual void Update();
|
||||||
|
|
||||||
//accessors & mutators
|
//accessors & mutators
|
||||||
int SetRoomIndex(int i);
|
int SetRoomIndex(int i);
|
||||||
Vector2 SetOrigin(Vector2 v);
|
Vector2 SetOrigin(Vector2 v);
|
||||||
Vector2 SetMotion(Vector2 v);
|
Vector2 SetMotion(Vector2 v);
|
||||||
|
BoundingBox SetBounds(BoundingBox b);
|
||||||
|
|
||||||
int GetRoomIndex() const;
|
int GetRoomIndex() const;
|
||||||
Vector2 GetOrigin() const;
|
Vector2 GetOrigin() const;
|
||||||
Vector2 GetMotion() const;
|
Vector2 GetMotion() const;
|
||||||
|
BoundingBox GetBounds() const;
|
||||||
|
|
||||||
|
const char* GetType() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Entity() = default;
|
Entity(const char* type);
|
||||||
virtual ~Entity() = default;
|
virtual ~Entity() = default;
|
||||||
|
|
||||||
int roomIndex = -1;
|
int roomIndex = -1;
|
||||||
Vector2 origin;
|
Vector2 origin = {0, 0};
|
||||||
Vector2 motion;
|
Vector2 motion = {0, 0};
|
||||||
|
BoundingBox bounds = {0, 0, 0, 0};
|
||||||
|
const char* type;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -41,6 +41,17 @@ static int setMotion(lua_State* L) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int setBounds(lua_State* L) {
|
||||||
|
Entity* entity = static_cast<Entity*>(lua_touserdata(L, 1));
|
||||||
|
entity->SetBounds({
|
||||||
|
lua_tointeger(L, 2),
|
||||||
|
lua_tointeger(L, 3),
|
||||||
|
lua_tointeger(L, 4),
|
||||||
|
lua_tointeger(L, 5)
|
||||||
|
});
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int getRoomIndex(lua_State* L) {
|
static int getRoomIndex(lua_State* L) {
|
||||||
Entity* entity = static_cast<Entity*>(lua_touserdata(L, 1));
|
Entity* entity = static_cast<Entity*>(lua_touserdata(L, 1));
|
||||||
lua_pushinteger(L, entity->GetRoomIndex());
|
lua_pushinteger(L, entity->GetRoomIndex());
|
||||||
@@ -56,18 +67,36 @@ static int getOrigin(lua_State* L) {
|
|||||||
|
|
||||||
static int getMotion(lua_State* L) {
|
static int getMotion(lua_State* L) {
|
||||||
Entity* entity = static_cast<Entity*>(lua_touserdata(L, 1));
|
Entity* entity = static_cast<Entity*>(lua_touserdata(L, 1));
|
||||||
lua_pushnumber(L, entity->GetOrigin().x);
|
lua_pushnumber(L, entity->GetMotion().x);
|
||||||
lua_pushnumber(L, entity->GetOrigin().y);
|
lua_pushnumber(L, entity->GetMotion().y);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int getBounds(lua_State* L) {
|
||||||
|
Entity* entity = static_cast<Entity*>(lua_touserdata(L, 1));
|
||||||
|
lua_pushinteger(L, entity->GetBounds().x);
|
||||||
|
lua_pushinteger(L, entity->GetBounds().y);
|
||||||
|
lua_pushinteger(L, entity->GetBounds().w);
|
||||||
|
lua_pushinteger(L, entity->GetBounds().h);
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getType(lua_State* L) {
|
||||||
|
Entity* entity = static_cast<Entity*>(lua_touserdata(L, 1));
|
||||||
|
lua_pushstring(L, entity->GetType());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static const luaL_Reg entityLib[] = {
|
static const luaL_Reg entityLib[] = {
|
||||||
{"SetRoomIndex", setRoomIndex},
|
{"SetRoomIndex", setRoomIndex},
|
||||||
{"SetOrigin", setOrigin},
|
{"SetOrigin", setOrigin},
|
||||||
{"SetMotion", setMotion},
|
{"SetMotion", setMotion},
|
||||||
|
{"SetBounds", setBounds},
|
||||||
{"GetRoomIndex", getRoomIndex},
|
{"GetRoomIndex", getRoomIndex},
|
||||||
{"GetOrigin", getOrigin},
|
{"GetOrigin", getOrigin},
|
||||||
{"GetMotion", getMotion},
|
{"GetMotion", getMotion},
|
||||||
|
{"GetBounds", getBounds},
|
||||||
|
{"GetType", getType},
|
||||||
{nullptr, nullptr}
|
{nullptr, nullptr}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -30,8 +30,3 @@ $(OUTDIR):
|
|||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o *.a *.exe
|
|
||||||
|
|
||||||
rebuild: clean all
|
|
||||||
|
|||||||
+23
-10
@@ -37,10 +37,17 @@
|
|||||||
#include "lua.hpp"
|
#include "lua.hpp"
|
||||||
|
|
||||||
#include "entity_api.hpp"
|
#include "entity_api.hpp"
|
||||||
#include "map_system_api.hpp"
|
#include "character_api.hpp"
|
||||||
#include "monster_system_api.hpp"
|
#include "character_manager_api.hpp"
|
||||||
#include "room_system_api.hpp"
|
#include "region_api.hpp"
|
||||||
#include "waypoint_system_api.hpp"
|
#include "region_pager_api.hpp"
|
||||||
|
//#include "monster_api.hpp"
|
||||||
|
//#include "monster_manager_api.hpp"
|
||||||
|
#include "network_api.hpp"
|
||||||
|
#include "room_api.hpp"
|
||||||
|
#include "room_manager_api.hpp"
|
||||||
|
#include "trigger_api.hpp"
|
||||||
|
#include "trigger_manager_api.hpp"
|
||||||
|
|
||||||
//these libs are loaded by lua.c and are readily available to any Lua program
|
//these libs are loaded by lua.c and are readily available to any Lua program
|
||||||
static const luaL_Reg loadedlibs[] = {
|
static const luaL_Reg loadedlibs[] = {
|
||||||
@@ -58,14 +65,20 @@ static const luaL_Reg loadedlibs[] = {
|
|||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//these libs are preloaded and must be required before used
|
//these libs are preloaded and must be required before used
|
||||||
static const luaL_Reg preloadedlibs[] = {
|
static const luaL_Reg preloadedlibs[] = {
|
||||||
{TORTUGA_ENTITY_API, openEntityAPI},
|
{TORTUGA_ENTITY_API, openEntityAPI}, //required by derived classes
|
||||||
{TORTUGA_MAP_SYSTEM_API, openMapSystemAPI},
|
{TORTUGA_CHARACTER_API, openCharacterAPI},
|
||||||
{TORTUGA_MONSTER_SYSTEM_API, openMonsterSystemAPI},
|
{TORTUGA_CHARACTER_MANAGER_API, openCharacterManagerAPI},
|
||||||
{TORTUGA_ROOM_SYSTEM_API, openRoomSystemAPI},
|
// {TORTUGA_MONSTER_API, openMonsterAPI},
|
||||||
{TORTUGA_WAYPOINT_SYSTEM_API, openWaypointSystemAPI},
|
// {TORTUGA_MONSTER_MANAGER_API, openMonsterManagerAPI},
|
||||||
|
{TORTUGA_NETWORK_API, openNetworkAPI},
|
||||||
|
{TORTUGA_REGION_API, openRegionAPI},
|
||||||
|
{TORTUGA_REGION_PAGER_API, openRegionPagerAPI},
|
||||||
|
{TORTUGA_ROOM_API, openRoomAPI},
|
||||||
|
{TORTUGA_ROOM_MANAGER_API, openRoomManagerAPI},
|
||||||
|
{TORTUGA_TRIGGER_API, openTriggerAPI},
|
||||||
|
{TORTUGA_TRIGGER_MANAGER_API, openTriggerManagerAPI},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
#include "config_utility.hpp"
|
#include "config_utility.hpp"
|
||||||
#include "room_manager.hpp"
|
#include "room_manager.hpp"
|
||||||
#include "udp_network_utility.hpp"
|
#include "udp_network_utility.hpp"
|
||||||
#include "waypoint_manager.hpp"
|
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|||||||
+13
-3
@@ -1,5 +1,5 @@
|
|||||||
#include directories
|
#include directories
|
||||||
INCLUDES+=. accounts characters clients entities monsters rooms server_utilities waypoints ../common/debugging ../common/gameplay ../common/map ../common/network ../common/network/packet_types ../common/utilities
|
INCLUDES+=SDL . accounts characters clients entities rooms server_utilities triggers ../common/debugging ../common/gameplay ../common/map ../common/network ../common/network/packet_types ../common/utilities
|
||||||
|
|
||||||
#libraries
|
#libraries
|
||||||
#the order of the $(LIBS) is important, at least for MinGW
|
#the order of the $(LIBS) is important, at least for MinGW
|
||||||
@@ -8,6 +8,10 @@ ifeq ($(OS),Windows_NT)
|
|||||||
LIBS+=-lwsock32 -liphlpapi -lmingw32
|
LIBS+=-lwsock32 -liphlpapi -lmingw32
|
||||||
endif
|
endif
|
||||||
LIBS+=-lSDLmain -lSDL -llua -lsqlite3
|
LIBS+=-lSDLmain -lSDL -llua -lsqlite3
|
||||||
|
ifeq ($(shell uname), Linux)
|
||||||
|
#I don't know what this does, but Ubuntu needs it
|
||||||
|
LIBS+=-ldl
|
||||||
|
endif
|
||||||
|
|
||||||
#flags
|
#flags
|
||||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||||
@@ -29,10 +33,10 @@ all: $(OBJ) $(OUT)
|
|||||||
$(MAKE) -C characters
|
$(MAKE) -C characters
|
||||||
$(MAKE) -C clients
|
$(MAKE) -C clients
|
||||||
$(MAKE) -C entities
|
$(MAKE) -C entities
|
||||||
$(MAKE) -C monsters
|
# $(MAKE) -C monsters
|
||||||
$(MAKE) -C rooms
|
$(MAKE) -C rooms
|
||||||
$(MAKE) -C server_utilities
|
$(MAKE) -C server_utilities
|
||||||
$(MAKE) -C waypoints
|
$(MAKE) -C triggers
|
||||||
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS)
|
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS)
|
||||||
|
|
||||||
$(OBJ): | $(OBJDIR)
|
$(OBJ): | $(OBJDIR)
|
||||||
@@ -49,6 +53,12 @@ $(OBJDIR)/%.o: %.cpp
|
|||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
$(RM) *.o *.a *.exe
|
$(RM) *.o *.a *.exe
|
||||||
|
else ifeq ($(shell uname), Linux)
|
||||||
|
find . -type f -name *.o -exec rm -f -r -v {} \;
|
||||||
|
find . -type f -name *.a -exec rm -f -r -v {} \;
|
||||||
|
rm -f -v out/client out/server
|
||||||
|
endif
|
||||||
|
|
||||||
rebuild: clean all
|
rebuild: clean all
|
||||||
|
|||||||
@@ -30,8 +30,3 @@ $(OUTDIR):
|
|||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o *.a *.exe
|
|
||||||
|
|
||||||
rebuild: clean all
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
static int setAvatar(lua_State* L) {
|
static int setAvatar(lua_State* L) {
|
||||||
MonsterData* monster = static_cast<MonsterData*>(lua_touserdata(L, 1));
|
MonsterData* monster = static_cast<MonsterData*>(lua_touserdata(L, 1));
|
||||||
monster->SetAvatar(lua_tostring(L, 2));
|
monster->SetAvatar(lua_tostring(L, 2));
|
||||||
//TODO: send an update to the clients?
|
//TODO: (1) send an update to the clients?
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,27 +61,27 @@ static const luaL_Reg monsterLib[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
LUAMOD_API int openMonsterAPI(lua_State* L) {
|
LUAMOD_API int openMonsterAPI(lua_State* L) {
|
||||||
//the local table
|
|
||||||
luaL_newlib(L, monsterLib);
|
|
||||||
|
|
||||||
//get the parent table
|
//get the parent table
|
||||||
luaL_requiref(L, TORTUGA_ENTITY_API, openEntityAPI, false);
|
luaL_requiref(L, TORTUGA_ENTITY_API, openEntityAPI, false);
|
||||||
|
|
||||||
//clone the parent table into the local table
|
//the local table
|
||||||
|
luaL_newlib(L, monsterLib);
|
||||||
|
|
||||||
|
//merge the local table into the parent table
|
||||||
lua_pushnil(L); //first key
|
lua_pushnil(L); //first key
|
||||||
while(lua_next(L, -2)) {
|
while(lua_next(L, -2)) {
|
||||||
//copy the key-value pair
|
//copy the key-value pair
|
||||||
lua_pushvalue(L, -2);
|
lua_pushvalue(L, -2);
|
||||||
lua_pushvalue(L, -2);
|
lua_pushvalue(L, -2);
|
||||||
|
|
||||||
//push the copy to the local table
|
//push the copy to the parent table
|
||||||
lua_settable(L, -6);
|
lua_settable(L, -6);
|
||||||
|
|
||||||
//pop the original value before continuing
|
//pop the original value before continuing
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//remove the parent table, leaving the expanded child table
|
//remove the local table, leaving the expanded parent table
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -21,6 +21,23 @@
|
|||||||
*/
|
*/
|
||||||
#include "monster_data.hpp"
|
#include "monster_data.hpp"
|
||||||
|
|
||||||
|
MonsterData::MonsterData(std::string _avatar, int _scriptRef):
|
||||||
|
Entity("monster"),
|
||||||
|
avatar(_avatar),
|
||||||
|
scriptRef(_scriptRef)
|
||||||
|
{
|
||||||
|
//EMPTY
|
||||||
|
}
|
||||||
|
|
||||||
|
void MonsterData::Update() {
|
||||||
|
Entity::Update();
|
||||||
|
//TODO: (0) call the script reference
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//accessors & mutators
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
std::string MonsterData::SetAvatar(std::string s) {
|
std::string MonsterData::SetAvatar(std::string s) {
|
||||||
return avatar = s;
|
return avatar = s;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,13 +24,26 @@
|
|||||||
|
|
||||||
#include "entity.hpp"
|
#include "entity.hpp"
|
||||||
|
|
||||||
|
#include "lua.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
/* DOCS: Monster attributes, read more
|
||||||
|
* species (avatar, script)
|
||||||
|
* level
|
||||||
|
* health/mana
|
||||||
|
* permadeath/respawn
|
||||||
|
*/
|
||||||
|
|
||||||
class MonsterData: public Entity {
|
class MonsterData: public Entity {
|
||||||
public:
|
public:
|
||||||
MonsterData() = default;
|
MonsterData(std::string avatar, int scriptRef);
|
||||||
~MonsterData() = default;
|
~MonsterData() = default;
|
||||||
|
|
||||||
|
virtual void Update();
|
||||||
|
|
||||||
|
//accessors & mutators
|
||||||
|
|
||||||
std::string SetAvatar(std::string);
|
std::string SetAvatar(std::string);
|
||||||
std::string GetAvatar();
|
std::string GetAvatar();
|
||||||
|
|
||||||
@@ -41,7 +54,7 @@ private:
|
|||||||
friend class MonsterManager;
|
friend class MonsterManager;
|
||||||
|
|
||||||
std::string avatar;
|
std::string avatar;
|
||||||
int scriptRef;
|
int scriptRef = LUA_NOREF;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -29,46 +29,66 @@ MonsterManager::~MonsterManager() {
|
|||||||
UnloadAll();
|
UnloadAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
int MonsterManager::Create(std::string) {
|
int MonsterManager::Create(std::string avatar, int scriptRef) {
|
||||||
//Create
|
//implicitly create the new
|
||||||
|
elementMap.emplace(counter, MonsterData(avatar, scriptRef));
|
||||||
|
|
||||||
|
//TODO: do various things like saving to the database
|
||||||
|
return counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: (1) monster load, save
|
||||||
|
|
||||||
void MonsterManager::Unload(int uid) {
|
void MonsterManager::Unload(int uid) {
|
||||||
//Unload
|
elementMap.erase(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MonsterManager::UnloadAll() {
|
void MonsterManager::UnloadAll() {
|
||||||
//UnloadAll
|
elementMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
std::map<int, MonsterData>::iterator it = elementMap.begin();
|
||||||
|
while (it != elementMap.end()) {
|
||||||
|
if (fn(*it)) {
|
||||||
|
it = elementMap.erase(it);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MonsterData* MonsterManager::Get(int uid) {
|
MonsterData* MonsterManager::Get(int uid) {
|
||||||
//Get
|
std::map<int, MonsterData>::iterator it = elementMap.find(uid);
|
||||||
|
|
||||||
|
if (it == elementMap.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MonsterManager::GetLoadedCount() {
|
int MonsterManager::GetLoadedCount() {
|
||||||
//GetLoadedCount
|
return elementMap.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<int, MonsterData>* MonsterManager::GetContainer() {
|
std::map<int, MonsterData>* MonsterManager::GetContainer() {
|
||||||
//GetContainer
|
return &elementMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_State* MonsterManager::SetLuaState(lua_State* L) {
|
lua_State* MonsterManager::SetLuaState(lua_State* L) {
|
||||||
//SetLuaState
|
return lua = L;
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_State* MonsterManager::GetLuaState() {
|
lua_State* MonsterManager::GetLuaState() {
|
||||||
//GetLuaState
|
return lua;
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlite3* MonsterManager::SetDatabase(sqlite3* db) {
|
sqlite3* MonsterManager::SetDatabase(sqlite3* db) {
|
||||||
//SetDatabase
|
return database = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlite3* MonsterManager::GetDatabase() {
|
sqlite3* MonsterManager::GetDatabase() {
|
||||||
//GetDatabase
|
return database;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public:
|
|||||||
~MonsterManager();
|
~MonsterManager();
|
||||||
|
|
||||||
//common public methods
|
//common public methods
|
||||||
int Create(std::string);
|
int Create(std::string avatar, int scriptRef);
|
||||||
void Unload(int uid);
|
void Unload(int uid);
|
||||||
|
|
||||||
void UnloadAll();
|
void UnloadAll();
|
||||||
@@ -57,6 +57,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
//members
|
//members
|
||||||
std::map<int, MonsterData> elementMap;
|
std::map<int, MonsterData> elementMap;
|
||||||
|
int counter = 0;
|
||||||
lua_State* lua = nullptr;
|
lua_State* lua = nullptr;
|
||||||
sqlite3* database = nullptr;
|
sqlite3* database = nullptr;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,7 +23,54 @@
|
|||||||
|
|
||||||
#include "monster_manager.hpp"
|
#include "monster_manager.hpp"
|
||||||
|
|
||||||
|
static int create(lua_State* L) {
|
||||||
|
MonsterManager* mgr = static_cast<MonsterManager* const>(lua_touserdata(L, 1));
|
||||||
|
int index = mgr->Create(lua_tostring(L, 2), lua_tointeger(L, 3));
|
||||||
|
MonsterData* monster = mgr->Get(index);
|
||||||
|
lua_pushlightuserdata(L, static_cast<void*>(monster));
|
||||||
|
lua_pushinteger(L, index);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TOOD: this needs to take the userdata as a parameter too
|
||||||
|
static int unload(lua_State* L) {
|
||||||
|
MonsterManager* mgr = static_cast<MonsterManager* const>(lua_touserdata(L, 1));
|
||||||
|
mgr->Unload(lua_tointeger(L, 2));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int unloadAll(lua_State* L) {
|
||||||
|
MonsterManager* mgr = static_cast<MonsterManager* const>(lua_touserdata(L, 1));
|
||||||
|
mgr->UnloadAll();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int unloadIf(lua_State* L) {
|
||||||
|
MonsterManager* mgr = static_cast<MonsterManager* const>(lua_touserdata(L, 1));
|
||||||
|
//TODO: unloadIf
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get(lua_State* L) {
|
||||||
|
MonsterManager* mgr = static_cast<MonsterManager* const>(lua_touserdata(L, 1));
|
||||||
|
MonsterData* monster = mgr->Get(lua_tointeger(L, 2));
|
||||||
|
lua_pushlightuserdata(L, static_cast<void*>(monster));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getLoadedCount(lua_State* L) {
|
||||||
|
MonsterManager* mgr = static_cast<MonsterManager* const>(lua_touserdata(L, 1));
|
||||||
|
lua_pushinteger(L, mgr->GetLoadedCount());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static const luaL_Reg monsterManagerLib[] = {
|
static const luaL_Reg monsterManagerLib[] = {
|
||||||
|
{"Create", create},
|
||||||
|
{"Unload", unload},
|
||||||
|
{"UnloadAll", unloadAll},
|
||||||
|
// {"UnloadIf", unloadIf},
|
||||||
|
{"Get", get},
|
||||||
|
{"GetLoadedCount", getLoadedCount},
|
||||||
{nullptr, nullptr}
|
{nullptr, nullptr}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,55 +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 "monster_system_api.hpp"
|
|
||||||
|
|
||||||
//all monster API headers
|
|
||||||
#include "monster_api.hpp"
|
|
||||||
#include "monster_manager_api.hpp"
|
|
||||||
|
|
||||||
//useful "globals"
|
|
||||||
//...
|
|
||||||
|
|
||||||
//This mimics linit.c to create a nested collection of all monster modules.
|
|
||||||
static const luaL_Reg funcs[] = {
|
|
||||||
{nullptr, nullptr}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const luaL_Reg libs[] = {
|
|
||||||
{"Monster", openMonsterAPI},
|
|
||||||
{"MonsterManager", openMonsterManagerAPI},
|
|
||||||
{nullptr, nullptr}
|
|
||||||
};
|
|
||||||
|
|
||||||
int openMonsterSystemAPI(lua_State* L) {
|
|
||||||
//create the table
|
|
||||||
luaL_newlibtable(L, libs);
|
|
||||||
|
|
||||||
//push the "global" functions
|
|
||||||
luaL_setfuncs(L, funcs, 0);
|
|
||||||
|
|
||||||
//push the substable
|
|
||||||
for (const luaL_Reg* lib = libs; lib->func; lib++) {
|
|
||||||
lib->func(L);
|
|
||||||
lua_setfield(L, -2, lib->name);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#config
|
#config
|
||||||
INCLUDES+=. ../characters ../entities ../monsters ../server_utilities ../waypoints ../../common/gameplay ../../common/map ../../common/utilities
|
INCLUDES+=. ../characters ../entities ../monsters ../server_utilities ../triggers ../../common/gameplay ../../common/map ../../common/utilities
|
||||||
LIBS+=
|
LIBS+=
|
||||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||||
|
|
||||||
@@ -30,8 +30,3 @@ $(OUTDIR):
|
|||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o *.a *.exe
|
|
||||||
|
|
||||||
rebuild: clean all
|
|
||||||
|
|||||||
@@ -23,6 +23,9 @@
|
|||||||
|
|
||||||
#include "room_data.hpp"
|
#include "room_data.hpp"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
static int setRoomName(lua_State* L) {
|
static int setRoomName(lua_State* L) {
|
||||||
RoomData* room = reinterpret_cast<RoomData*>(lua_touserdata(L, 1));
|
RoomData* room = reinterpret_cast<RoomData*>(lua_touserdata(L, 1));
|
||||||
room->SetName(lua_tostring(L, 2));
|
room->SetName(lua_tostring(L, 2));
|
||||||
@@ -53,15 +56,67 @@ static int getPager(lua_State* L) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
static int getMonsterMgr(lua_State* L) {
|
static int getMonsterMgr(lua_State* L) {
|
||||||
RoomData* room = reinterpret_cast<RoomData*>(lua_touserdata(L, 1));
|
RoomData* room = reinterpret_cast<RoomData*>(lua_touserdata(L, 1));
|
||||||
lua_pushlightuserdata(L, reinterpret_cast<void*>(room->GetMonsterMgr()) );
|
lua_pushlightuserdata(L, reinterpret_cast<void*>(room->GetMonsterMgr()) );
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
static int getWaypointMgr(lua_State* L) {
|
static int getTriggerMgr(lua_State* L) {
|
||||||
RoomData* room = reinterpret_cast<RoomData*>(lua_touserdata(L, 1));
|
RoomData* room = reinterpret_cast<RoomData*>(lua_touserdata(L, 1));
|
||||||
lua_pushlightuserdata(L, reinterpret_cast<void*>(room->GetWaypointMgr()) );
|
lua_pushlightuserdata(L, reinterpret_cast<void*>(room->GetTriggerMgr()) );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int forEachCharacter(lua_State* L) {
|
||||||
|
RoomData* room = reinterpret_cast<RoomData*>(lua_touserdata(L, 1));
|
||||||
|
//pass each character to the given function
|
||||||
|
for (auto& it : *room->GetCharacterList()) {
|
||||||
|
lua_pushvalue(L, -1);
|
||||||
|
lua_pushlightuserdata(L, static_cast<void*>(it));
|
||||||
|
//call each iteration, throwing an exception if something happened
|
||||||
|
if (lua_pcall(L, 1, 0, 0) != LUA_OK) {
|
||||||
|
std::ostringstream os;
|
||||||
|
os << "Lua error: ";
|
||||||
|
os << lua_tostring(L, -1);
|
||||||
|
throw(std::runtime_error(os.str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
static int forEachMonster(lua_State* L) {
|
||||||
|
RoomData* room = reinterpret_cast<RoomData*>(lua_touserdata(L, 1));
|
||||||
|
MonsterManager* monsterMgr = room->GetMonsterMgr();
|
||||||
|
//pass each monster to the given function
|
||||||
|
for (auto& it : *monsterMgr->GetContainer()) {
|
||||||
|
lua_pushvalue(L, -1);
|
||||||
|
lua_pushlightuserdata(L, static_cast<void*>(&it.second));
|
||||||
|
//call each iteration, throwing an exception if something happened
|
||||||
|
if (lua_pcall(L, 1, 0, 0) != LUA_OK) {
|
||||||
|
std::ostringstream os;
|
||||||
|
os << "Lua error: ";
|
||||||
|
os << lua_tostring(L, -1);
|
||||||
|
throw(std::runtime_error(os.str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int setOnTick(lua_State* L) {
|
||||||
|
RoomData* room = reinterpret_cast<RoomData*>(lua_touserdata(L, 1));
|
||||||
|
luaL_unref(L, LUA_REGISTRYINDEX, room->GetTickReference());
|
||||||
|
room->SetTickReference(luaL_ref(L, LUA_REGISTRYINDEX));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getOnTick(lua_State* L) {
|
||||||
|
RoomData* room = reinterpret_cast<RoomData*>(lua_touserdata(L, 1));
|
||||||
|
lua_rawgeti(L, LUA_REGISTRYINDEX, room->GetTickReference());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,8 +140,14 @@ static const luaL_Reg roomLib[] = {
|
|||||||
{"GetTileset", getTilesetName},
|
{"GetTileset", getTilesetName},
|
||||||
|
|
||||||
{"GetPager",getPager},
|
{"GetPager",getPager},
|
||||||
{"GetMonsterMgr",getMonsterMgr},
|
// {"GetMonsterMgr",getMonsterMgr},
|
||||||
{"GetWaypointMgr",getWaypointMgr},
|
{"GetTriggerMgr",getTriggerMgr},
|
||||||
|
|
||||||
|
{"ForEachCharacter", forEachCharacter},
|
||||||
|
// {"ForEachMonster", forEachMonster},
|
||||||
|
|
||||||
|
{"SetOnTick", setOnTick},
|
||||||
|
{"GetOnTick", getOnTick},
|
||||||
|
|
||||||
{"Initialize", initialize},
|
{"Initialize", initialize},
|
||||||
{nullptr, nullptr}
|
{nullptr, nullptr}
|
||||||
|
|||||||
+111
-6
@@ -21,6 +21,87 @@
|
|||||||
*/
|
*/
|
||||||
#include "room_data.hpp"
|
#include "room_data.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stack>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
//TODO: (9) character collisions should be preformed client-side
|
||||||
|
void RoomData::RunFrame() {
|
||||||
|
//get the hook
|
||||||
|
lua_rawgeti(lua, LUA_REGISTRYINDEX, tickRef);
|
||||||
|
|
||||||
|
if (!lua_isnil(lua, -1)) {
|
||||||
|
//call the tick function, with this as a parameter
|
||||||
|
lua_pushlightuserdata(lua, this);
|
||||||
|
if (lua_pcall(lua, 1, 0, 0) != LUA_OK) {
|
||||||
|
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lua_pop(lua, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//update the entities in the room
|
||||||
|
for (auto& it : characterList) {
|
||||||
|
it->Update();
|
||||||
|
}
|
||||||
|
//TODO: (3) iterate through the monster map
|
||||||
|
//TODO: (3) trigger script for monsters
|
||||||
|
|
||||||
|
//build a list of game entities
|
||||||
|
std::stack<Entity*> entityStack;
|
||||||
|
for (auto& it : characterList) {
|
||||||
|
entityStack.push(it);
|
||||||
|
}
|
||||||
|
//TODO: (3) push the monster entities
|
||||||
|
|
||||||
|
//compare the triggers to the entities, using their real hitboxes
|
||||||
|
//NOTE: this stack solution should prevent problems when modifying the various lists
|
||||||
|
while(entityStack.size()) {
|
||||||
|
//get the entity & hitbox
|
||||||
|
Entity* entity = entityStack.top();
|
||||||
|
BoundingBox entityBox = entity->GetBounds() + entity->GetOrigin();
|
||||||
|
|
||||||
|
//get the trigger pair & hitbox
|
||||||
|
for (auto& triggerPair : *triggerMgr.GetContainer()) {
|
||||||
|
BoundingBox triggerBox = triggerPair.second.GetBoundingBox() + triggerPair.second.GetOrigin();
|
||||||
|
|
||||||
|
//find all collisions
|
||||||
|
if (entityBox.CheckOverlap(triggerBox)) {
|
||||||
|
//skip members of the exclusion list
|
||||||
|
if (std::any_of(triggerPair.second.GetExclusionList()->begin(), triggerPair.second.GetExclusionList()->end(), [entity](Entity* ptr) -> bool {
|
||||||
|
return entity == ptr;
|
||||||
|
})) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//run the trigger script
|
||||||
|
lua_rawgeti(lua, LUA_REGISTRYINDEX, triggerPair.second.GetScriptReference());
|
||||||
|
lua_pushlightuserdata(lua, entity);
|
||||||
|
|
||||||
|
if (lua_pcall(lua, 1, 0, 0) != LUA_OK) {
|
||||||
|
//error
|
||||||
|
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) ));
|
||||||
|
}
|
||||||
|
|
||||||
|
//push to the exclusion list
|
||||||
|
triggerPair.second.GetExclusionList()->push_back(entity);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//remove members of the exclusion list
|
||||||
|
//NOTE: characters in different rooms won't be removed, but that shouldn't be a problem
|
||||||
|
triggerPair.second.GetExclusionList()->remove_if([entity](Entity* ptr) -> bool {
|
||||||
|
return entity == ptr;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//next
|
||||||
|
entityStack.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string RoomData::SetName(std::string s) {
|
std::string RoomData::SetName(std::string s) {
|
||||||
return roomName = s;
|
return roomName = s;
|
||||||
}
|
}
|
||||||
@@ -41,14 +122,38 @@ RegionPagerLua* RoomData::GetPager() {
|
|||||||
return &pager;
|
return &pager;
|
||||||
}
|
}
|
||||||
|
|
||||||
MonsterManager* RoomData::GetMonsterMgr() {
|
TriggerManager* RoomData::GetTriggerMgr() {
|
||||||
return &monsterMgr;
|
return &triggerMgr;
|
||||||
}
|
|
||||||
|
|
||||||
WaypointManager* RoomData::GetWaypointMgr() {
|
|
||||||
return &waypointMgr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<CharacterData*>* RoomData::GetCharacterList() {
|
std::list<CharacterData*>* RoomData::GetCharacterList() {
|
||||||
return &characterList;
|
return &characterList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lua_State* RoomData::SetLuaState(lua_State* L) {
|
||||||
|
lua = L;
|
||||||
|
pager.SetLuaState(lua);
|
||||||
|
triggerMgr.SetLuaState(lua);
|
||||||
|
return lua;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_State* RoomData::GetLuaState() {
|
||||||
|
return lua;
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3* RoomData::SetDatabase(sqlite3* db) {
|
||||||
|
database = db;
|
||||||
|
return database;
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3* RoomData::GetDatabase() {
|
||||||
|
return database;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RoomData::SetTickReference(int i) {
|
||||||
|
return tickRef = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RoomData::GetTickReference() {
|
||||||
|
return tickRef;
|
||||||
|
}
|
||||||
+25
-10
@@ -23,11 +23,11 @@
|
|||||||
#define ROOMDATA_HPP_
|
#define ROOMDATA_HPP_
|
||||||
|
|
||||||
#include "character_data.hpp"
|
#include "character_data.hpp"
|
||||||
#include "monster_manager.hpp"
|
|
||||||
#include "region_pager_lua.hpp"
|
#include "region_pager_lua.hpp"
|
||||||
#include "waypoint_manager.hpp"
|
#include "trigger_manager.hpp"
|
||||||
|
|
||||||
#include "lua.hpp"
|
#include "lua.hpp"
|
||||||
|
#include "sqlite3.h"
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -37,6 +37,8 @@ public:
|
|||||||
RoomData() = default;
|
RoomData() = default;
|
||||||
~RoomData() = default;
|
~RoomData() = default;
|
||||||
|
|
||||||
|
void RunFrame();
|
||||||
|
|
||||||
//accessors and mutators
|
//accessors and mutators
|
||||||
std::string SetName(std::string);
|
std::string SetName(std::string);
|
||||||
std::string GetName();
|
std::string GetName();
|
||||||
@@ -45,23 +47,36 @@ public:
|
|||||||
std::string GetTileset();
|
std::string GetTileset();
|
||||||
|
|
||||||
RegionPagerLua* GetPager();
|
RegionPagerLua* GetPager();
|
||||||
MonsterManager* GetMonsterMgr();
|
TriggerManager* GetTriggerMgr();
|
||||||
WaypointManager* GetWaypointMgr();
|
|
||||||
std::list<CharacterData*>* GetCharacterList();
|
std::list<CharacterData*>* GetCharacterList();
|
||||||
|
|
||||||
//TODO: triggers for unload, save, per-second, player enter, player exit, etc.
|
//API interfaces
|
||||||
|
lua_State* SetLuaState(lua_State* L);
|
||||||
|
lua_State* GetLuaState();
|
||||||
|
sqlite3* SetDatabase(sqlite3* db);
|
||||||
|
sqlite3* GetDatabase();
|
||||||
|
|
||||||
|
//hooks
|
||||||
|
int SetTickReference(int i);
|
||||||
|
int GetTickReference();
|
||||||
|
//TODO: other triggers like player entry & exit, etc.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class RoomManager;
|
//metadata
|
||||||
|
|
||||||
//members
|
|
||||||
std::string roomName;
|
std::string roomName;
|
||||||
std::string tilesetName;
|
std::string tilesetName;
|
||||||
|
|
||||||
|
//members
|
||||||
RegionPagerLua pager;
|
RegionPagerLua pager;
|
||||||
MonsterManager monsterMgr;
|
TriggerManager triggerMgr;
|
||||||
WaypointManager waypointMgr;
|
|
||||||
std::list<CharacterData*> characterList;
|
std::list<CharacterData*> characterList;
|
||||||
|
|
||||||
|
//API
|
||||||
|
lua_State* lua = nullptr;
|
||||||
|
sqlite3* database = nullptr;
|
||||||
|
|
||||||
|
//hooks
|
||||||
|
int tickRef = LUA_NOREF;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -35,29 +35,79 @@ int RoomManager::Create(std::string roomName, std::string tileset) {
|
|||||||
newRoom->SetName(roomName);
|
newRoom->SetName(roomName);
|
||||||
newRoom->SetTileset(tileset);
|
newRoom->SetTileset(tileset);
|
||||||
|
|
||||||
newRoom->pager.SetLuaState(lua);
|
newRoom->SetLuaState(lua);
|
||||||
newRoom->monsterMgr.SetLuaState(lua);
|
newRoom->SetDatabase(database);
|
||||||
newRoom->monsterMgr.SetDatabase(database);
|
|
||||||
newRoom->waypointMgr.SetLuaState(lua);
|
//get the hook
|
||||||
|
lua_rawgeti(lua, LUA_REGISTRYINDEX, createRef);
|
||||||
|
|
||||||
|
if(!lua_isnil(lua, -1)) {
|
||||||
|
lua_pushlightuserdata(lua, newRoom);
|
||||||
|
lua_pushinteger(lua, counter);
|
||||||
|
//call the function, 2 arg, 0 return
|
||||||
|
if (lua_pcall(lua, 2, 0, 0) != LUA_OK) {
|
||||||
|
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//finish the routine
|
//finish the routine
|
||||||
return counter++;
|
return counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoomManager::UnloadAll() {
|
void RoomManager::UnloadAll() {
|
||||||
|
//get the hook
|
||||||
|
lua_rawgeti(lua, LUA_REGISTRYINDEX, unloadRef);
|
||||||
|
|
||||||
|
if(!lua_isnil(lua, -1)) {
|
||||||
|
//pass each room to the hook
|
||||||
|
for (auto& it : elementMap) {
|
||||||
|
lua_pushvalue(lua, -1); //copy the hook
|
||||||
|
lua_pushlightuserdata(lua, &it.second);
|
||||||
|
lua_pushinteger(lua, it.first);
|
||||||
|
//call the function, 2 arg, 0 return
|
||||||
|
if (lua_pcall(lua, 2, 0, 0) != LUA_OK) {
|
||||||
|
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//pop the hook or nil
|
||||||
|
lua_pop(lua, 1);
|
||||||
|
|
||||||
elementMap.clear();
|
elementMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoomManager::UnloadIf(std::function<bool(std::pair<const int, RoomData const&>)> fn) {
|
void RoomManager::UnloadIf(std::function<bool(std::pair<const int, RoomData const&>)> fn) {
|
||||||
|
//get the hook
|
||||||
|
lua_rawgeti(lua, LUA_REGISTRYINDEX, unloadRef);
|
||||||
|
|
||||||
|
//get the element
|
||||||
std::map<int, RoomData>::iterator it = elementMap.begin();
|
std::map<int, RoomData>::iterator it = elementMap.begin();
|
||||||
|
|
||||||
|
//jenky pattern
|
||||||
while (it != elementMap.end()) {
|
while (it != elementMap.end()) {
|
||||||
if (fn(*it)) {
|
if (fn(*it)) {
|
||||||
|
|
||||||
|
if(!lua_isnil(lua, -1)) {
|
||||||
|
lua_pushvalue(lua, -1); //copy the hook
|
||||||
|
lua_pushlightuserdata(lua, &it->second);
|
||||||
|
lua_pushinteger(lua, it->first);
|
||||||
|
|
||||||
|
//call the function, 2 arg, 0 return
|
||||||
|
if (lua_pcall(lua, 2, 0, 0) != LUA_OK) {
|
||||||
|
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
it = elementMap.erase(it);
|
it = elementMap.erase(it);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//pop the hook or nil
|
||||||
|
lua_pop(lua, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoomManager::PushCharacter(CharacterData* character) {
|
void RoomManager::PushCharacter(CharacterData* character) {
|
||||||
@@ -71,7 +121,7 @@ void RoomManager::PushCharacter(CharacterData* character) {
|
|||||||
throw(std::runtime_error("Failed to push an character to a non-existant room"));
|
throw(std::runtime_error("Failed to push an character to a non-existant room"));
|
||||||
}
|
}
|
||||||
|
|
||||||
room->characterList.push_back(character);
|
room->GetCharacterList()->push_back(character);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoomManager::PopCharacter(CharacterData const* character) {
|
void RoomManager::PopCharacter(CharacterData const* character) {
|
||||||
@@ -86,7 +136,7 @@ void RoomManager::PopCharacter(CharacterData const* character) {
|
|||||||
throw(std::runtime_error("Failed to pop an character to a non-existant room"));
|
throw(std::runtime_error("Failed to pop an character to a non-existant room"));
|
||||||
}
|
}
|
||||||
|
|
||||||
room->characterList.remove_if([character](CharacterData* ptr) {
|
room->GetCharacterList()->remove_if([character](CharacterData* ptr) {
|
||||||
return character == ptr;
|
return character == ptr;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -119,7 +169,11 @@ std::map<int, RoomData>* RoomManager::GetContainer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lua_State* RoomManager::SetLuaState(lua_State* L) {
|
lua_State* RoomManager::SetLuaState(lua_State* L) {
|
||||||
return lua = L;
|
lua = L;
|
||||||
|
for (auto& it : elementMap) {
|
||||||
|
it.second.SetLuaState(lua);
|
||||||
|
}
|
||||||
|
return lua;
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_State* RoomManager::GetLuaState() {
|
lua_State* RoomManager::GetLuaState() {
|
||||||
@@ -127,9 +181,29 @@ lua_State* RoomManager::GetLuaState() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sqlite3* RoomManager::SetDatabase(sqlite3* db) {
|
sqlite3* RoomManager::SetDatabase(sqlite3* db) {
|
||||||
return database = db;
|
database = db;
|
||||||
|
for (auto& it : elementMap) {
|
||||||
|
it.second.SetDatabase(database);
|
||||||
|
}
|
||||||
|
return database;
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlite3* RoomManager::GetDatabase() {
|
sqlite3* RoomManager::GetDatabase() {
|
||||||
return database;
|
return database;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int RoomManager::SetCreateReference(int i) {
|
||||||
|
return createRef = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RoomManager::SetUnloadReference(int i) {
|
||||||
|
return unloadRef = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RoomManager::GetCreateReference() {
|
||||||
|
return createRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RoomManager::GetUnloadReference() {
|
||||||
|
return unloadRef;
|
||||||
|
}
|
||||||
|
|||||||
@@ -49,12 +49,19 @@ public:
|
|||||||
int GetLoadedCount();
|
int GetLoadedCount();
|
||||||
std::map<int, RoomData>* GetContainer();
|
std::map<int, RoomData>* GetContainer();
|
||||||
|
|
||||||
//hooks
|
//API interfaces
|
||||||
lua_State* SetLuaState(lua_State* L);
|
lua_State* SetLuaState(lua_State* L);
|
||||||
lua_State* GetLuaState();
|
lua_State* GetLuaState();
|
||||||
sqlite3* SetDatabase(sqlite3* db);
|
sqlite3* SetDatabase(sqlite3* db);
|
||||||
sqlite3* GetDatabase();
|
sqlite3* GetDatabase();
|
||||||
|
|
||||||
|
//hooks
|
||||||
|
int SetCreateReference(int i);
|
||||||
|
int SetUnloadReference(int i);
|
||||||
|
|
||||||
|
int GetCreateReference();
|
||||||
|
int GetUnloadReference();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend Singleton<RoomManager>;
|
friend Singleton<RoomManager>;
|
||||||
|
|
||||||
@@ -63,9 +70,15 @@ private:
|
|||||||
|
|
||||||
//members
|
//members
|
||||||
std::map<int, RoomData> elementMap;
|
std::map<int, RoomData> elementMap;
|
||||||
|
int counter = 0;
|
||||||
|
|
||||||
|
//API
|
||||||
lua_State* lua = nullptr;
|
lua_State* lua = nullptr;
|
||||||
sqlite3* database = nullptr;
|
sqlite3* database = nullptr;
|
||||||
int counter = 0;
|
|
||||||
|
//hooks
|
||||||
|
int createRef = LUA_NOREF;
|
||||||
|
int unloadRef = LUA_NOREF;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -96,10 +96,26 @@ int getRoom(lua_State* L) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int setOnCreate(lua_State* L) {
|
||||||
|
RoomManager& roomMgr = RoomManager::GetSingleton();
|
||||||
|
luaL_unref(L, LUA_REGISTRYINDEX, roomMgr.GetCreateReference());
|
||||||
|
roomMgr.SetCreateReference(luaL_ref(L, LUA_REGISTRYINDEX));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int setOnUnload(lua_State* L) {
|
||||||
|
RoomManager& roomMgr = RoomManager::GetSingleton();
|
||||||
|
luaL_unref(L, LUA_REGISTRYINDEX, roomMgr.GetUnloadReference());
|
||||||
|
roomMgr.SetUnloadReference(luaL_ref(L, LUA_REGISTRYINDEX));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const luaL_Reg roomManagerLib[] = {
|
static const luaL_Reg roomManagerLib[] = {
|
||||||
{"CreateRoom", createRoom},
|
{"CreateRoom", createRoom},
|
||||||
{"UnloadRoom", unloadRoom},
|
{"UnloadRoom", unloadRoom},
|
||||||
{"GetRoom", getRoom},
|
{"GetRoom", getRoom},
|
||||||
|
{"SetOnCreate", setOnCreate},
|
||||||
|
{"SetOnUnload", setOnUnload},
|
||||||
{nullptr, nullptr}
|
{nullptr, nullptr}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,55 +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 "room_system_api.hpp"
|
|
||||||
|
|
||||||
//all room API headers
|
|
||||||
#include "room_api.hpp"
|
|
||||||
#include "room_manager_api.hpp"
|
|
||||||
|
|
||||||
//useful "globals"
|
|
||||||
//...
|
|
||||||
|
|
||||||
//This mimics linit.c to create a nested collection of all room modules.
|
|
||||||
static const luaL_Reg funcs[] = {
|
|
||||||
{nullptr, nullptr}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const luaL_Reg libs[] = {
|
|
||||||
{"Room", openRoomAPI},
|
|
||||||
{"RoomManager", openRoomManagerAPI},
|
|
||||||
{nullptr, nullptr}
|
|
||||||
};
|
|
||||||
|
|
||||||
int openRoomSystemAPI(lua_State* L) {
|
|
||||||
//create the table
|
|
||||||
luaL_newlibtable(L, libs);
|
|
||||||
|
|
||||||
//push the "global" functions
|
|
||||||
luaL_setfuncs(L, funcs, 0);
|
|
||||||
|
|
||||||
//push the substable
|
|
||||||
for (const luaL_Reg* lib = libs; lib->func; lib++) {
|
|
||||||
lib->func(L);
|
|
||||||
lua_setfield(L, -2, lib->name);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
@@ -26,7 +26,6 @@
|
|||||||
#include "account_manager.hpp"
|
#include "account_manager.hpp"
|
||||||
#include "character_manager.hpp"
|
#include "character_manager.hpp"
|
||||||
#include "client_manager.hpp"
|
#include "client_manager.hpp"
|
||||||
#include "monster_manager.hpp"
|
|
||||||
#include "room_manager.hpp"
|
#include "room_manager.hpp"
|
||||||
|
|
||||||
//utilities
|
//utilities
|
||||||
@@ -38,6 +37,9 @@
|
|||||||
#include "serial_packet.hpp"
|
#include "serial_packet.hpp"
|
||||||
#include "singleton.hpp"
|
#include "singleton.hpp"
|
||||||
|
|
||||||
|
//server utilities
|
||||||
|
#include "server_utilities.hpp"
|
||||||
|
|
||||||
//APIs
|
//APIs
|
||||||
#include "lua.hpp"
|
#include "lua.hpp"
|
||||||
#include "sqlite3.h"
|
#include "sqlite3.h"
|
||||||
@@ -102,22 +104,13 @@ private:
|
|||||||
void hCharacterAttack(CharacterPacket* const);
|
void hCharacterAttack(CharacterPacket* const);
|
||||||
void hCharacterDamage(CharacterPacket* const);
|
void hCharacterDamage(CharacterPacket* const);
|
||||||
|
|
||||||
//character management
|
|
||||||
void hMonsterDamage(MonsterPacket* const);
|
|
||||||
|
|
||||||
//chat
|
//chat
|
||||||
void hTextBroadcast(TextPacket* const);
|
void hTextBroadcast(TextPacket* const);
|
||||||
void hTextSpeech(TextPacket* const);
|
void hTextSpeech(TextPacket* const);
|
||||||
void hTextWhisper(TextPacket* const);
|
void hTextWhisper(TextPacket* const);
|
||||||
|
|
||||||
//utility methods
|
//utility methods
|
||||||
void PumpPacket(SerialPacket* const);
|
|
||||||
void PumpPacketProximity(SerialPacket* const argPacket, int roomIndex, Vector2 position, int distance);
|
|
||||||
void CopyCharacterToPacket(CharacterPacket* const packet, int characterIndex);
|
|
||||||
void SaveServerState();
|
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;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "server_application.hpp"
|
#include "server_application.hpp"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
@@ -46,13 +47,14 @@ void ServerApplication::hCharacterCreate(CharacterPacket* const argPacket) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//push to the rooms
|
//push to the rooms
|
||||||
roomMgr.PushCharacter(characterMgr.Get(characterIndex));
|
CharacterData* characterData = characterMgr.Get(characterIndex);
|
||||||
|
roomMgr.PushCharacter(characterData);
|
||||||
|
|
||||||
//pump this character to all clients
|
//pump this character to all clients
|
||||||
CharacterPacket newPacket;
|
CharacterPacket newPacket;
|
||||||
CopyCharacterToPacket(&newPacket, characterIndex);
|
copyCharacterToPacket(&newPacket, characterIndex);
|
||||||
newPacket.type = SerialPacketType::CHARACTER_CREATE;
|
newPacket.type = SerialPacketType::CHARACTER_CREATE;
|
||||||
PumpPacket(&newPacket);
|
pumpPacketProximity(&newPacket, characterData->GetRoomIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::hCharacterDelete(CharacterPacket* const argPacket) {
|
void ServerApplication::hCharacterDelete(CharacterPacket* const argPacket) {
|
||||||
@@ -90,16 +92,17 @@ void ServerApplication::hCharacterDelete(CharacterPacket* const argPacket) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//pop from the rooms
|
//pop from the rooms
|
||||||
roomMgr.PopCharacter(characterMgr.Get(characterIndex));
|
CharacterData* characterData = characterMgr.Get(characterIndex);
|
||||||
|
roomMgr.PopCharacter(characterData);
|
||||||
//delete the character
|
|
||||||
characterMgr.Delete(characterIndex);
|
|
||||||
|
|
||||||
//pump character delete
|
//pump character delete
|
||||||
CharacterPacket newPacket;
|
CharacterPacket newPacket;
|
||||||
newPacket.type = SerialPacketType::CHARACTER_DELETE;
|
newPacket.type = SerialPacketType::CHARACTER_DELETE;
|
||||||
newPacket.characterIndex = characterIndex;
|
newPacket.characterIndex = characterIndex;
|
||||||
PumpPacket(static_cast<SerialPacket*>(&newPacket));
|
pumpPacketProximity(static_cast<SerialPacket*>(&newPacket), characterData->GetRoomIndex());
|
||||||
|
|
||||||
|
//delete the character
|
||||||
|
characterMgr.Delete(characterIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::hCharacterLoad(CharacterPacket* const argPacket) {
|
void ServerApplication::hCharacterLoad(CharacterPacket* const argPacket) {
|
||||||
@@ -126,13 +129,14 @@ void ServerApplication::hCharacterLoad(CharacterPacket* const argPacket) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//push to the rooms
|
//push to the rooms
|
||||||
roomMgr.PushCharacter(characterMgr.Get(characterIndex));
|
CharacterData* characterData = characterMgr.Get(characterIndex);
|
||||||
|
roomMgr.PushCharacter(characterData);
|
||||||
|
|
||||||
//pump this character to all clients
|
//pump this character to all clients
|
||||||
CharacterPacket newPacket;
|
CharacterPacket newPacket;
|
||||||
CopyCharacterToPacket(&newPacket, characterIndex);
|
copyCharacterToPacket(&newPacket, characterIndex);
|
||||||
newPacket.type = SerialPacketType::CHARACTER_CREATE;
|
newPacket.type = SerialPacketType::CHARACTER_CREATE;
|
||||||
PumpPacket(&newPacket);
|
pumpPacketProximity(&newPacket, characterData->GetRoomIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::hCharacterUnload(CharacterPacket* const argPacket) {
|
void ServerApplication::hCharacterUnload(CharacterPacket* const argPacket) {
|
||||||
@@ -161,14 +165,14 @@ void ServerApplication::hCharacterUnload(CharacterPacket* const argPacket) {
|
|||||||
//pop from the rooms
|
//pop from the rooms
|
||||||
roomMgr.PopCharacter(characterData);
|
roomMgr.PopCharacter(characterData);
|
||||||
|
|
||||||
//unload the character
|
|
||||||
characterMgr.Unload(argPacket->characterIndex);
|
|
||||||
|
|
||||||
//pump character delete
|
//pump character delete
|
||||||
CharacterPacket newPacket;
|
CharacterPacket newPacket;
|
||||||
newPacket.type = SerialPacketType::CHARACTER_DELETE;
|
newPacket.type = SerialPacketType::CHARACTER_DELETE;
|
||||||
newPacket.characterIndex = argPacket->characterIndex;
|
newPacket.characterIndex = argPacket->characterIndex;
|
||||||
PumpPacket(static_cast<SerialPacket*>(&newPacket));
|
pumpPacketProximity(static_cast<SerialPacket*>(&newPacket), characterData->GetRoomIndex());
|
||||||
|
|
||||||
|
//unload the character
|
||||||
|
characterMgr.Unload(argPacket->characterIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
@@ -180,10 +184,15 @@ void ServerApplication::hCharacterUnload(CharacterPacket* const argPacket) {
|
|||||||
void ServerApplication::hCharacterMovement(CharacterPacket* const argPacket) {
|
void ServerApplication::hCharacterMovement(CharacterPacket* const argPacket) {
|
||||||
//get the specified objects
|
//get the specified objects
|
||||||
AccountData* accountData = accountMgr.Get(argPacket->accountIndex);
|
AccountData* accountData = accountMgr.Get(argPacket->accountIndex);
|
||||||
|
|
||||||
|
if (!accountData) {
|
||||||
|
throw(std::runtime_error("Failed to move a character, missing account"));
|
||||||
|
}
|
||||||
|
|
||||||
CharacterData* characterData = characterMgr.Get(argPacket->characterIndex);
|
CharacterData* characterData = characterMgr.Get(argPacket->characterIndex);
|
||||||
|
|
||||||
if (!accountData || !characterData) {
|
if (!characterData) {
|
||||||
throw(std::runtime_error("Failed to move a character, missing data"));
|
throw(std::runtime_error("Failed to move a character, missing character"));
|
||||||
}
|
}
|
||||||
|
|
||||||
//get this account's client
|
//get this account's client
|
||||||
@@ -197,28 +206,19 @@ 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: (3) 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if moving rooms
|
//check if moving rooms
|
||||||
if (characterData->GetRoomIndex() != argPacket->roomIndex) {
|
if (characterData->GetRoomIndex() != argPacket->roomIndex) {
|
||||||
//delete from the old room
|
//set the character's origin and motion
|
||||||
CharacterPacket newPacket;
|
characterData->SetOrigin(argPacket->origin);
|
||||||
CopyCharacterToPacket(&newPacket, argPacket->characterIndex);
|
characterData->SetMotion(argPacket->motion);
|
||||||
newPacket.type = SerialPacketType::CHARACTER_DELETE;
|
|
||||||
PumpPacketProximity(&newPacket, characterData->GetRoomIndex(), characterData->GetOrigin(), -1);
|
|
||||||
|
|
||||||
//move the character between rooms
|
//send the delete & create messages
|
||||||
roomMgr.PopCharacter(characterData);
|
pumpAndChangeRooms(characterData, argPacket->roomIndex, argPacket->characterIndex);
|
||||||
characterData->SetRoomIndex(argPacket->roomIndex);
|
|
||||||
roomMgr.PushCharacter(characterData);
|
|
||||||
|
|
||||||
//create in the new room
|
|
||||||
CopyCharacterToPacket(&newPacket, argPacket->characterIndex);
|
|
||||||
newPacket.type = SerialPacketType::CHARACTER_CREATE;
|
|
||||||
PumpPacketProximity(&newPacket, characterData->GetRoomIndex(), characterData->GetOrigin(), -1);
|
|
||||||
}
|
}
|
||||||
//if not moving between rooms
|
//if not moving between rooms
|
||||||
else {
|
else {
|
||||||
@@ -228,16 +228,16 @@ void ServerApplication::hCharacterMovement(CharacterPacket* const argPacket) {
|
|||||||
|
|
||||||
//update the clients
|
//update the clients
|
||||||
CharacterPacket newPacket;
|
CharacterPacket newPacket;
|
||||||
CopyCharacterToPacket(&newPacket, argPacket->characterIndex);
|
copyCharacterToPacket(&newPacket, argPacket->characterIndex);
|
||||||
newPacket.type = SerialPacketType::CHARACTER_MOVEMENT;
|
newPacket.type = SerialPacketType::CHARACTER_MOVEMENT;
|
||||||
PumpPacketProximity(&newPacket, characterData->GetRoomIndex(), characterData->GetOrigin(), -1);
|
pumpPacketProximity(&newPacket, characterData->GetRoomIndex());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::hCharacterAttack(CharacterPacket* const argPacket) {
|
void ServerApplication::hCharacterAttack(CharacterPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) ServerApplication::hCharacterAttack()
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::hCharacterDamage(CharacterPacket* const argPacket) {
|
void ServerApplication::hCharacterDamage(CharacterPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) ServerApplication::hCharacterDamage()
|
||||||
}
|
}
|
||||||
@@ -22,13 +22,13 @@
|
|||||||
#include "server_application.hpp"
|
#include "server_application.hpp"
|
||||||
|
|
||||||
void ServerApplication::hTextBroadcast(TextPacket* const argPacket) {
|
void ServerApplication::hTextBroadcast(TextPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) ServerApplication::hTextBroadcast()
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::hTextSpeech(TextPacket* const argPacket) {
|
void ServerApplication::hTextSpeech(TextPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) ServerApplication::hTextSpeech()
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::hTextWhisper(TextPacket* const argPacket) {
|
void ServerApplication::hTextWhisper(TextPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) ServerApplication::hTextWhisper()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "server_application.hpp"
|
#include "server_application.hpp"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
@@ -138,7 +139,7 @@ void ServerApplication::hLogoutRequest(ClientPacket* const argPacket) {
|
|||||||
network.SendTo(clientData->GetAddress(), static_cast<SerialPacket*>(&newPacket));
|
network.SendTo(clientData->GetAddress(), static_cast<SerialPacket*>(&newPacket));
|
||||||
|
|
||||||
//save and unload this account and it's characters
|
//save and unload this account and it's characters
|
||||||
FullAccountUnload(argPacket->accountIndex);
|
fullAccountUnload(argPacket->accountIndex);
|
||||||
|
|
||||||
//finished this routine
|
//finished this routine
|
||||||
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;
|
||||||
@@ -165,7 +166,7 @@ void ServerApplication::hDisconnectRequest(ClientPacket* const argPacket) {
|
|||||||
network.SendTo(clientData->GetAddress(), static_cast<SerialPacket*>(&newPacket));
|
network.SendTo(clientData->GetAddress(), static_cast<SerialPacket*>(&newPacket));
|
||||||
|
|
||||||
//unload the client, it's accounts, and their characters
|
//unload the client, it's accounts, and their characters
|
||||||
FullClientUnload(argPacket->clientIndex);
|
fullClientUnload(argPacket->clientIndex);
|
||||||
|
|
||||||
//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;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "server_application.hpp"
|
#include "server_application.hpp"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
@@ -69,28 +70,28 @@ void ServerApplication::hQueryCharacterExists(CharacterPacket* const argPacket)
|
|||||||
if (argPacket->roomIndex != -1 && it.second.GetRoomIndex() != argPacket->roomIndex) {
|
if (argPacket->roomIndex != -1 && it.second.GetRoomIndex() != argPacket->roomIndex) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
CopyCharacterToPacket(&newPacket, it.first);
|
copyCharacterToPacket(&newPacket, it.first);
|
||||||
newPacket.type = SerialPacketType::QUERY_CHARACTER_EXISTS;
|
newPacket.type = SerialPacketType::QUERY_CHARACTER_EXISTS;
|
||||||
network.SendTo(argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket));
|
network.SendTo(argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::hQueryCharacterStats(CharacterPacket* const argPacket) {
|
void ServerApplication::hQueryCharacterStats(CharacterPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) ServerApplication::hQueryCharacterStats()
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::hQueryCharacterLocation(CharacterPacket* const argPacket) {
|
void ServerApplication::hQueryCharacterLocation(CharacterPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) ServerApplication::hQueryCharacterLocation()
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::hQueryMonsterExists(MonsterPacket* const argPacket) {
|
void ServerApplication::hQueryMonsterExists(MonsterPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) ServerApplication::hQueryMonsterExists()
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::hQueryMonsterStats(MonsterPacket* const argPacket) {
|
void ServerApplication::hQueryMonsterStats(MonsterPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) ServerApplication::hQueryMonsterStats()
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::hQueryMonsterLocation(MonsterPacket* const argPacket) {
|
void ServerApplication::hQueryMonsterLocation(MonsterPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) ServerApplication::hQueryMonsterLocation()
|
||||||
}
|
}
|
||||||
|
|||||||
+37
-18
@@ -27,7 +27,9 @@
|
|||||||
//std & STL
|
//std & STL
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <list>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -50,7 +52,9 @@ void ServerApplication::Init(int argc, char* argv[]) {
|
|||||||
|
|
||||||
//Init SDL
|
//Init SDL
|
||||||
if (SDL_Init(0)) {
|
if (SDL_Init(0)) {
|
||||||
throw(std::runtime_error("Failed to initialize SDL"));
|
std::ostringstream os;
|
||||||
|
os << "Failed to initialize SDL: " << SDL_GetError();
|
||||||
|
throw(std::runtime_error(os.str()));
|
||||||
}
|
}
|
||||||
std::cout << "Initialized SDL" << std::endl;
|
std::cout << "Initialized SDL" << std::endl;
|
||||||
|
|
||||||
@@ -161,9 +165,16 @@ void ServerApplication::Init(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::Proc() {
|
void ServerApplication::Proc() {
|
||||||
|
//network buffer
|
||||||
SerialPacket* packetBuffer = reinterpret_cast<SerialPacket*>(new char[MAX_PACKET_SIZE]);
|
SerialPacket* packetBuffer = reinterpret_cast<SerialPacket*>(new char[MAX_PACKET_SIZE]);
|
||||||
memset(packetBuffer, 0, MAX_PACKET_SIZE); //zero the buffer
|
memset(packetBuffer, 0, MAX_PACKET_SIZE); //zero the buffer
|
||||||
|
|
||||||
|
//time system
|
||||||
|
typedef std::chrono::steady_clock Clock;
|
||||||
|
|
||||||
|
Clock::time_point simTime = Clock::now();
|
||||||
|
Clock::time_point realTime;
|
||||||
|
|
||||||
while(running) {
|
while(running) {
|
||||||
//suck in the waiting packets & process them
|
//suck in the waiting packets & process them
|
||||||
while(network.Receive(packetBuffer)) {
|
while(network.Receive(packetBuffer)) {
|
||||||
@@ -173,20 +184,33 @@ void ServerApplication::Proc() {
|
|||||||
catch(std::exception& e) {
|
catch(std::exception& e) {
|
||||||
std::cerr << "HandlePacket Error: " << e.what() << std::endl;
|
std::cerr << "HandlePacket Error: " << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
memset(packetBuffer, 0, MAX_PACKET_SIZE); //reset the buffer
|
//reset the buffer
|
||||||
}
|
memset(packetBuffer, 0, MAX_PACKET_SIZE);
|
||||||
//update the internals
|
|
||||||
//...
|
|
||||||
|
|
||||||
//Check connections
|
|
||||||
int disconnected = clientMgr.CheckConnections();
|
|
||||||
if (disconnected != -1) {
|
|
||||||
FullClientUnload(disconnected);
|
|
||||||
std::cerr << "Client dropped: " << disconnected << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//give the machine a break
|
//Check client connections
|
||||||
SDL_Delay(10);
|
std::list<int> disconnections = clientMgr.CheckConnections();
|
||||||
|
for(auto const& it : disconnections) {
|
||||||
|
fullClientUnload(it);
|
||||||
|
std::cerr << "Client dropped: " << it << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//"tick" the internals
|
||||||
|
realTime = Clock::now();
|
||||||
|
|
||||||
|
if (simTime < realTime) {
|
||||||
|
while(simTime < realTime) {
|
||||||
|
for (auto& it : *roomMgr.GetContainer()) {
|
||||||
|
it.second.RunFrame();
|
||||||
|
}
|
||||||
|
//~60 FPS
|
||||||
|
simTime += std::chrono::duration<int, std::milli>(16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//give the machine a break
|
||||||
|
SDL_Delay(10);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
delete reinterpret_cast<char*>(packetBuffer);
|
delete reinterpret_cast<char*>(packetBuffer);
|
||||||
}
|
}
|
||||||
@@ -303,11 +327,6 @@ void ServerApplication::HandlePacket(SerialPacket* const argPacket) {
|
|||||||
hCharacterDamage(static_cast<CharacterPacket*>(argPacket));
|
hCharacterDamage(static_cast<CharacterPacket*>(argPacket));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//monster management
|
|
||||||
case SerialPacketType::MONSTER_DAMAGE:
|
|
||||||
hMonsterDamage(static_cast<MonsterPacket*>(argPacket));
|
|
||||||
break;
|
|
||||||
|
|
||||||
//chat
|
//chat
|
||||||
case SerialPacketType::TEXT_BROADCAST:
|
case SerialPacketType::TEXT_BROADCAST:
|
||||||
hTextBroadcast(static_cast<TextPacket*>(argPacket));
|
hTextBroadcast(static_cast<TextPacket*>(argPacket));
|
||||||
|
|||||||
+4
-118
@@ -22,6 +22,7 @@
|
|||||||
#include "server_application.hpp"
|
#include "server_application.hpp"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@
|
|||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
void ServerApplication::hAdminDisconnectForced(ClientPacket* const argPacket) {
|
void ServerApplication::hAdminDisconnectForced(ClientPacket* const argPacket) {
|
||||||
//TODO: (9) empty
|
//TODO: (9) ServerApplication::hAdminDisconnectForced()
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::hAdminShutdownRequest(ClientPacket* const argPacket) {
|
void ServerApplication::hAdminShutdownRequest(ClientPacket* const argPacket) {
|
||||||
@@ -78,127 +79,12 @@ void ServerApplication::hAdminShutdownRequest(ClientPacket* const argPacket) {
|
|||||||
TextPacket newPacket;
|
TextPacket newPacket;
|
||||||
newPacket.type = SerialPacketType::ADMIN_DISCONNECT_FORCED;
|
newPacket.type = SerialPacketType::ADMIN_DISCONNECT_FORCED;
|
||||||
strncpy(newPacket.text, "Server shutdown", PACKET_STRING_SIZE);
|
strncpy(newPacket.text, "Server shutdown", PACKET_STRING_SIZE);
|
||||||
PumpPacket(&newPacket);
|
pumpPacket(&newPacket);
|
||||||
|
|
||||||
//finished this routine
|
//finished this routine
|
||||||
std::cout << "Shutdown signal accepted" << std::endl;
|
std::cout << "Shutdown signal accepted" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::SaveServerState() {
|
void ServerApplication::SaveServerState() {
|
||||||
//TODO: (9) empty
|
//TODO: (3) Periodic mass server saves
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------
|
|
||||||
//full unload methods
|
|
||||||
//-------------------------
|
|
||||||
|
|
||||||
void ServerApplication::FullClientUnload(int index) {
|
|
||||||
clientMgr.UnloadIf([&](std::pair<const int, ClientData const&> client) -> bool {
|
|
||||||
//skip the wrong clients
|
|
||||||
if (client.first != index) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//unload associated accounts
|
|
||||||
for (std::map<int, AccountData>::iterator it = accountMgr.GetContainer()->begin(); it != accountMgr.GetContainer()->end(); /* EMPTY */) {
|
|
||||||
if (it->second.GetClientIndex() == index) {
|
|
||||||
FullAccountUnload(it->first);
|
|
||||||
it = accountMgr.GetContainer()->begin();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//unload this client
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void ServerApplication::FullAccountUnload(int index) {
|
|
||||||
accountMgr.UnloadIf([&](std::pair<const int, AccountData const&> account) -> bool {
|
|
||||||
//skip the wrong accounts
|
|
||||||
if (account.first != index) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//unload associated characters
|
|
||||||
for (std::map<int, CharacterData>::iterator it = characterMgr.GetContainer()->begin(); it != characterMgr.GetContainer()->end(); /* EMPTY */) {
|
|
||||||
if (it->second.GetOwner() == index) {
|
|
||||||
FullCharacterUnload(it->first);
|
|
||||||
it = characterMgr.GetContainer()->begin();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//unload this account
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void ServerApplication::FullCharacterUnload(int index) {
|
|
||||||
characterMgr.UnloadIf([&](std::pair<const int, CharacterData const&> character) -> bool {
|
|
||||||
//skip the wrong characters
|
|
||||||
if (character.first != index) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//pop from the rooms
|
|
||||||
roomMgr.PopCharacter(&character.second);
|
|
||||||
|
|
||||||
//pump character unload
|
|
||||||
CharacterPacket newPacket;
|
|
||||||
newPacket.type = SerialPacketType::CHARACTER_DELETE;
|
|
||||||
newPacket.characterIndex = character.first;
|
|
||||||
//NOTE: more character info as needed
|
|
||||||
|
|
||||||
PumpPacket(&newPacket);
|
|
||||||
|
|
||||||
//unload this character
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------
|
|
||||||
//utility methods
|
|
||||||
//-------------------------
|
|
||||||
|
|
||||||
void ServerApplication::PumpPacket(SerialPacket* const argPacket) {
|
|
||||||
for (auto& it : *clientMgr.GetContainer()) {
|
|
||||||
network.SendTo(it.second.GetAddress(), argPacket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ServerApplication::PumpPacketProximity(SerialPacket* const argPacket, int roomIndex, Vector2 position, int distance) {
|
|
||||||
RoomData* room = roomMgr.Get(roomIndex);
|
|
||||||
|
|
||||||
if (!room) {
|
|
||||||
throw(std::runtime_error("Failed to pump to a non-existant room"));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& character : *room->GetCharacterList()) {
|
|
||||||
if (distance == -1 || (character->GetOrigin() - position).Length() <= distance) {
|
|
||||||
AccountData* account = accountMgr.Get(character->GetOwner());
|
|
||||||
ClientData* client = clientMgr.Get(account->GetClientIndex());
|
|
||||||
network.SendTo(client->GetAddress(), argPacket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ServerApplication::CopyCharacterToPacket(CharacterPacket* const packet, int characterIndex) {
|
|
||||||
CharacterData* character = characterMgr.Get(characterIndex);
|
|
||||||
if (!character) {
|
|
||||||
throw(std::runtime_error("Failed to copy a character to a packet"));
|
|
||||||
}
|
|
||||||
|
|
||||||
//NOTE: keep this up to date when the character changes
|
|
||||||
packet->characterIndex = characterIndex;
|
|
||||||
strncpy(packet->handle, character->GetHandle().c_str(), PACKET_STRING_SIZE);
|
|
||||||
strncpy(packet->avatar, character->GetAvatar().c_str(), PACKET_STRING_SIZE);
|
|
||||||
packet->accountIndex = character->GetOwner();
|
|
||||||
packet->roomIndex = character->GetRoomIndex();
|
|
||||||
packet->origin = character->GetOrigin();
|
|
||||||
packet->motion = character->GetMotion();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#config
|
#config
|
||||||
INCLUDES+=.
|
INCLUDES+=. ../accounts ../characters ../clients ../entities ../monsters ../rooms ../triggers ../../common/gameplay ../../common/map ../../common/network ../../common/network/packet_types ../../common/utilities
|
||||||
LIBS+=
|
LIBS+=
|
||||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||||
|
|
||||||
@@ -30,8 +30,3 @@ $(OUTDIR):
|
|||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o *.a *.exe
|
|
||||||
|
|
||||||
rebuild: clean all
|
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/* 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 "network_api.hpp"
|
||||||
|
|
||||||
|
#include "character_data.hpp"
|
||||||
|
#include "character_manager.hpp"
|
||||||
|
#include "server_utilities.hpp"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
static int pumpCharacterUpdate(lua_State* L) {
|
||||||
|
CharacterData* characterData = static_cast<CharacterData*>(lua_touserdata(L, 1));
|
||||||
|
|
||||||
|
//determine the character's index
|
||||||
|
int index = -1;
|
||||||
|
for (auto const& it : *CharacterManager::GetSingleton().GetContainer()) {
|
||||||
|
if(characterData == &it.second) {
|
||||||
|
index = it.first;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//signal an error
|
||||||
|
if (index == -1) {
|
||||||
|
lua_pushboolean(L, false);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//fill the packet with all of this character's data
|
||||||
|
CharacterPacket newPacket;
|
||||||
|
newPacket.type = SerialPacketType::CHARACTER_UPDATE;
|
||||||
|
newPacket.characterIndex = index;
|
||||||
|
strncpy(newPacket.handle, characterData->GetHandle().c_str(), PACKET_STRING_SIZE);
|
||||||
|
strncpy(newPacket.avatar, characterData->GetAvatar().c_str(), PACKET_STRING_SIZE);
|
||||||
|
newPacket.accountIndex = characterData->GetOwner();
|
||||||
|
newPacket.roomIndex = characterData->GetRoomIndex();
|
||||||
|
newPacket.origin = characterData->GetOrigin();
|
||||||
|
newPacket.motion = characterData->GetMotion();
|
||||||
|
|
||||||
|
//pump to the room
|
||||||
|
pumpPacketProximity(&newPacket, characterData->GetRoomIndex());
|
||||||
|
|
||||||
|
//signal success
|
||||||
|
lua_pushboolean(L, true);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pumpMonsterUpdate(lua_State* L) {
|
||||||
|
//TODO: (0) send the info about a specific monster instance
|
||||||
|
}
|
||||||
|
|
||||||
|
static const luaL_Reg networkLib[] = {
|
||||||
|
{"PumpCharacterUpdate", pumpCharacterUpdate},
|
||||||
|
{"PumpMonsterUpdate", pumpMonsterUpdate},
|
||||||
|
{nullptr, nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
LUAMOD_API int openNetworkAPI(lua_State* L) {
|
||||||
|
luaL_newlib(L, networkLib);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
@@ -19,12 +19,12 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
#ifndef WAYPOINTAPI_HPP_
|
#ifndef NETWORKAPI_HPP_
|
||||||
#define WAYPOINTAPI_HPP_
|
#define NETWORKAPI_HPP_
|
||||||
|
|
||||||
#include "lua.hpp"
|
#include "lua.hpp"
|
||||||
|
|
||||||
#define TORTUGA_WAYPOINT_API "waypoint"
|
#define TORTUGA_NETWORK_API "network"
|
||||||
LUAMOD_API int openWaypointAPI(lua_State* L);
|
LUAMOD_API int openNetworkAPI(lua_State* L);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -0,0 +1,184 @@
|
|||||||
|
/* 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_utilities.hpp"
|
||||||
|
|
||||||
|
#include "account_manager.hpp"
|
||||||
|
#include "character_manager.hpp"
|
||||||
|
#include "client_manager.hpp"
|
||||||
|
#include "room_manager.hpp"
|
||||||
|
#include "udp_network_utility.hpp"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//manager unload functions
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void fullClientUnload(int index) {
|
||||||
|
ClientManager::GetSingleton().UnloadIf([index](std::pair<const int, ClientData const&> clientPair) -> bool {
|
||||||
|
//skip the wrong clients
|
||||||
|
if (clientPair.first != index) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountManager& accountMgr = AccountManager::GetSingleton();
|
||||||
|
|
||||||
|
//unload associated accounts
|
||||||
|
for (std::map<int, AccountData>::iterator it = accountMgr.GetContainer()->begin(); it != accountMgr.GetContainer()->end(); /* EMPTY */) {
|
||||||
|
if (it->second.GetClientIndex() == index) {
|
||||||
|
fullAccountUnload(it->first);
|
||||||
|
it = accountMgr.GetContainer()->begin();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//unload this client
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void fullAccountUnload(int index) {
|
||||||
|
AccountManager::GetSingleton().UnloadIf([index](std::pair<const int, AccountData const&> accountPair) -> bool {
|
||||||
|
//skip the wrong accounts
|
||||||
|
if (accountPair.first != index) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CharacterManager& characterMgr = CharacterManager::GetSingleton();
|
||||||
|
|
||||||
|
//unload associated characters
|
||||||
|
for (std::map<int, CharacterData>::iterator it = characterMgr.GetContainer()->begin(); it != characterMgr.GetContainer()->end(); /* EMPTY */) {
|
||||||
|
if (it->second.GetOwner() == index) {
|
||||||
|
fullCharacterUnload(it->first);
|
||||||
|
it = characterMgr.GetContainer()->begin();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//unload this account
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void fullCharacterUnload(int index) {
|
||||||
|
CharacterManager::GetSingleton().UnloadIf([index](std::pair<const int, CharacterData const&> characterPair) -> bool {
|
||||||
|
//skip the wrong characters
|
||||||
|
if (characterPair.first != index) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//pop from the rooms
|
||||||
|
RoomManager::GetSingleton().PopCharacter(&characterPair.second);
|
||||||
|
|
||||||
|
//pump character unload
|
||||||
|
CharacterPacket newPacket;
|
||||||
|
newPacket.type = SerialPacketType::CHARACTER_DELETE;
|
||||||
|
newPacket.characterIndex = characterPair.first;
|
||||||
|
//NOTE: more character info as needed
|
||||||
|
|
||||||
|
//TODO: proximity?
|
||||||
|
pumpPacketProximity(&newPacket, characterPair.second.GetRoomIndex());
|
||||||
|
|
||||||
|
//unload this character
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//utility functions
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void pumpPacket(SerialPacket* const argPacket) {
|
||||||
|
for (auto& it : *ClientManager::GetSingleton().GetContainer()) {
|
||||||
|
UDPNetworkUtility::GetSingleton().SendTo(it.second.GetAddress(), argPacket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pumpPacketProximity(SerialPacket* const argPacket, int roomIndex, Vector2 position, int distance) {
|
||||||
|
RoomData* roomData = RoomManager::GetSingleton().Get(roomIndex);
|
||||||
|
|
||||||
|
if (!roomData) {
|
||||||
|
throw(std::runtime_error("Failed to pump to a non-existant room"));
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountData* accountData = nullptr;
|
||||||
|
ClientData* clientData = nullptr;
|
||||||
|
|
||||||
|
for (auto& characterIt : *roomData->GetCharacterList()) {
|
||||||
|
if (distance == -1 || (characterIt->GetOrigin() - position).Length() <= distance) {
|
||||||
|
accountData = AccountManager::GetSingleton().Get(characterIt->GetOwner());
|
||||||
|
clientData = ClientManager::GetSingleton().Get(accountData->GetClientIndex());
|
||||||
|
UDPNetworkUtility::GetSingleton().SendTo(clientData->GetAddress(), argPacket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyCharacterToPacket(CharacterPacket* const packet, int characterIndex) {
|
||||||
|
CharacterData* characterData = CharacterManager::GetSingleton().Get(characterIndex);
|
||||||
|
if (!characterData) {
|
||||||
|
throw(std::runtime_error("Failed to copy a character to a packet"));
|
||||||
|
}
|
||||||
|
|
||||||
|
copyCharacterToPacket(packet, characterData, characterIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyCharacterToPacket(CharacterPacket* const packet, CharacterData* const characterData, int characterIndex) {
|
||||||
|
//NOTE: keep this up to date when the character changes
|
||||||
|
packet->characterIndex = characterIndex;
|
||||||
|
strncpy(packet->handle, characterData->GetHandle().c_str(), PACKET_STRING_SIZE);
|
||||||
|
strncpy(packet->avatar, characterData->GetAvatar().c_str(), PACKET_STRING_SIZE);
|
||||||
|
packet->accountIndex = characterData->GetOwner();
|
||||||
|
packet->roomIndex = characterData->GetRoomIndex();
|
||||||
|
packet->origin = characterData->GetOrigin();
|
||||||
|
packet->motion = characterData->GetMotion();
|
||||||
|
packet->bounds = characterData->GetBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
void pumpAndChangeRooms(int characterIndex, int newRoomIndex) {
|
||||||
|
//get the character object
|
||||||
|
CharacterData* character = CharacterManager::GetSingleton().Get(characterIndex);
|
||||||
|
|
||||||
|
//pass ownwards
|
||||||
|
pumpAndChangeRooms(character, newRoomIndex, characterIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pumpAndChangeRooms(CharacterData* const characterData, int newRoomIndex, int characterIndex) {
|
||||||
|
//delete from the old room
|
||||||
|
CharacterPacket newPacket;
|
||||||
|
copyCharacterToPacket(&newPacket, characterData, characterIndex);
|
||||||
|
newPacket.type = SerialPacketType::CHARACTER_DELETE;
|
||||||
|
pumpPacketProximity(&newPacket, characterData->GetRoomIndex());
|
||||||
|
|
||||||
|
//move the character between rooms
|
||||||
|
RoomManager::GetSingleton().PopCharacter(characterData);
|
||||||
|
characterData->SetRoomIndex(newRoomIndex);
|
||||||
|
RoomManager::GetSingleton().PushCharacter(characterData);
|
||||||
|
|
||||||
|
//create in the new room
|
||||||
|
copyCharacterToPacket(&newPacket, characterData, characterIndex);
|
||||||
|
newPacket.type = SerialPacketType::CHARACTER_CREATE;
|
||||||
|
pumpPacketProximity(&newPacket, characterData->GetRoomIndex());
|
||||||
|
}
|
||||||
+16
-5
@@ -19,12 +19,23 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
#ifndef MONSTERSYSTEMAPI_HPP_
|
#ifndef SERVERUTILITIES_HPP_
|
||||||
#define MONSTERSYSTEMAPI_HPP_
|
#define SERVERUTILITIES_HPP_
|
||||||
|
|
||||||
#include "lua.hpp"
|
#include "character_data.hpp"
|
||||||
|
#include "serial_packet.hpp"
|
||||||
|
#include "vector2.hpp"
|
||||||
|
|
||||||
#define TORTUGA_MONSTER_SYSTEM_API "monster_system"
|
void fullClientUnload(int index);
|
||||||
LUAMOD_API int openMonsterSystemAPI(lua_State* L);
|
void fullAccountUnload(int index);
|
||||||
|
void fullCharacterUnload(int index);
|
||||||
|
|
||||||
|
void pumpPacket(SerialPacket* const argPacket);
|
||||||
|
void pumpPacketProximity(SerialPacket* const argPacket, int roomIndex, Vector2 position = {0, 0}, int distance = -1);
|
||||||
|
|
||||||
|
void copyCharacterToPacket(CharacterPacket* const packet, int characterIndex);
|
||||||
|
void copyCharacterToPacket(CharacterPacket* const packet, CharacterData* const characterData, int characterIndex);
|
||||||
|
void pumpAndChangeRooms(int characterIndex, int newRoomIndex);
|
||||||
|
void pumpAndChangeRooms(CharacterData* const characterData, int newRoomIndex, int characterIndex);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -30,8 +30,3 @@ $(OUTDIR):
|
|||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) *.o *.a *.exe
|
|
||||||
|
|
||||||
rebuild: clean all
|
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
/* 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 "trigger_api.hpp"
|
||||||
|
|
||||||
|
#include "trigger_data.hpp"
|
||||||
|
|
||||||
|
//hamdle
|
||||||
|
static int setHandle(lua_State* L) {
|
||||||
|
TriggerData* trigger = static_cast<TriggerData*>(lua_touserdata(L, 1));
|
||||||
|
trigger->SetHandle(lua_tostring(L, 2));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getHandle(lua_State* L) {
|
||||||
|
TriggerData* trigger = static_cast<TriggerData*>(lua_touserdata(L, 1));
|
||||||
|
lua_pushstring(L, trigger->GetHandle().c_str());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//origin
|
||||||
|
static int setOrigin(lua_State* L) {
|
||||||
|
TriggerData* trigger = static_cast<TriggerData*>(lua_touserdata(L, 1));
|
||||||
|
trigger->SetOrigin(Vector2(lua_tonumber(L, 2), lua_tonumber(L, 3)));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getOrigin(lua_State* L) {
|
||||||
|
TriggerData* trigger = static_cast<TriggerData*>(lua_touserdata(L, 1));
|
||||||
|
lua_pushnumber(L, trigger->GetOrigin().x);
|
||||||
|
lua_pushnumber(L, trigger->GetOrigin().y);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
//bounds
|
||||||
|
static int setBoundingBox(lua_State* L) {
|
||||||
|
TriggerData* trigger = static_cast<TriggerData*>(lua_touserdata(L, 1));
|
||||||
|
trigger->SetBoundingBox(BoundingBox(
|
||||||
|
lua_tonumber(L, 2),
|
||||||
|
lua_tonumber(L, 3),
|
||||||
|
lua_tonumber(L, 4),
|
||||||
|
lua_tonumber(L, 5)
|
||||||
|
));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getBoundingBox(lua_State* L) {
|
||||||
|
TriggerData* trigger = static_cast<TriggerData*>(lua_touserdata(L, 1));
|
||||||
|
lua_pushinteger(L, trigger->GetBoundingBox().x);
|
||||||
|
lua_pushinteger(L, trigger->GetBoundingBox().y);
|
||||||
|
lua_pushinteger(L, trigger->GetBoundingBox().w);
|
||||||
|
lua_pushinteger(L, trigger->GetBoundingBox().h);
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
//triggers
|
||||||
|
static int setReference(lua_State* L) {
|
||||||
|
TriggerData* trigger = static_cast<TriggerData*>(lua_touserdata(L, 1));
|
||||||
|
luaL_unref(L, LUA_REGISTRYINDEX, trigger->GetScriptReference());
|
||||||
|
trigger->SetScriptReference(luaL_ref(L, LUA_REGISTRYINDEX));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getReference(lua_State* L) {
|
||||||
|
TriggerData* trigger = static_cast<TriggerData*>(lua_touserdata(L, 1));
|
||||||
|
lua_pushinteger(L, trigger->GetScriptReference());
|
||||||
|
lua_gettable(L, LUA_REGISTRYINDEX);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pushExclusionEntity(lua_State* L) {
|
||||||
|
TriggerData* trigger = static_cast<TriggerData*>(lua_touserdata(L, 1));
|
||||||
|
trigger->GetExclusionList()->push_back(static_cast<Entity*>(lua_touserdata(L, 2)));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int removeExclusionEntity(lua_State* L) {
|
||||||
|
TriggerData* trigger = static_cast<TriggerData*>(lua_touserdata(L, 1));
|
||||||
|
Entity* entity = static_cast<Entity*>(lua_touserdata(L, 2));
|
||||||
|
trigger->GetExclusionList()->remove_if([entity](Entity* ptr){
|
||||||
|
return entity == ptr;
|
||||||
|
});
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const luaL_Reg triggerLib[] = {
|
||||||
|
{"SetHandle", setHandle},
|
||||||
|
{"GetHandle", getHandle},
|
||||||
|
|
||||||
|
{"SetOrigin",setOrigin},
|
||||||
|
{"GetOrigin",getOrigin},
|
||||||
|
|
||||||
|
{"SetBounds",setBoundingBox},
|
||||||
|
{"GetBounds",getBoundingBox},
|
||||||
|
|
||||||
|
{"SetScript",setReference},
|
||||||
|
{"GetScript",getReference},
|
||||||
|
|
||||||
|
{"PushExclusionEntity", pushExclusionEntity},
|
||||||
|
{"RemoveExclusionEntity", removeExclusionEntity},
|
||||||
|
|
||||||
|
{nullptr, nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
LUAMOD_API int openTriggerAPI(lua_State* L) {
|
||||||
|
luaL_newlib(L, triggerLib);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
@@ -19,12 +19,12 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
#ifndef MAPSYSTEMAPI_HPP_
|
#ifndef TRIGGERAPI_HPP_
|
||||||
#define MAPSYSTEMAPI_APP_
|
#define TRIGGERAPI_HPP_
|
||||||
|
|
||||||
#include "lua.hpp"
|
#include "lua.hpp"
|
||||||
|
|
||||||
#define TORTUGA_MAP_SYSTEM_API "map_system"
|
#define TORTUGA_TRIGGER_API "trigger"
|
||||||
LUAMOD_API int openMapSystemAPI(lua_State* L);
|
LUAMOD_API int openTriggerAPI(lua_State* L);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -19,28 +19,40 @@
|
|||||||
* 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 "waypoint_data.hpp"
|
#include "trigger_data.hpp"
|
||||||
|
|
||||||
int WaypointData::SetTriggerReference(int i) {
|
std::string TriggerData::SetHandle(std::string s) {
|
||||||
return triggerRef = i;
|
return handle = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WaypointData::GetTriggerReference() {
|
std::string TriggerData::GetHandle() const {
|
||||||
return triggerRef;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundingBox WaypointData::SetBoundingBox(BoundingBox b) {
|
Vector2 TriggerData::SetOrigin(Vector2 v) {
|
||||||
return bounds = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
BoundingBox WaypointData::GetBoundingBox() {
|
|
||||||
return bounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 WaypointData::SetOrigin(Vector2 v) {
|
|
||||||
return origin = v;
|
return origin = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2 WaypointData::GetOrigin() {
|
Vector2 TriggerData::GetOrigin() {
|
||||||
return origin;
|
return origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BoundingBox TriggerData::SetBoundingBox(BoundingBox b) {
|
||||||
|
return bounds = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
BoundingBox TriggerData::GetBoundingBox() {
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TriggerData::SetScriptReference(int i) {
|
||||||
|
return scriptRef = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TriggerData::GetScriptReference() {
|
||||||
|
return scriptRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<Entity*>* TriggerData::GetExclusionList() {
|
||||||
|
return &exclusionList;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user