Compare commits
53 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 854dc0eb45 | |||
| e90afb7e4a | |||
| 0453f6becf | |||
| c8a58ab515 | |||
| 553f8dbfa5 | |||
| 2bacdcdab7 | |||
| 99aecbfdbb | |||
| 27bda5dc28 | |||
| 962f3f5dd0 | |||
| 41077b43b3 | |||
| 4410ab892f | |||
| 60000cb0cf | |||
| 66b00255d5 | |||
| a5b68cf1fd | |||
| 4cff57fe71 | |||
| 38b603fc8f | |||
| 47684380a9 | |||
| e4bfbfb906 | |||
| 9db86c19f6 | |||
| d5b551cec3 | |||
| 7e500027e3 | |||
| dd786ba579 | |||
| 5a57888305 | |||
| 706aa5e1d7 | |||
| 19c1b1197d | |||
| 5cf62f5517 | |||
| 56d02ad8d4 | |||
| 006a72174f | |||
| 0cbc9dd9db | |||
| 60c31ff56d | |||
| 6a204643f6 | |||
| 59285d1630 | |||
| a850d6b1af | |||
| f17fa0f345 | |||
| 756d4e770d | |||
| 7bb5e8ce0d | |||
| 975533afba | |||
| 19749f7c87 | |||
| 7703c4b0ad | |||
| dc8f594eec | |||
| 4629b7302b | |||
| 02d83d1f16 | |||
| 91c9cef56d | |||
| f7d4912942 | |||
| eb8674b84f | |||
| ff44e4d916 | |||
| e66540f114 | |||
| 639c0c70e3 | |||
| 37b02352e2 | |||
| 31c8bd7fd2 | |||
| 808fe570a3 | |||
| e706cc9d13 | |||
| eb02cc4b6a |
@@ -1,6 +1,6 @@
|
|||||||
You can find the [latest nightly build here](https://dl.dropboxusercontent.com/u/46669050/Tortuga.rar).
|
The most recent stable windows build can be found [here](https://dl.dropboxusercontent.com/u/46669050/Tortuga.rar).
|
||||||
|
|
||||||
Tortuga is an open source 2D multiplayer role playing game featuring permadeath (deletion of a character upon death). The emphasis of this game is on multiplayer cooperation, competition, and customization. The game runs on customizable server software that can support up to 150 simultaneous players or more.
|
Tortuga is an open source 2D multiplayer role playing game featuring permadeath (deletion of a character upon death). The emphasis of this game is on multiplayer cooperation, competition, exploration and customization. The game runs on customizable server software that can support up to 150 simultaneous players or more.
|
||||||
|
|
||||||
This game is inspired by classic 2D RPGs, as well as more modern sandbox MMOs. This project is currently independently created and funded, with the goal of creating a game that will engage user's imagination and inspire a large modding community.
|
This game is inspired by classic 2D RPGs, as well as more modern sandbox MMOs. This project is currently independently created and funded, with the goal of creating a game that will engage user's imagination and inspire a large modding community.
|
||||||
|
|
||||||
@@ -13,14 +13,14 @@ This game is inspired by classic 2D RPGs, as well as more modern sandbox MMOs. T
|
|||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
[Tortuga Game Design Document](https://docs.google.com/document/d/17SjOTdacKKWX0Z-UkaiFnVnjfEeMsc5LRmARtnjh5UI/edit?usp=sharing)
|
[Tortuga Game Design Document](https://github.com/Ratstail91/Tortuga/blob/docs/design%20doc.docx?raw=true)
|
||||||
[Tortuga Technical Document](https://docs.google.com/document/d/1ASTfM_1e0yE1cFP-IZey_rHEC6k2kmVY56X4K407sw0/edit?usp=sharing)
|
[Tortuga Technical Document](https://github.com/Ratstail91/Tortuga/blob/docs/technical%20doc.docx?raw=true)
|
||||||
|
|
||||||
## Copyright
|
## Copyright
|
||||||
|
|
||||||
The current version of Tortuga is released under the [zlib license](http://en.wikipedia.org/wiki/Zlib_License).
|
The current version of Tortuga is released under the [zlib license](http://en.wikipedia.org/wiki/Zlib_License).
|
||||||
|
|
||||||
Copyright (c) 2013 Kayne Ruse
|
Copyright (c) 2013, 2014 Kayne Ruse
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
|||||||
@@ -62,13 +62,13 @@ void ClientApplication::Init() {
|
|||||||
if (SDL_Init(SDL_INIT_VIDEO)) {
|
if (SDL_Init(SDL_INIT_VIDEO)) {
|
||||||
throw(std::runtime_error("Failed to initialize SDL"));
|
throw(std::runtime_error("Failed to initialize SDL"));
|
||||||
}
|
}
|
||||||
BaseScene::SetScreen(config.Int("screen.w"), config.Int("screen.h"), 0, (config.Bool("screen.f")) ? SDL_HWSURFACE|SDL_DOUBLEBUF : SDL_HWSURFACE);
|
BaseScene::SetScreen(config.Int("screen.w"), config.Int("screen.h"), 0, (config.Bool("screen.f")) ? SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_FULLSCREEN : SDL_HWSURFACE|SDL_DOUBLEBUF);
|
||||||
|
|
||||||
//initialize SDL_net
|
//initialize SDL_net
|
||||||
if (SDLNet_Init()) {
|
if (SDLNet_Init()) {
|
||||||
throw(std::runtime_error("Failed to initialize SDL_net"));
|
throw(std::runtime_error("Failed to initialize SDL_net"));
|
||||||
}
|
}
|
||||||
network.Open(0, sizeof(NetworkPacket));
|
network.Open(0, PACKET_BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientApplication::Proc() {
|
void ClientApplication::Proc() {
|
||||||
@@ -77,7 +77,7 @@ void ClientApplication::Proc() {
|
|||||||
//prepare the time system
|
//prepare the time system
|
||||||
typedef std::chrono::steady_clock Clock;
|
typedef std::chrono::steady_clock Clock;
|
||||||
|
|
||||||
Clock::duration delta(16 * Clock::duration::period::den / std::milli::den);
|
std::chrono::duration<int, std::milli> delta(16);
|
||||||
Clock::time_point simTime = Clock::now();
|
Clock::time_point simTime = Clock::now();
|
||||||
Clock::time_point realTime;
|
Clock::time_point realTime;
|
||||||
|
|
||||||
@@ -95,15 +95,12 @@ void ClientApplication::Proc() {
|
|||||||
//simulate game time
|
//simulate game time
|
||||||
while (simTime < realTime) {
|
while (simTime < realTime) {
|
||||||
//call each user defined function
|
//call each user defined function
|
||||||
activeScene->RunFrame(double(delta.count()) / Clock::duration::period::den);
|
activeScene->RunFrame(double(delta.count()) / std::chrono::duration<int, std::milli>::period::den);
|
||||||
simTime += delta;
|
simTime += delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
//draw the game to the screen
|
//draw the game to the screen
|
||||||
activeScene->RenderFrame();
|
activeScene->RenderFrame();
|
||||||
|
|
||||||
//give the computer a break
|
|
||||||
SDL_Delay(10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UnloadScene();
|
UnloadScene();
|
||||||
@@ -121,7 +118,6 @@ void ClientApplication::Quit() {
|
|||||||
|
|
||||||
void ClientApplication::LoadScene(SceneList sceneIndex) {
|
void ClientApplication::LoadScene(SceneList sceneIndex) {
|
||||||
UnloadScene();
|
UnloadScene();
|
||||||
|
|
||||||
switch(sceneIndex) {
|
switch(sceneIndex) {
|
||||||
//add scene creation calls here
|
//add scene creation calls here
|
||||||
case SceneList::FIRST:
|
case SceneList::FIRST:
|
||||||
@@ -143,7 +139,6 @@ void ClientApplication::LoadScene(SceneList sceneIndex) {
|
|||||||
case SceneList::INCOMBAT:
|
case SceneList::INCOMBAT:
|
||||||
activeScene = new InCombat();
|
activeScene = new InCombat();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw(std::logic_error("Failed to recognize the scene index"));
|
throw(std::logic_error("Failed to recognize the scene index"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public:
|
|||||||
|
|
||||||
void Update(double delta);
|
void Update(double delta);
|
||||||
|
|
||||||
void DrawTo(SDL_Surface* const dest) { sprite.DrawTo(dest, position.x, position.y); }
|
void DrawTo(SDL_Surface* const dest, int camX, int camY) { sprite.DrawTo(dest, position.x - camX, position.y - camY); }
|
||||||
|
|
||||||
//clunky code results in smooth movement and controls
|
//clunky code results in smooth movement and controls
|
||||||
void AdjustDirection(Direction);
|
void AdjustDirection(Direction);
|
||||||
|
|||||||
+207
-23
@@ -23,8 +23,15 @@
|
|||||||
|
|
||||||
#include "channels.hpp"
|
#include "channels.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
//debugging
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout;
|
||||||
|
using std::endl;
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//Public access members
|
//Public access members
|
||||||
//-------------------------
|
//-------------------------
|
||||||
@@ -35,26 +42,34 @@ InWorld::InWorld(ConfigUtility* const argConfig, UDPNetworkUtility* const argNet
|
|||||||
clientIndex(*argClientIndex)
|
clientIndex(*argClientIndex)
|
||||||
{
|
{
|
||||||
//setup the utility objects
|
//setup the utility objects
|
||||||
image.LoadSurface(config["dir.interface"] + "button_menu.bmp");
|
buttonImage.LoadSurface(config["dir.interface"] + "button_menu.bmp");
|
||||||
image.SetClipH(image.GetClipH()/3);
|
buttonImage.SetClipH(buttonImage.GetClipH()/3);
|
||||||
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
|
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
|
||||||
|
|
||||||
//pass the utility objects
|
//pass the utility objects
|
||||||
disconnectButton.SetImage(&image);
|
disconnectButton.SetImage(&buttonImage);
|
||||||
disconnectButton.SetFont(&font);
|
disconnectButton.SetFont(&font);
|
||||||
shutDownButton.SetImage(&image);
|
shutDownButton.SetImage(&buttonImage);
|
||||||
shutDownButton.SetFont(&font);
|
shutDownButton.SetFont(&font);
|
||||||
|
|
||||||
//set the button positions
|
//set the button positions
|
||||||
disconnectButton.SetX(50);
|
disconnectButton.SetX(50);
|
||||||
disconnectButton.SetY(50 + image.GetClipH() * 0);
|
disconnectButton.SetY(50 + buttonImage.GetClipH() * 0);
|
||||||
shutDownButton.SetX(50);
|
shutDownButton.SetX(50);
|
||||||
shutDownButton.SetY(50 + image.GetClipH() * 1);
|
shutDownButton.SetY(50 + buttonImage.GetClipH() * 1);
|
||||||
|
|
||||||
//set the button texts
|
//set the button texts
|
||||||
disconnectButton.SetText("Disconnect");
|
disconnectButton.SetText("Disconnect");
|
||||||
shutDownButton.SetText("Shut Down");
|
shutDownButton.SetText("Shut Down");
|
||||||
|
|
||||||
|
//load the tilesheet
|
||||||
|
tileSheet.Load(config["dir.tilesets"] + "terrain.bmp", 12, 15);
|
||||||
|
|
||||||
|
//setup the map object
|
||||||
|
mapPager.SetRegionWidth(REGION_WIDTH);
|
||||||
|
mapPager.SetRegionHeight(REGION_HEIGHT);
|
||||||
|
mapPager.SetRegionDepth(REGION_DEPTH);
|
||||||
|
|
||||||
//create the server-side player object
|
//create the server-side player object
|
||||||
NetworkPacket packet;
|
NetworkPacket packet;
|
||||||
packet.meta.type = NetworkPacket::Type::PLAYER_NEW;
|
packet.meta.type = NetworkPacket::Type::PLAYER_NEW;
|
||||||
@@ -65,11 +80,17 @@ InWorld::InWorld(ConfigUtility* const argConfig, UDPNetworkUtility* const argNet
|
|||||||
packet.playerInfo.motion = {0,0};
|
packet.playerInfo.motion = {0,0};
|
||||||
|
|
||||||
//send it
|
//send it
|
||||||
network.Send(Channels::SERVER, &packet, sizeof(NetworkPacket));
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
serialize(&packet, buffer);
|
||||||
|
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
|
||||||
|
|
||||||
//request a sync
|
//request a sync
|
||||||
packet.meta.type = NetworkPacket::Type::SYNCHRONIZE;
|
packet.meta.type = NetworkPacket::Type::SYNCHRONIZE;
|
||||||
network.Send(Channels::SERVER, &packet, sizeof(NetworkPacket));
|
serialize(&packet, buffer);
|
||||||
|
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
|
||||||
|
|
||||||
|
//debug
|
||||||
|
// RequestRegion(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
InWorld::~InWorld() {
|
InWorld::~InWorld() {
|
||||||
@@ -85,29 +106,59 @@ void InWorld::FrameStart() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void InWorld::Update(double delta) {
|
void InWorld::Update(double delta) {
|
||||||
//suck in all waiting packets
|
|
||||||
NetworkPacket packet;
|
NetworkPacket packet;
|
||||||
|
|
||||||
|
//suck in all waiting packets
|
||||||
while(network.Receive()) {
|
while(network.Receive()) {
|
||||||
memcpy(&packet, network.GetInData(), sizeof(NetworkPacket));
|
deserialize(&packet, network.GetInData());
|
||||||
packet.meta.srcAddress = network.GetInPacket()->address;
|
packet.meta.srcAddress = network.GetInPacket()->address;
|
||||||
HandlePacket(packet);
|
HandlePacket(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//update the characters
|
||||||
for (auto& it : playerCharacters) {
|
for (auto& it : playerCharacters) {
|
||||||
it.second.Update(delta);
|
it.second.Update(delta);
|
||||||
}
|
}
|
||||||
|
//TODO: sort the players and entities by Y position
|
||||||
|
|
||||||
|
//update the camera
|
||||||
|
if(localCharacter) {
|
||||||
|
camera.x = localCharacter->GetPosition().x - camera.marginX;
|
||||||
|
camera.y = localCharacter->GetPosition().y - camera.marginY;
|
||||||
|
}
|
||||||
|
|
||||||
|
//check the map
|
||||||
|
UpdateMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InWorld::FrameEnd() {
|
void InWorld::FrameEnd() {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InWorld::RenderFrame() {
|
||||||
|
// SDL_FillRect(GetScreen(), 0, 0);
|
||||||
|
Render(GetScreen());
|
||||||
|
SDL_Flip(GetScreen());
|
||||||
|
}
|
||||||
|
|
||||||
void InWorld::Render(SDL_Surface* const screen) {
|
void InWorld::Render(SDL_Surface* const screen) {
|
||||||
for (auto& it : playerCharacters) {
|
//draw the map
|
||||||
it.second.DrawTo(screen);
|
for (auto it = mapPager.GetContainer()->begin(); it != mapPager.GetContainer()->end(); it++) {
|
||||||
|
tileSheet.DrawRegionTo(screen, *it, camera.x, camera.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//draw characters
|
||||||
|
for (auto& it : playerCharacters) {
|
||||||
|
it.second.DrawTo(screen, camera.x, camera.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
//draw UI
|
||||||
disconnectButton.DrawTo(screen);
|
disconnectButton.DrawTo(screen);
|
||||||
shutDownButton.DrawTo(screen);
|
shutDownButton.DrawTo(screen);
|
||||||
|
|
||||||
|
font.DrawStringTo(to_string_custom(fps.GetFrameRate()), screen, 0, 0);
|
||||||
|
|
||||||
|
fps.Calculate();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
@@ -209,24 +260,27 @@ void InWorld::KeyUp(SDL_KeyboardEvent const& key) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Network handlers
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
void InWorld::HandlePacket(NetworkPacket packet) {
|
void InWorld::HandlePacket(NetworkPacket packet) {
|
||||||
switch(packet.meta.type) {
|
switch(packet.meta.type) {
|
||||||
case NetworkPacket::Type::DISCONNECT:
|
case NetworkPacket::Type::DISCONNECT:
|
||||||
HandleDisconnect(packet);
|
HandleDisconnect(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NetworkPacket::Type::PLAYER_NEW:
|
case NetworkPacket::Type::PLAYER_NEW:
|
||||||
HandlePlayerNew(packet);
|
HandlePlayerNew(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NetworkPacket::Type::PLAYER_DELETE:
|
case NetworkPacket::Type::PLAYER_DELETE:
|
||||||
HandlePlayerDelete(packet);
|
HandlePlayerDelete(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NetworkPacket::Type::PLAYER_UPDATE:
|
case NetworkPacket::Type::PLAYER_UPDATE:
|
||||||
HandlePlayerUpdate(packet);
|
HandlePlayerUpdate(packet);
|
||||||
break;
|
break;
|
||||||
|
case NetworkPacket::Type::REGION_CONTENT:
|
||||||
|
HandleRegionContent(packet);
|
||||||
|
break;
|
||||||
//handle errors
|
//handle errors
|
||||||
default:
|
default:
|
||||||
throw(std::runtime_error("Unknown NetworkPacket::Type encountered"));
|
throw(std::runtime_error("Unknown NetworkPacket::Type encountered"));
|
||||||
@@ -254,6 +308,12 @@ void InWorld::HandlePlayerNew(NetworkPacket packet) {
|
|||||||
if (packet.playerInfo.clientIndex == clientIndex && !localCharacter) {
|
if (packet.playerInfo.clientIndex == clientIndex && !localCharacter) {
|
||||||
playerIndex = packet.playerInfo.playerIndex;
|
playerIndex = packet.playerInfo.playerIndex;
|
||||||
localCharacter = &playerCharacters[playerIndex];
|
localCharacter = &playerCharacters[playerIndex];
|
||||||
|
//setup the camera
|
||||||
|
camera.width = GetScreen()->w;
|
||||||
|
camera.height = GetScreen()->h;
|
||||||
|
//center on the player's character
|
||||||
|
camera.marginX = (GetScreen()->w / 2 - localCharacter->GetSprite()->GetImage()->GetClipW() / 2);
|
||||||
|
camera.marginY = (GetScreen()->h / 2 - localCharacter->GetSprite()->GetImage()->GetClipH() / 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,31 +345,155 @@ void InWorld::HandlePlayerUpdate(NetworkPacket packet) {
|
|||||||
playerCharacters[packet.playerInfo.playerIndex].ResetDirection();
|
playerCharacters[packet.playerInfo.playerIndex].ResetDirection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InWorld::HandleRegionContent(NetworkPacket packet) {
|
||||||
|
//replace existing regions
|
||||||
|
if (mapPager.FindRegion(packet.regionInfo.x, packet.regionInfo.y)) {
|
||||||
|
mapPager.UnloadRegion(packet.regionInfo.x, packet.regionInfo.y);
|
||||||
|
}
|
||||||
|
mapPager.PushRegion(packet.regionInfo.region);
|
||||||
|
packet.regionInfo.region = nullptr;
|
||||||
|
|
||||||
|
//debugging
|
||||||
|
cout << "Received region: " << packet.regionInfo.x << ", " << packet.regionInfo.y << endl;
|
||||||
|
if (mapPager.FindRegion(packet.regionInfo.x, packet.regionInfo.y)) {
|
||||||
|
cout << "Success" << endl;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cout << "Failure" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Server control
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
void InWorld::SendState() {
|
void InWorld::SendState() {
|
||||||
NetworkPacket packet;
|
NetworkPacket packet;
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
|
//pack the packet
|
||||||
packet.meta.type = NetworkPacket::Type::PLAYER_UPDATE;
|
packet.meta.type = NetworkPacket::Type::PLAYER_UPDATE;
|
||||||
packet.playerInfo.clientIndex = clientIndex;
|
packet.playerInfo.clientIndex = clientIndex;
|
||||||
packet.playerInfo.playerIndex = playerIndex;
|
packet.playerInfo.playerIndex = playerIndex;
|
||||||
// snprintf(packet.playerInfo.handle, PACKET_STRING_SIZE, "%s", config["player.handle"].c_str());
|
|
||||||
// snprintf(packet.playerInfo.avatar, PACKET_STRING_SIZE, "%s", config["player.avatar"].c_str());
|
|
||||||
packet.playerInfo.position = localCharacter->GetPosition();
|
packet.playerInfo.position = localCharacter->GetPosition();
|
||||||
packet.playerInfo.motion = localCharacter->GetMotion();
|
packet.playerInfo.motion = localCharacter->GetMotion();
|
||||||
|
|
||||||
network.Send(Channels::SERVER, &packet, sizeof(NetworkPacket));
|
serialize(&packet, buffer);
|
||||||
|
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InWorld::RequestDisconnect() {
|
void InWorld::RequestDisconnect() {
|
||||||
//send a disconnect request
|
|
||||||
NetworkPacket packet;
|
NetworkPacket packet;
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
|
//send a disconnect request
|
||||||
packet.meta.type = NetworkPacket::Type::DISCONNECT;
|
packet.meta.type = NetworkPacket::Type::DISCONNECT;
|
||||||
packet.clientInfo.index = clientIndex;
|
packet.clientInfo.index = clientIndex;
|
||||||
network.Send(Channels::SERVER, &packet, sizeof(NetworkPacket));
|
serialize(&packet, buffer);
|
||||||
|
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InWorld::RequestShutDown() {
|
void InWorld::RequestShutDown() {
|
||||||
//send a shutdown request
|
|
||||||
NetworkPacket packet;
|
NetworkPacket packet;
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
|
//send a shutdown request
|
||||||
packet.meta.type = NetworkPacket::Type::SHUTDOWN;
|
packet.meta.type = NetworkPacket::Type::SHUTDOWN;
|
||||||
packet.clientInfo.index = clientIndex;
|
packet.clientInfo.index = clientIndex;
|
||||||
network.Send(Channels::SERVER, &packet, sizeof(NetworkPacket));
|
serialize(&packet, buffer);
|
||||||
|
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InWorld::RequestRegion(int x, int y) {
|
||||||
|
NetworkPacket packet;
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
|
//pack the region's data
|
||||||
|
packet.meta.type = NetworkPacket::Type::REGION_REQUEST;
|
||||||
|
packet.regionInfo.x = x;
|
||||||
|
packet.regionInfo.y = y;
|
||||||
|
serialize(&packet, buffer);
|
||||||
|
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Utilities
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
int InWorld::CheckBufferDistance(Region* const region) {
|
||||||
|
/* DOCUMENTATION
|
||||||
|
* This algorithm is extremely complex and involed, but initial tests show
|
||||||
|
* that it gives the right answers. The purpose is to determine how far off screen
|
||||||
|
* a certain region is, so that it can be unloaded when necessary.
|
||||||
|
*
|
||||||
|
* If the region is actually onscreen, then there's no reason to run the rest, so
|
||||||
|
* the algorithm corrects for the camera's location, before checking the bounds of
|
||||||
|
* the screen.
|
||||||
|
*
|
||||||
|
* The next part is tricky. If X or Y is negative, then it is divided by the
|
||||||
|
* graphical size of the regions, resulting in a usable integer, representing how
|
||||||
|
* far from the screen it is in "region units". If, however, X or Y is larger than
|
||||||
|
* 0, than first, the size of the screen is subtracted from that variable, before
|
||||||
|
* it is then divided by the graphical size of a region. Finally, to compensate for
|
||||||
|
* the off by one error, 1 is added at the end.
|
||||||
|
*
|
||||||
|
* Since only the magnitude of the distance in either direction is needed, this
|
||||||
|
* method returns the largest absolute value of X or Y.
|
||||||
|
*
|
||||||
|
* The final result of this algorithm is an integer representing how far, rounded
|
||||||
|
* up, a certain region is from the screen's edges in any direction, measured in
|
||||||
|
* "region units". This algorithm may be flawed, in which case, I recommend simply
|
||||||
|
* replacing it with a boolean check, to see if the region's distance from the player
|
||||||
|
* is larger than a certain value. This algorithm lacks the advantages I initially
|
||||||
|
* expected, so that may be beneficial at some point.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//locations relative to the camera
|
||||||
|
int x = region->GetX() - camera.x;
|
||||||
|
int y = region->GetY() - camera.y;
|
||||||
|
|
||||||
|
//if the region is visible, return -1
|
||||||
|
if (x >= -mapPager.GetRegionWidth() * tileSheet.GetTileW() && x < camera.width &&
|
||||||
|
y >= -mapPager.GetRegionHeight() * tileSheet.GetTileH() && y < camera.height) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//prune the screen's area from the algorithm; get the pseudo-indexes
|
||||||
|
if (x < 0) x /= (mapPager.GetRegionWidth() * tileSheet.GetTileW());
|
||||||
|
if (y < 0) y /= (mapPager.GetRegionHeight() * tileSheet.GetTileH());
|
||||||
|
if (x > 0) x = (x - camera.width) / (mapPager.GetRegionWidth() * tileSheet.GetTileW()) + 1;
|
||||||
|
if (y > 0) y = (y - camera.height) / (mapPager.GetRegionHeight() * tileSheet.GetTileH()) + 1;
|
||||||
|
|
||||||
|
//return the pseudo-index with the greatest magnitude
|
||||||
|
return std::max(abs(x), abs(y));
|
||||||
|
}
|
||||||
|
|
||||||
|
void InWorld::UpdateMap() {
|
||||||
|
//prune distant regions
|
||||||
|
for (auto it = mapPager.GetContainer()->begin(); it != mapPager.GetContainer()->end(); /* EMPTY */) {
|
||||||
|
if (CheckBufferDistance(*it) > 2) {
|
||||||
|
//debugging
|
||||||
|
cout << "unloading: " << (*it)->GetX() << ", " << (*it)->GetY() << endl;
|
||||||
|
|
||||||
|
mapPager.UnloadRegion((*it)->GetX(), (*it)->GetY());
|
||||||
|
|
||||||
|
//reset
|
||||||
|
it = mapPager.GetContainer()->begin();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: make the region units official
|
||||||
|
int regionUnitX = mapPager.GetRegionWidth() * tileSheet.GetTileW();
|
||||||
|
int regionUnitY = mapPager.GetRegionHeight() * tileSheet.GetTileH();
|
||||||
|
|
||||||
|
//request empty regions, including buffers (-1 & +1 region unit)
|
||||||
|
for (int i = snapToBase(regionUnitX, camera.x - regionUnitX); i <= snapToBase(regionUnitX, camera.x + camera.width + regionUnitX); i += regionUnitX) {
|
||||||
|
for (int j = snapToBase(regionUnitY, camera.y - regionUnitY); j <= snapToBase(regionUnitY, camera.y + camera.height + regionUnitY); j += regionUnitY) {
|
||||||
|
if (!mapPager.FindRegion(i, j)) {
|
||||||
|
RequestRegion(i, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -22,16 +22,31 @@
|
|||||||
#ifndef INWORLD_HPP_
|
#ifndef INWORLD_HPP_
|
||||||
#define INWORLD_HPP_
|
#define INWORLD_HPP_
|
||||||
|
|
||||||
#include "base_scene.hpp"
|
//maps
|
||||||
|
#include "map_generator.hpp"
|
||||||
|
#include "map_file_format.hpp"
|
||||||
|
#include "region_pager.hpp"
|
||||||
|
|
||||||
#include "config_utility.hpp"
|
//networking
|
||||||
#include "udp_network_utility.hpp"
|
#include "udp_network_utility.hpp"
|
||||||
#include "network_packet.hpp"
|
#include "network_packet.hpp"
|
||||||
|
#include "serial.hpp"
|
||||||
|
|
||||||
|
//graphics
|
||||||
#include "image.hpp"
|
#include "image.hpp"
|
||||||
#include "raster_font.hpp"
|
#include "raster_font.hpp"
|
||||||
#include "button.hpp"
|
#include "button.hpp"
|
||||||
|
#include "tile_sheet.hpp"
|
||||||
|
|
||||||
|
//common
|
||||||
|
#include "config_utility.hpp"
|
||||||
|
#include "frame_rate.hpp"
|
||||||
|
|
||||||
|
//client
|
||||||
|
#include "base_scene.hpp"
|
||||||
#include "player_character.hpp"
|
#include "player_character.hpp"
|
||||||
|
|
||||||
|
//STL
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
class InWorld : public BaseScene {
|
class InWorld : public BaseScene {
|
||||||
@@ -45,6 +60,7 @@ protected:
|
|||||||
void FrameStart();
|
void FrameStart();
|
||||||
void Update(double delta);
|
void Update(double delta);
|
||||||
void FrameEnd();
|
void FrameEnd();
|
||||||
|
void RenderFrame();
|
||||||
void Render(SDL_Surface* const);
|
void Render(SDL_Surface* const);
|
||||||
|
|
||||||
//Event handlers
|
//Event handlers
|
||||||
@@ -55,26 +71,48 @@ protected:
|
|||||||
void KeyDown(SDL_KeyboardEvent const&);
|
void KeyDown(SDL_KeyboardEvent const&);
|
||||||
void KeyUp(SDL_KeyboardEvent const&);
|
void KeyUp(SDL_KeyboardEvent const&);
|
||||||
|
|
||||||
|
//Network handlers
|
||||||
void HandlePacket(NetworkPacket);
|
void HandlePacket(NetworkPacket);
|
||||||
void HandleDisconnect(NetworkPacket);
|
void HandleDisconnect(NetworkPacket);
|
||||||
void HandlePlayerNew(NetworkPacket);
|
void HandlePlayerNew(NetworkPacket);
|
||||||
void HandlePlayerDelete(NetworkPacket);
|
void HandlePlayerDelete(NetworkPacket);
|
||||||
void HandlePlayerUpdate(NetworkPacket);
|
void HandlePlayerUpdate(NetworkPacket);
|
||||||
|
void HandleRegionContent(NetworkPacket);
|
||||||
|
|
||||||
|
//Server control
|
||||||
void SendState();
|
void SendState();
|
||||||
void RequestDisconnect();
|
void RequestDisconnect();
|
||||||
void RequestShutDown();
|
void RequestShutDown();
|
||||||
|
void RequestRegion(int x, int y);
|
||||||
|
|
||||||
//global
|
//utilities
|
||||||
|
int CheckBufferDistance(Region* const);
|
||||||
|
void UpdateMap();
|
||||||
|
|
||||||
|
//globals
|
||||||
ConfigUtility& config;
|
ConfigUtility& config;
|
||||||
|
FrameRate fps;
|
||||||
UDPNetworkUtility& network;
|
UDPNetworkUtility& network;
|
||||||
int& clientIndex;
|
int& clientIndex;
|
||||||
|
|
||||||
//members
|
//graphics
|
||||||
Image image;
|
Image buttonImage;
|
||||||
RasterFont font;
|
RasterFont font;
|
||||||
|
TileSheet tileSheet;
|
||||||
|
|
||||||
|
//map
|
||||||
|
RegionPager<BlankGenerator, DummyFormat> mapPager;
|
||||||
|
|
||||||
|
//UI
|
||||||
Button disconnectButton;
|
Button disconnectButton;
|
||||||
Button shutDownButton;
|
Button shutDownButton;
|
||||||
|
struct {
|
||||||
|
int x = 0, y = 0;
|
||||||
|
int width = 0, height = 0;
|
||||||
|
int marginX = 0, marginY = 0;
|
||||||
|
} camera;
|
||||||
|
|
||||||
|
//game
|
||||||
std::map<int, PlayerCharacter> playerCharacters;
|
std::map<int, PlayerCharacter> playerCharacters;
|
||||||
PlayerCharacter* localCharacter = nullptr;
|
PlayerCharacter* localCharacter = nullptr;
|
||||||
int playerIndex = -1;
|
int playerIndex = -1;
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ void LobbyMenu::Update(double delta) {
|
|||||||
//suck in all waiting packets
|
//suck in all waiting packets
|
||||||
NetworkPacket packet;
|
NetworkPacket packet;
|
||||||
while(network.Receive()) {
|
while(network.Receive()) {
|
||||||
memcpy(&packet, network.GetInData(), sizeof(NetworkPacket));
|
deserialize(&packet, network.GetInData());
|
||||||
packet.meta.srcAddress = network.GetInPacket()->address;
|
packet.meta.srcAddress = network.GetInPacket()->address;
|
||||||
HandlePacket(packet);
|
HandlePacket(packet);
|
||||||
}
|
}
|
||||||
@@ -125,10 +125,14 @@ void LobbyMenu::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
|||||||
|
|
||||||
void LobbyMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
void LobbyMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||||
if (search.MouseButtonUp(button) == Button::State::HOVER) {
|
if (search.MouseButtonUp(button) == Button::State::HOVER) {
|
||||||
//broadcast to the network, or a specific server
|
//the vars
|
||||||
NetworkPacket packet;
|
NetworkPacket packet;
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
|
//broadcast to the network, or a specific server
|
||||||
packet.meta.type = NetworkPacket::Type::BROADCAST_REQUEST;
|
packet.meta.type = NetworkPacket::Type::BROADCAST_REQUEST;
|
||||||
network.Send(config["server.host"].c_str(), config.Int("server.port"), reinterpret_cast<void*>(&packet), sizeof(NetworkPacket));
|
serialize(&packet, buffer);
|
||||||
|
network.Send(config["server.host"].c_str(), config.Int("server.port"), buffer, PACKET_BUFFER_SIZE);
|
||||||
|
|
||||||
//reset the server list
|
//reset the server list
|
||||||
serverInfo.clear();
|
serverInfo.clear();
|
||||||
@@ -136,10 +140,14 @@ void LobbyMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
else if (join.MouseButtonUp(button) == Button::State::HOVER && selection != nullptr) {
|
else if (join.MouseButtonUp(button) == Button::State::HOVER && selection != nullptr) {
|
||||||
//join the selected server
|
//the vars
|
||||||
NetworkPacket packet;
|
NetworkPacket packet;
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
|
//join the selected server
|
||||||
packet.meta.type = NetworkPacket::Type::JOIN_REQUEST;
|
packet.meta.type = NetworkPacket::Type::JOIN_REQUEST;
|
||||||
network.Send(&selection->address, &packet, sizeof(NetworkPacket));
|
serialize(&packet, buffer);
|
||||||
|
network.Send(&selection->address, buffer, PACKET_BUFFER_SIZE);
|
||||||
selection = nullptr;
|
selection = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#include "config_utility.hpp"
|
#include "config_utility.hpp"
|
||||||
#include "udp_network_utility.hpp"
|
#include "udp_network_utility.hpp"
|
||||||
#include "network_packet.hpp"
|
#include "network_packet.hpp"
|
||||||
|
#include "serial.hpp"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright: (c) Kayne Ruse 2013
|
/* Copyright: (c) Kayne Ruse 2014
|
||||||
*
|
*
|
||||||
* This software is provided 'as-is', without any express or implied
|
* This software is provided 'as-is', without any express or implied
|
||||||
* warranty. In no event will the authors be held liable for any damages
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -19,32 +19,30 @@
|
|||||||
* 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 TILE_HPP_
|
#ifndef FRAMERATE_HPP_
|
||||||
#define TILE_HPP_
|
#define FRAMERATE_HPP_
|
||||||
|
|
||||||
//explicitly a POD
|
#include <chrono>
|
||||||
struct Tile {
|
|
||||||
//position relative to the Region
|
|
||||||
int x, y, depth;
|
|
||||||
|
|
||||||
//graphics
|
class FrameRate {
|
||||||
int width, height;
|
public:
|
||||||
int tileIndex;
|
typedef std::chrono::high_resolution_clock Clock;
|
||||||
|
|
||||||
Tile() = default;
|
FrameRate() = default;
|
||||||
Tile(int _x, int _y, int _depth, int _width, int _height, int _tileIndex) {
|
int Calculate() {
|
||||||
//The order of the arguments should be explicit
|
frameCount++;
|
||||||
x = _x;
|
if (Clock::now() - tick >= std::chrono::duration<int>(1)) {
|
||||||
y = _y;
|
lastFrameRate = frameCount;
|
||||||
depth = _depth;
|
frameCount = 0;
|
||||||
width = _width;
|
tick = Clock::now();
|
||||||
height = _height;
|
|
||||||
tileIndex = _tileIndex;
|
|
||||||
}
|
}
|
||||||
|
return lastFrameRate;
|
||||||
|
}
|
||||||
|
int GetFrameRate() { return lastFrameRate; }
|
||||||
|
private:
|
||||||
|
int frameCount = 0;
|
||||||
|
int lastFrameRate = 0;
|
||||||
|
Clock::time_point tick = Clock::now();
|
||||||
};
|
};
|
||||||
|
|
||||||
bool operator<(Tile const& lhs, Tile const& rhs);
|
|
||||||
bool operator>(Tile const& lhs, Tile const& rhs);
|
|
||||||
bool operator==(Tile const& lhs, Tile const& rhs);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#config
|
#config
|
||||||
INCLUDES+=. ..
|
INCLUDES+=. .. ../map
|
||||||
LIBS+=
|
LIBS+=
|
||||||
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2014
|
||||||
|
*
|
||||||
|
* 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 "tile_sheet.hpp"
|
||||||
|
|
||||||
|
void TileSheet::Load(std::string fname, int xc, int yc) {
|
||||||
|
XCount = xc;
|
||||||
|
YCount = yc;
|
||||||
|
image.LoadSurface(fname);
|
||||||
|
image.SetClipW(image.GetClipW()/XCount);
|
||||||
|
image.SetClipH(image.GetClipH()/YCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileSheet::Unload() {
|
||||||
|
image.FreeSurface();
|
||||||
|
XCount = YCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileSheet::DrawTo(SDL_Surface* const dest, int x, int y, Region::type_t tile) {
|
||||||
|
//0 is invisible
|
||||||
|
if (tile == 0) return;
|
||||||
|
image.SetClipX((tile-1) % XCount * image.GetClipW());
|
||||||
|
image.SetClipY((tile-1) / XCount * image.GetClipH());
|
||||||
|
image.DrawTo(dest, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileSheet::DrawRegionTo(SDL_Surface* const dest, Region* const region, int camX, int camY) {
|
||||||
|
Region::type_t tile = 0;
|
||||||
|
for (register int i = 0; i < region->GetWidth(); ++i) {
|
||||||
|
for (register int j = 0; j < region->GetHeight(); ++j) {
|
||||||
|
for (register int k = 0; k < region->GetDepth(); ++k) {
|
||||||
|
tile = region->GetTile(i, j, k);
|
||||||
|
//0 is invisible
|
||||||
|
if (tile == 0) continue;
|
||||||
|
image.SetClipX((tile-1) % XCount * image.GetClipW());
|
||||||
|
image.SetClipY((tile-1) / XCount * image.GetClipH());
|
||||||
|
image.DrawTo(dest,
|
||||||
|
region->GetX() + i * image.GetClipW() - camX,
|
||||||
|
region->GetY() + j * image.GetClipH() - camY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2014
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
#ifndef TILESHEET_HPP_
|
||||||
|
#define TILESHEET_HPP_
|
||||||
|
|
||||||
|
#include "region.hpp"
|
||||||
|
|
||||||
|
#include "image.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class TileSheet {
|
||||||
|
public:
|
||||||
|
TileSheet() = default;
|
||||||
|
TileSheet(std::string f, int x, int y) { Load(f, x, y); }
|
||||||
|
~TileSheet() = default;
|
||||||
|
|
||||||
|
void Load(std::string fname, int XCount, int YCount);
|
||||||
|
void Unload();
|
||||||
|
|
||||||
|
void DrawTo(SDL_Surface* const dest, int x, int y, Region::type_t tile);
|
||||||
|
void DrawRegionTo(SDL_Surface* const dest, Region* const region, int camX, int camY);
|
||||||
|
|
||||||
|
//accessors
|
||||||
|
Image* GetImage() { return ℑ }
|
||||||
|
int GetXCount() { return XCount; }
|
||||||
|
int GetYCount() { return YCount; }
|
||||||
|
int GetTileW() { return image.GetClipW(); }
|
||||||
|
int GetTileH() { return image.GetClipH(); }
|
||||||
|
private:
|
||||||
|
Image image;
|
||||||
|
int XCount = 0, YCount = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -22,6 +22,7 @@ all: $(OBJ) $(OUT)
|
|||||||
ar -crs $(OUT) $(OBJ)
|
ar -crs $(OUT) $(OBJ)
|
||||||
$(MAKE) -C graphics
|
$(MAKE) -C graphics
|
||||||
$(MAKE) -C map
|
$(MAKE) -C map
|
||||||
|
$(MAKE) -C script
|
||||||
$(MAKE) -C network
|
$(MAKE) -C network
|
||||||
$(MAKE) -C ui
|
$(MAKE) -C ui
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2014
|
||||||
|
*
|
||||||
|
* 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_file_format.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
void DummyFormat::Load(Region** const ptr, int width, int height, int depth, int x, int y) {
|
||||||
|
//EMPTY
|
||||||
|
}
|
||||||
|
|
||||||
|
void DummyFormat::Save(Region* const ptr) {
|
||||||
|
//EMPTY
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
void VerboseFormat::Load(Region** const ptr, int x, int y) {
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerboseFormat::Save(Region* const ptr) {
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompactFormat::Load(Region** const ptr, int x, int y) {
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompactFormat::Save(Region* const ptr) {
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
void LuaFormat::Load(Region** const ptr, int width, int height, int depth, int x, int y) {
|
||||||
|
//something to load into
|
||||||
|
(*ptr) = new Region(width, height, depth, x, y);
|
||||||
|
|
||||||
|
//API hook
|
||||||
|
lua_getglobal(state, "Region");
|
||||||
|
lua_getfield(state, -1, "Load");
|
||||||
|
lua_pushlightuserdata(state, *ptr);
|
||||||
|
lua_pushstring(state, saveDir.c_str());
|
||||||
|
if (lua_pcall(state, 2, 1, 0) != LUA_OK) {
|
||||||
|
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(state, -1) ));
|
||||||
|
}
|
||||||
|
if (lua_toboolean(state, -1) == false) {
|
||||||
|
delete (*ptr);
|
||||||
|
(*ptr) = nullptr;
|
||||||
|
}
|
||||||
|
lua_pop(state, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaFormat::Save(Region* const ptr) {
|
||||||
|
//API hook
|
||||||
|
lua_getglobal(state, "Region");
|
||||||
|
lua_getfield(state, -1, "Save");
|
||||||
|
lua_pushlightuserdata(state, ptr);
|
||||||
|
lua_pushstring(state, saveDir.c_str());
|
||||||
|
if (lua_pcall(state, 2, 0, 0) != LUA_OK) {
|
||||||
|
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(state, -1) ));
|
||||||
|
}
|
||||||
|
lua_pop(state, 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2014
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
#ifndef MAPFILEFORMAT_HPP_
|
||||||
|
#define MAPFILEFORMAT_HPP_
|
||||||
|
|
||||||
|
#include "region.hpp"
|
||||||
|
|
||||||
|
#include "lua/lua.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class DummyFormat {
|
||||||
|
public:
|
||||||
|
void Load(Region** const, int width, int height, int depth, int x, int y);
|
||||||
|
void Save(Region* const);
|
||||||
|
|
||||||
|
std::string SetSaveDir(std::string s) { return saveDir = s; }
|
||||||
|
std::string GetSaveDir() { return saveDir; }
|
||||||
|
private:
|
||||||
|
std::string saveDir;
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
class VerboseFormat {
|
||||||
|
public:
|
||||||
|
void Load(Region** const, int width, int height, int depth, int x, int y);
|
||||||
|
void Save(Region* const);
|
||||||
|
|
||||||
|
std::string SetSaveDir(std::string s) { return saveDir = s; }
|
||||||
|
std::string GetSaveDir() { return saveDir; }
|
||||||
|
private:
|
||||||
|
std::string saveDir;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CompactFormat {
|
||||||
|
public:
|
||||||
|
void Load(Region** const, int width, int height, int depth, int x, int y);
|
||||||
|
void Save(Region* const);
|
||||||
|
|
||||||
|
std::string SetSaveDir(std::string s) { return saveDir = s; }
|
||||||
|
std::string GetSaveDir() { return saveDir; }
|
||||||
|
private:
|
||||||
|
std::string saveDir;
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
class LuaFormat {
|
||||||
|
public:
|
||||||
|
void Load(Region** const, int width, int height, int depth, int x, int y);
|
||||||
|
void Save(Region* const);
|
||||||
|
|
||||||
|
std::string SetSaveDir(std::string s) { return saveDir = s; }
|
||||||
|
std::string GetSaveDir() { return saveDir; }
|
||||||
|
|
||||||
|
lua_State* SetLuaState(lua_State* L) { return state = L; }
|
||||||
|
lua_State* GetLuaState() { return state; }
|
||||||
|
private:
|
||||||
|
std::string saveDir;
|
||||||
|
lua_State* state = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2014
|
||||||
|
*
|
||||||
|
* 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_generator.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
void BlankGenerator::Create(Region** const ptr, int width, int height, int depth, int x, int y) {
|
||||||
|
(*ptr) = new Region(width, height, depth, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlankGenerator::Unload(Region* const ptr) {
|
||||||
|
delete ptr;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
void PerlinGenerator::Create(Region** const ptr, int width, int height, int depth, int x, int y) {
|
||||||
|
(*ptr) = new Region(width, height, depth, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PerlinGenerator::Unload(Region* const ptr) {
|
||||||
|
delete ptr;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
void LuaGenerator::Create(Region** const ptr, int width, int height, int depth, int x, int y) {
|
||||||
|
//something to work on
|
||||||
|
(*ptr) = new Region(width, height, depth, x, y);
|
||||||
|
|
||||||
|
//API hook
|
||||||
|
lua_getglobal(state, "Region");
|
||||||
|
lua_getfield(state, -1, "Create");
|
||||||
|
lua_pushlightuserdata(state, *ptr);
|
||||||
|
if (lua_pcall(state, 1, 0, 0) != LUA_OK) {
|
||||||
|
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(state, -1) ));
|
||||||
|
}
|
||||||
|
lua_pop(state, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaGenerator::Unload(Region* const ptr) {
|
||||||
|
//API hook
|
||||||
|
lua_getglobal(state, "Region");
|
||||||
|
lua_getfield(state, -1, "Unload");
|
||||||
|
lua_pushlightuserdata(state, ptr);
|
||||||
|
if (lua_pcall(state, 1, 0, 0) != LUA_OK) {
|
||||||
|
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(state, -1) ));
|
||||||
|
}
|
||||||
|
lua_pop(state, 1);
|
||||||
|
|
||||||
|
//clean up the memory
|
||||||
|
delete ptr;
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright: (c) Kayne Ruse 2013
|
/* Copyright: (c) Kayne Ruse 2014
|
||||||
*
|
*
|
||||||
* This software is provided 'as-is', without any express or implied
|
* This software is provided 'as-is', without any express or implied
|
||||||
* warranty. In no event will the authors be held liable for any damages
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -19,33 +19,38 @@
|
|||||||
* 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 TILESHEETMANAGER_HPP_
|
#ifndef MAPGENERATOR_HPP_
|
||||||
#define TILESHEETMANAGER_HPP_
|
#define MAPGENERATOR_HPP_
|
||||||
|
|
||||||
#include "tile_sheet.hpp"
|
#include "region.hpp"
|
||||||
|
|
||||||
#include <map>
|
#include "lua/lua.hpp"
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class TileSheetManager {
|
class BlankGenerator {
|
||||||
public:
|
public:
|
||||||
TileSheetManager() = default;
|
void Create(Region** const, int width, int height, int depth, int x, int y);
|
||||||
~TileSheetManager() = default;
|
void Unload(Region* const);
|
||||||
|
|
||||||
TileSheet* LoadSheet(std::string fname, Uint16 w, Uint16 h);
|
|
||||||
TileSheet* GetSheet(std::string name);
|
|
||||||
TileSheet* GetSheetByIndex(int tileIndex);
|
|
||||||
void UnloadSheet(std::string name);
|
|
||||||
|
|
||||||
void DrawTo(SDL_Surface* const, int x, int y, int tileIndex);
|
|
||||||
|
|
||||||
int SetRangeEnd(int i) { return rangeEnd += i; }
|
|
||||||
int GetRangeEnd() const { return rangeEnd; }
|
|
||||||
|
|
||||||
std::map<std::string, TileSheet>* GetSheetMap() { return &sheetMap; }
|
|
||||||
private:
|
private:
|
||||||
std::map<std::string, TileSheet> sheetMap;
|
//
|
||||||
int rangeEnd = 0;
|
};
|
||||||
|
/*
|
||||||
|
class PerlinGenerator {
|
||||||
|
public:
|
||||||
|
void Create(Region** const, int width, int height, int depth, int x, int y);
|
||||||
|
void Unload(Region* const);
|
||||||
|
private:
|
||||||
|
//
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
class LuaGenerator {
|
||||||
|
public:
|
||||||
|
void Create(Region** const, int width, int height, int depth, int x, int y);
|
||||||
|
void Unload(Region* const);
|
||||||
|
|
||||||
|
lua_State* SetLuaState(lua_State* L) { return state = L; }
|
||||||
|
lua_State* GetLuaState() { return state; }
|
||||||
|
private:
|
||||||
|
lua_State* state = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
+27
-91
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright: (c) Kayne Ruse 2013
|
/* Copyright: (c) Kayne Ruse 2014
|
||||||
*
|
*
|
||||||
* This software is provided 'as-is', without any express or implied
|
* This software is provided 'as-is', without any express or implied
|
||||||
* warranty. In no event will the authors be held liable for any damages
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -21,103 +21,39 @@
|
|||||||
*/
|
*/
|
||||||
#include "region.hpp"
|
#include "region.hpp"
|
||||||
|
|
||||||
#include "utility.hpp"
|
Region::Region(int argWidth, int argHeight, int argDepth, int argX, int argY):
|
||||||
|
width(argWidth),
|
||||||
#include <stdexcept>
|
height(argHeight),
|
||||||
#include <sstream>
|
depth(argDepth),
|
||||||
|
x(argX),
|
||||||
Region::Region(int _x, int _y, int _w, int _h):
|
y(argY)
|
||||||
x(_x),
|
|
||||||
y(_y),
|
|
||||||
width(_w),
|
|
||||||
height(_h)
|
|
||||||
{
|
{
|
||||||
//make sure that the region's position lines up
|
tiles = new type_t**[width];
|
||||||
if (x != snapToBase(width, x) || y != snapToBase(height, y)) {
|
for (register int i = 0; i < width; ++i) {
|
||||||
std::ostringstream os;
|
tiles[i] = new type_t*[height];
|
||||||
os << "Region is unaligned; x: " << x << ", y: " << y << ", width: " << width << ", height: " << height;
|
for (register int j = 0; j < height; ++j) {
|
||||||
throw(std::runtime_error(os.str()));
|
tiles[i][j] = new type_t[depth];
|
||||||
|
for (register int k = 0; k < depth; ++k) {
|
||||||
|
tiles[i][j][k] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Region::NewTileR(Tile const& tile) {
|
Region::~Region() {
|
||||||
//return 1 for overwrite, 0 for insert
|
for (register int i = 0; i < width; ++i) {
|
||||||
if (!InBoundsR(tile.x, tile.y)) {
|
for (register int j = 0; j < height; j++) {
|
||||||
std::ostringstream os;
|
delete tiles[i][j];
|
||||||
os << "New tile location out of bounds: " <<
|
|
||||||
"(" << x << "," << y << ")->" <<
|
|
||||||
"(" << tile.x << "," << tile.y << ")"
|
|
||||||
;
|
|
||||||
throw(std::runtime_error(os.str()));
|
|
||||||
}
|
}
|
||||||
|
delete tiles[i];
|
||||||
int ret = tiles.erase(tile);
|
}
|
||||||
tiles.insert(tile);
|
delete tiles;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Tile Region::GetTileR(int tx, int ty, int minDepth) {
|
Region::type_t Region::SetTile(int x, int y, int z, type_t v) {
|
||||||
std::set<Tile>::iterator ptr = tiles.begin();
|
return tiles[x][y][z] = v;
|
||||||
|
|
||||||
//skip the tiles that are too deep
|
|
||||||
while(ptr != tiles.end()) {
|
|
||||||
if (ptr->depth >= minDepth) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ptr++;
|
|
||||||
}
|
|
||||||
|
|
||||||
//find the first tile here
|
|
||||||
while(ptr != tiles.end()) {
|
|
||||||
//bounds
|
|
||||||
if ((ptr->x <= tx) && (ptr->y <= ty) && (ptr->x + ptr->width > tx) && (ptr->y + ptr->height > ty)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ptr++;
|
|
||||||
}
|
|
||||||
|
|
||||||
//found it
|
|
||||||
if (ptr != tiles.end()) {
|
|
||||||
return *ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
//a tileIndex of -1 is an error code, the rest is for show
|
|
||||||
return {0,0,0,-1,-1,-1};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Region::DeleteTileR(Tile const& tile) {
|
Region::type_t Region::GetTile(int x, int y, int z) {
|
||||||
if (!InBoundsR(tile.x, tile.y)) {
|
return tiles[x][y][z];
|
||||||
throw(std::runtime_error("Deleted tile location out of bounds"));
|
|
||||||
|
|
||||||
std::ostringstream os;
|
|
||||||
os << "Deleted tile location out of bounds: " <<
|
|
||||||
"(" << x << "," << y << ")->" <<
|
|
||||||
"(" << tile.x << "," << tile.y << ")"
|
|
||||||
;
|
|
||||||
throw(std::runtime_error(os.str()));
|
|
||||||
}
|
|
||||||
//sentinel/error code
|
|
||||||
if (tile.tileIndex == -1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return tiles.erase(tile);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator<(Region const& lhs, Region const& rhs) {
|
|
||||||
//sort by y -> x
|
|
||||||
if (lhs.y == rhs.y) {
|
|
||||||
return lhs.x < rhs.x;
|
|
||||||
}
|
|
||||||
return lhs.y < rhs.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator>(Region const& lhs, Region const& rhs) {
|
|
||||||
//wrap the other operator
|
|
||||||
return rhs < lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator==(Region const& lhs, Region const& rhs) {
|
|
||||||
//comparisons work on the location ONLY
|
|
||||||
//this function is redundant as far as the std::set object is concerned
|
|
||||||
return (lhs.x == rhs.x) && (lhs.y == rhs.y);
|
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-77
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright: (c) Kayne Ruse 2013
|
/* Copyright: (c) Kayne Ruse 2014
|
||||||
*
|
*
|
||||||
* This software is provided 'as-is', without any express or implied
|
* This software is provided 'as-is', without any express or implied
|
||||||
* warranty. In no event will the authors be held liable for any damages
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -22,91 +22,36 @@
|
|||||||
#ifndef REGION_HPP_
|
#ifndef REGION_HPP_
|
||||||
#define REGION_HPP_
|
#define REGION_HPP_
|
||||||
|
|
||||||
#include "tile.hpp"
|
//temporary?
|
||||||
|
#define REGION_WIDTH 20
|
||||||
|
#define REGION_HEIGHT 20
|
||||||
|
#define REGION_DEPTH 3
|
||||||
|
|
||||||
#include <set>
|
|
||||||
|
|
||||||
/* A single section of the map.
|
|
||||||
* This class stores the tiles relative to it's own position, but
|
|
||||||
* there are functions for referencing the tiles' absolute position.
|
|
||||||
* These functions simply wrap the normal functions.
|
|
||||||
*/
|
|
||||||
class Region {
|
class Region {
|
||||||
public:
|
public:
|
||||||
|
typedef unsigned short type_t;
|
||||||
|
|
||||||
Region() = delete;
|
Region() = delete;
|
||||||
Region(int x, int y, int width, int height);
|
Region(int width, int height, int depth, int x, int y);
|
||||||
~Region() = default;
|
~Region();
|
||||||
|
|
||||||
//create and insert a new tile, overwriting an existing tile at that location
|
type_t SetTile(int x, int y, int z, type_t v);
|
||||||
int NewTileR(Tile const& tile);
|
type_t GetTile(int x, int y, int z);
|
||||||
int NewTileA(Tile const& tile) {
|
|
||||||
//these can change, if the Tile class is changed
|
|
||||||
return NewTileR({
|
|
||||||
tile.x - x,
|
|
||||||
tile.y - y,
|
|
||||||
tile.depth,
|
|
||||||
tile.width,
|
|
||||||
tile.height,
|
|
||||||
tile.tileIndex
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//find the first tile at this location, with the specified minimum depth
|
//accessors
|
||||||
Tile GetTileR(int tx, int ty, int minDepth);
|
|
||||||
Tile GetTileA(int tx, int ty, int minDepth) {
|
|
||||||
return GetTileR(tx - x, ty - y, minDepth);
|
|
||||||
}
|
|
||||||
|
|
||||||
//wrap the other delete functions
|
|
||||||
int DeleteTileR(int tx, int ty, int minDepth) {
|
|
||||||
return DeleteTileR(GetTileR(tx, ty, minDepth));
|
|
||||||
}
|
|
||||||
int DeleteTileA(int tx, int ty, int minDepth) {
|
|
||||||
//explicitly skip one function call by adjusting from A to R
|
|
||||||
return DeleteTileR(GetTileR(tx - x, ty - y, minDepth));
|
|
||||||
}
|
|
||||||
|
|
||||||
//delete the specified tile
|
|
||||||
int DeleteTileR(Tile const& tile);
|
|
||||||
int DeleteTileA(Tile const& tile) {
|
|
||||||
//these can change, if the Tile class is changed
|
|
||||||
return DeleteTileR({
|
|
||||||
tile.x - x,
|
|
||||||
tile.y - y,
|
|
||||||
tile.depth,
|
|
||||||
tile.width,
|
|
||||||
tile.height,
|
|
||||||
tile.tileIndex
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//find if the specified location exists within the region's bounds
|
|
||||||
bool InBoundsR(int i, int j) {
|
|
||||||
return (i >= 0) && (j >= 0) && (i < width) && (j < height);
|
|
||||||
}
|
|
||||||
bool InBoundsA(int i, int j) {
|
|
||||||
return InBoundsR(i - x, j - y);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Raw accessors & mutators
|
|
||||||
int GetX() const { return x; }
|
|
||||||
int GetY() const { return y; }
|
|
||||||
int GetWidth() const { return width; }
|
int GetWidth() const { return width; }
|
||||||
int GetHeight() const { return height; }
|
int GetHeight() const { return height; }
|
||||||
|
int GetDepth() const { return depth; }
|
||||||
std::set<Tile>* GetTiles() { return &tiles; }
|
int GetX() const { return x; }
|
||||||
|
int GetY() const { return y; }
|
||||||
//sorting the regions by the locations
|
|
||||||
friend bool operator<(Region const& lhs, Region const& rhs);
|
|
||||||
friend bool operator>(Region const& lhs, Region const& rhs);
|
|
||||||
friend bool operator==(Region const& lhs, Region const& rhs);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int const x;
|
const int width;
|
||||||
int const y;
|
const int height;
|
||||||
int const width;
|
const int depth;
|
||||||
int const height;
|
const int x;
|
||||||
std::set<Tile> tiles;
|
const int y;
|
||||||
|
|
||||||
|
type_t*** tiles = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+38
-82
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright: (c) Kayne Ruse 2013
|
/* Copyright: (c) Kayne Ruse 2014
|
||||||
*
|
*
|
||||||
* This software is provided 'as-is', without any express or implied
|
* This software is provided 'as-is', without any express or implied
|
||||||
* warranty. In no event will the authors be held liable for any damages
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -23,99 +23,55 @@
|
|||||||
|
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
RegionPagerBase::RegionPagerBase(int argWidth, int argHeight, int argDepth):
|
||||||
#include <string>
|
regionWidth(argWidth),
|
||||||
|
regionHeight(argHeight),
|
||||||
RegionPager::RegionPager() {
|
regionDepth(argDepth)
|
||||||
//
|
{
|
||||||
|
//EMPTY
|
||||||
}
|
}
|
||||||
|
|
||||||
RegionPager::~RegionPager() {
|
RegionPagerBase::~RegionPagerBase() {
|
||||||
if (onDelete) {
|
//EMPTY
|
||||||
for (auto& i : regionList) {
|
|
||||||
onDelete(&i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Region* RegionPager::NewRegion(int x, int y) {
|
Region::type_t RegionPagerBase::SetTile(int x, int y, int z, Region::type_t v) {
|
||||||
for (auto& i : regionList) {
|
Region* ptr = GetRegion(x, y);
|
||||||
if (i.GetX() == x && i.GetY() == y) {
|
return ptr->SetTile(x - ptr->GetX(), y - ptr->GetY(), z, v);
|
||||||
throw(std::runtime_error("Duplicate Regions detected"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
regionList.push_front({x, y, regionWidth, regionHeight});
|
|
||||||
if (onNew) {
|
|
||||||
onNew(®ionList.front());
|
|
||||||
}
|
|
||||||
return ®ionList.front();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Region* RegionPager::GetRegion(int x, int y) {
|
Region::type_t RegionPagerBase::GetTile(int x, int y, int z) {
|
||||||
for (auto& i : regionList) {
|
Region* ptr = GetRegion(x, y);
|
||||||
if (i.GetX() == x && i.GetY() == y) {
|
return ptr->GetTile(x - ptr->GetX(), y - ptr->GetY(), z);
|
||||||
return &i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//create, insert and return
|
|
||||||
regionList.push_front({x, y, regionWidth, regionHeight});
|
|
||||||
if (onNew) {
|
|
||||||
onNew(®ionList.front());
|
|
||||||
}
|
|
||||||
return ®ionList.front();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegionPager::DeleteRegion(int x, int y) {
|
Region* RegionPagerBase::GetRegion(int x, int y) {
|
||||||
for (std::list<Region>::iterator i = regionList.begin(); i != regionList.end(); i++) {
|
//snap the coords
|
||||||
if (i->GetX() == x && i->GetY() == y) {
|
x = snapToBase(regionWidth, x);
|
||||||
if (onDelete) {
|
y = snapToBase(regionHeight, y);
|
||||||
onDelete(&(*i));
|
|
||||||
}
|
//get the region by various means
|
||||||
regionList.erase(i);
|
|
||||||
break;
|
//TODO: revert this try/catch point
|
||||||
}
|
Region* ptr = nullptr;
|
||||||
}
|
ptr = FindRegion(x, y);
|
||||||
|
if (ptr) return ptr;
|
||||||
|
ptr = LoadRegion(x, y);
|
||||||
|
if (ptr) return ptr;
|
||||||
|
return CreateRegion(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegionPager::DrawTo(SDL_Surface* const dest, TileSheetManager* const sheetMgr, int camX, int camY) {
|
Region* RegionPagerBase::FindRegion(int x, int y) {
|
||||||
for (auto& regionIter : regionList) {
|
//find the region
|
||||||
|
for (std::list<Region*>::iterator it = regionList.begin(); it != regionList.end(); it++) {
|
||||||
#ifdef DEBUG
|
if ((*it)->GetX() == x && (*it)->GetY() == y) {
|
||||||
//draw the region's location
|
return *it;
|
||||||
SDL_Rect box = {
|
|
||||||
Sint16(regionIter.GetX() - camX),
|
|
||||||
Sint16(regionIter.GetY() - camY),
|
|
||||||
Uint16(regionIter.GetWidth()),
|
|
||||||
Uint16(regionIter.GetHeight())
|
|
||||||
};
|
|
||||||
SDL_FillRect(dest, &box, SDL_MapRGB(dest->format, 10, 10, 20));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//draw each tile
|
|
||||||
for (auto& tileIter : *regionIter.GetTiles()) {
|
|
||||||
sheetMgr->DrawTo(
|
|
||||||
dest,
|
|
||||||
tileIter.x + regionIter.GetX() - camX,
|
|
||||||
tileIter.y + regionIter.GetY() - camY,
|
|
||||||
tileIter.tileIndex
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegionPager::Prune(int left, int top, int right, int bottom) {
|
Region* RegionPagerBase::PushRegion(Region* ptr) {
|
||||||
std::list<Region>::iterator it = regionList.begin();
|
regionList.push_front(ptr);
|
||||||
|
return regionList.front();
|
||||||
while(it != regionList.end()) {
|
|
||||||
if (it->GetX() >= right || it->GetY() >= bottom || it->GetX() + it->GetWidth() < left || it->GetY() + it->GetHeight() < top) {
|
|
||||||
if (onDelete) {
|
|
||||||
onDelete(&(*it));
|
|
||||||
}
|
|
||||||
regionList.erase(it);
|
|
||||||
it = regionList.begin();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
it++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+116
-28
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright: (c) Kayne Ruse 2013
|
/* Copyright: (c) Kayne Ruse 2014
|
||||||
*
|
*
|
||||||
* This software is provided 'as-is', without any express or implied
|
* This software is provided 'as-is', without any express or implied
|
||||||
* warranty. In no event will the authors be held liable for any damages
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -23,47 +23,135 @@
|
|||||||
#define REGIONPAGER_HPP_
|
#define REGIONPAGER_HPP_
|
||||||
|
|
||||||
#include "region.hpp"
|
#include "region.hpp"
|
||||||
#include "tile_sheet_manager.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
class RegionPager {
|
class RegionPagerBase {
|
||||||
public:
|
public:
|
||||||
//for simplicity and consistency
|
RegionPagerBase() = default;
|
||||||
typedef void (*regionCallback_t)(Region* const);
|
RegionPagerBase(int regionWidth, int regionHeight, int regionDepth);
|
||||||
|
virtual ~RegionPagerBase();
|
||||||
|
|
||||||
RegionPager();
|
//tile manipulation
|
||||||
~RegionPager();
|
Region::type_t SetTile(int x, int y, int z, Region::type_t v);
|
||||||
|
Region::type_t GetTile(int x, int y, int z);
|
||||||
|
|
||||||
//these parameters MUST be multiples of the width & height
|
//region manipulation
|
||||||
Region* NewRegion(int x, int y);
|
|
||||||
Region* GetRegion(int x, int y);
|
Region* GetRegion(int x, int y);
|
||||||
void DeleteRegion(int x, int y);
|
Region* FindRegion(int x, int y);
|
||||||
|
Region* PushRegion(Region*);
|
||||||
|
|
||||||
//call this to draw to the screen
|
//interface
|
||||||
void DrawTo(SDL_Surface* const, TileSheetManager* const, int camX, int camY);
|
virtual Region* LoadRegion(int x, int y) = 0;
|
||||||
|
virtual Region* SaveRegion(int x, int y) = 0;
|
||||||
|
virtual Region* CreateRegion(int x, int y) = 0;
|
||||||
|
virtual void UnloadRegion(int x, int y) = 0;
|
||||||
|
//TODO: delete?
|
||||||
|
|
||||||
//callback hooks
|
//accessors & mutators
|
||||||
void SetOnNew(regionCallback_t f) { onNew = f; }
|
//NOTE: don't change the sizes mid-program, it will cause issues
|
||||||
void SetOnDelete(regionCallback_t f) { onDelete = f; }
|
int SetRegionWidth(int i) { return regionWidth = i; }
|
||||||
|
int SetRegionHeight(int i) { return regionHeight = i; }
|
||||||
|
int SetRegionDepth(int i) { return regionDepth = i; }
|
||||||
|
|
||||||
//params: Absolute values
|
int GetRegionWidth() const { return regionWidth; }
|
||||||
void Prune(int left, int top, int right, int bottom);
|
int GetRegionHeight() const { return regionHeight; }
|
||||||
|
int GetRegionDepth() const { return regionDepth; }
|
||||||
|
|
||||||
//accessors and mutators
|
std::list<Region*>* GetContainer() { return ®ionList; }
|
||||||
int SetWidth(int i) { return regionWidth = i; }
|
protected:
|
||||||
int SetHeight(int i) { return regionHeight = i; }
|
int regionWidth;
|
||||||
|
int regionHeight;
|
||||||
|
int regionDepth;
|
||||||
|
std::list<Region*> regionList;
|
||||||
|
};
|
||||||
|
|
||||||
int GetWidth() const { return regionWidth; }
|
template<typename MapGenerator, typename MapFileFormat>
|
||||||
int GetHeight() const { return regionHeight; }
|
class RegionPager : public RegionPagerBase {
|
||||||
|
public:
|
||||||
|
RegionPager() = default;
|
||||||
|
RegionPager(int w, int h, int d):
|
||||||
|
RegionPagerBase(w, h, d)
|
||||||
|
{
|
||||||
|
//EMPTY
|
||||||
|
}
|
||||||
|
~RegionPager() {
|
||||||
|
UnloadAll();
|
||||||
|
}
|
||||||
|
|
||||||
std::list<Region>* GetRegions() { return ®ionList; }
|
Region* LoadRegion(int x, int y) {
|
||||||
private:
|
//snap the coords
|
||||||
std::list<Region> regionList;
|
x = snapToBase(regionWidth, x);
|
||||||
int regionWidth = 0, regionHeight = 0;
|
y = snapToBase(regionHeight, y);
|
||||||
|
|
||||||
regionCallback_t onNew = nullptr;
|
//load the region if possible
|
||||||
regionCallback_t onDelete = nullptr;
|
Region* ptr = nullptr;
|
||||||
|
format.Load(&ptr, regionWidth, regionHeight, regionDepth, x, y);
|
||||||
|
if (ptr) {
|
||||||
|
regionList.push_back(ptr);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Region* SaveRegion(int x, int y) {
|
||||||
|
//snap the coords
|
||||||
|
x = snapToBase(regionWidth, x);
|
||||||
|
y = snapToBase(regionHeight, y);
|
||||||
|
|
||||||
|
//find & save the region
|
||||||
|
for (std::list<Region*>::iterator it = regionList.begin(); it != regionList.end(); it++) {
|
||||||
|
if ((*it)->GetX() == x && (*it)->GetY() == y) {
|
||||||
|
format.Save(*it);
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Region* CreateRegion(int x, int y) {
|
||||||
|
//snap the coords
|
||||||
|
x = snapToBase(regionWidth, x);
|
||||||
|
y = snapToBase(regionHeight, y);
|
||||||
|
|
||||||
|
//create and push the object
|
||||||
|
Region* ptr = nullptr;
|
||||||
|
generator.Create(&ptr, regionWidth, regionHeight, regionDepth, x, y);
|
||||||
|
regionList.push_back(ptr);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnloadRegion(int x, int y) {
|
||||||
|
//snap the coords
|
||||||
|
x = snapToBase(regionWidth, x);
|
||||||
|
y = snapToBase(regionHeight, y);
|
||||||
|
|
||||||
|
for (std::list<Region*>::iterator it = regionList.begin(); it != regionList.end(); /* EMPTY */) {
|
||||||
|
if ((*it)->GetX() == x && (*it)->GetY() == y) {
|
||||||
|
generator.Unload(*it);
|
||||||
|
regionList.erase(it);
|
||||||
|
|
||||||
|
//reset the loop, because of reasons
|
||||||
|
it = regionList.begin();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void UnloadAll() {
|
||||||
|
for (auto& it : regionList) {
|
||||||
|
generator.Unload(it);
|
||||||
|
}
|
||||||
|
regionList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
//accessors
|
||||||
|
MapGenerator* GetGenerator() { return &generator; }
|
||||||
|
MapFileFormat* GetFormat() { return &format; }
|
||||||
|
protected:
|
||||||
|
MapGenerator generator;
|
||||||
|
MapFileFormat format;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
/* Copyright: (c) Kayne Ruse 2013
|
|
||||||
*
|
|
||||||
* 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 "tile.hpp"
|
|
||||||
|
|
||||||
bool operator<(Tile const& lhs, Tile const& rhs) {
|
|
||||||
//sort by depth -> y -> x
|
|
||||||
if (lhs.depth == rhs.depth) {
|
|
||||||
if (lhs.y == rhs.y) {
|
|
||||||
return lhs.x < rhs.x;
|
|
||||||
}
|
|
||||||
return lhs.y < rhs.y;
|
|
||||||
}
|
|
||||||
return lhs.depth < rhs.depth;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator>(Tile const& lhs, Tile const& rhs) {
|
|
||||||
//wrap the other operator
|
|
||||||
return rhs < lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator==(Tile const& lhs, Tile const& rhs) {
|
|
||||||
//comparisons work on the location ONLY
|
|
||||||
//this function is redundant as far as the std::set object is concerned
|
|
||||||
return (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.depth == rhs.depth);
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
/* Copyright: (c) Kayne Ruse 2013
|
|
||||||
*
|
|
||||||
* 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 "tile_sheet.hpp"
|
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
void TileSheet::Load(std::string fname, Uint16 w, Uint16 h) {
|
|
||||||
//setup the image
|
|
||||||
image.LoadSurface(fname);
|
|
||||||
image.SetClipW(w);
|
|
||||||
image.SetClipH(h);
|
|
||||||
|
|
||||||
//get the tile counts
|
|
||||||
xCount = image.GetSurface()->w / w;
|
|
||||||
yCount = image.GetSurface()->h / h;
|
|
||||||
totalCount = xCount * yCount;
|
|
||||||
|
|
||||||
//set begin & end (usually temporary)
|
|
||||||
begin = 0;
|
|
||||||
end = totalCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TileSheet::Unload() {
|
|
||||||
image.FreeSurface();
|
|
||||||
totalCount = xCount = yCount = 0;
|
|
||||||
begin = end = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TileSheet::DrawTo(SDL_Surface* const dest, int x, int y, int tileIndex) {
|
|
||||||
if (!InRange(tileIndex)) {
|
|
||||||
throw(std::invalid_argument("Tile index out of range"));
|
|
||||||
}
|
|
||||||
Sint16 clipX = (tileIndex-begin) % xCount * image.GetClipW();
|
|
||||||
Sint16 clipY = (tileIndex-begin) / xCount * image.GetClipH();
|
|
||||||
|
|
||||||
image.SetClipX(clipX);
|
|
||||||
image.SetClipY(clipY);
|
|
||||||
|
|
||||||
image.DrawTo(dest, x, y);
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
/* Copyright: (c) Kayne Ruse 2013
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
#ifndef TILESHEET_HPP_
|
|
||||||
#define TILESHEET_HPP_
|
|
||||||
|
|
||||||
#include "image.hpp"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
/* The TileSheet class is used for drawing tiles of the map to the screen.
|
|
||||||
* This class also tracks the range of the tile images.
|
|
||||||
*/
|
|
||||||
class TileSheet {
|
|
||||||
public:
|
|
||||||
TileSheet() = default;
|
|
||||||
~TileSheet() = default;
|
|
||||||
|
|
||||||
//these load/set functions need to be followed by bookkeeping code
|
|
||||||
//w & h are the width & height of individual tiles
|
|
||||||
//TODO: rename these
|
|
||||||
void Load(std::string fname, Uint16 w, Uint16 h);
|
|
||||||
void Unload();
|
|
||||||
|
|
||||||
void DrawTo(SDL_Surface* const dest, int x, int y, int tileIndex);
|
|
||||||
|
|
||||||
bool InRange(int i) { return i >= begin && i < end; }
|
|
||||||
|
|
||||||
//accessors and mutators
|
|
||||||
Image* GetImage() { return ℑ }
|
|
||||||
|
|
||||||
int GetTileW() const { return image.GetClipW(); }
|
|
||||||
int GetTileH() const { return image.GetClipH(); }
|
|
||||||
|
|
||||||
int GetTotalCount() const { return totalCount; }
|
|
||||||
int GetXCount() const { return xCount; }
|
|
||||||
int GetYCount() const { return yCount; }
|
|
||||||
|
|
||||||
int SetBegin(int i) { return begin = i; }
|
|
||||||
int SetEnd(int i) { return end = i; }
|
|
||||||
|
|
||||||
int GetBegin() const { return begin; }
|
|
||||||
int GetEnd() const { return end; }
|
|
||||||
private:
|
|
||||||
Image image;
|
|
||||||
|
|
||||||
//these are generated and used by internal processes
|
|
||||||
int totalCount = 0, xCount = 0, yCount = 0;
|
|
||||||
int begin = -1, end = -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
/* Copyright: (c) Kayne Ruse 2013
|
|
||||||
*
|
|
||||||
* 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 "tile_sheet_manager.hpp"
|
|
||||||
|
|
||||||
#include "utility.hpp"
|
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
TileSheet* TileSheetManager::LoadSheet(std::string fname, Uint16 w, Uint16 h) {
|
|
||||||
//get the key
|
|
||||||
std::string key = truncatePath(fname);
|
|
||||||
|
|
||||||
//don't override what's already here
|
|
||||||
if (sheetMap.find(key) != sheetMap.end()) {
|
|
||||||
throw(std::runtime_error("Cannot load duplicate tile sheets"));
|
|
||||||
}
|
|
||||||
|
|
||||||
//load & setup the sheet object
|
|
||||||
sheetMap[key].Load(fname, w, h);
|
|
||||||
sheetMap[key].SetBegin(rangeEnd);
|
|
||||||
rangeEnd += sheetMap[key].GetTotalCount();
|
|
||||||
sheetMap[key].SetEnd(rangeEnd);
|
|
||||||
|
|
||||||
//you can modify the object, say, during the save & load routines...
|
|
||||||
return &sheetMap[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
TileSheet* TileSheetManager::GetSheet(std::string name) {
|
|
||||||
return &sheetMap.at(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
TileSheet* TileSheetManager::GetSheetByIndex(int tileIndex) {
|
|
||||||
for (auto& it : sheetMap) {
|
|
||||||
if (it.second.InRange(tileIndex)) {
|
|
||||||
return &it.second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TileSheetManager::UnloadSheet(std::string name) {
|
|
||||||
sheetMap.erase(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TileSheetManager::DrawTo(SDL_Surface* const dest, int x, int y, int tileIndex) {
|
|
||||||
for (auto& it : sheetMap) {
|
|
||||||
if (it.second.InRange(tileIndex)) {
|
|
||||||
it.second.DrawTo(dest, x, y, tileIndex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//No matching tile index
|
|
||||||
throw(std::invalid_argument("Tile index is out of range of all tile sheets"));
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#config
|
#config
|
||||||
INCLUDES+=. ..
|
INCLUDES+=. .. ../map
|
||||||
LIBS+=
|
LIBS+=
|
||||||
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
|||||||
@@ -22,9 +22,10 @@
|
|||||||
#ifndef NETWORKPACKET_HPP_
|
#ifndef NETWORKPACKET_HPP_
|
||||||
#define NETWORKPACKET_HPP_
|
#define NETWORKPACKET_HPP_
|
||||||
|
|
||||||
#include "SDL/SDL_net.h"
|
|
||||||
|
|
||||||
#include "vector2.hpp"
|
#include "vector2.hpp"
|
||||||
|
#include "region.hpp"
|
||||||
|
|
||||||
|
#include "SDL/SDL_net.h"
|
||||||
|
|
||||||
#define PACKET_STRING_SIZE 100
|
#define PACKET_STRING_SIZE 100
|
||||||
|
|
||||||
@@ -61,6 +62,10 @@ union NetworkPacket {
|
|||||||
PLAYER_NEW = 10,
|
PLAYER_NEW = 10,
|
||||||
PLAYER_DELETE = 11,
|
PLAYER_DELETE = 11,
|
||||||
PLAYER_UPDATE = 12,
|
PLAYER_UPDATE = 12,
|
||||||
|
|
||||||
|
//map data
|
||||||
|
REGION_REQUEST = 13,
|
||||||
|
REGION_CONTENT = 14,
|
||||||
};
|
};
|
||||||
|
|
||||||
//metadata on the packet itself
|
//metadata on the packet itself
|
||||||
@@ -75,6 +80,7 @@ union NetworkPacket {
|
|||||||
//TODO: version info
|
//TODO: version info
|
||||||
char name[PACKET_STRING_SIZE];
|
char name[PACKET_STRING_SIZE];
|
||||||
//TODO: player count
|
//TODO: player count
|
||||||
|
//TODO: map format
|
||||||
}serverInfo;
|
}serverInfo;
|
||||||
|
|
||||||
//information about the client
|
//information about the client
|
||||||
@@ -94,6 +100,13 @@ union NetworkPacket {
|
|||||||
Vector2 motion;
|
Vector2 motion;
|
||||||
}playerInfo;
|
}playerInfo;
|
||||||
|
|
||||||
|
//map data
|
||||||
|
struct RegionInformation {
|
||||||
|
Metadata meta;
|
||||||
|
int width, height, depth, x, y;
|
||||||
|
Region* region;
|
||||||
|
}regionInfo;
|
||||||
|
|
||||||
//defaults
|
//defaults
|
||||||
NetworkPacket() {
|
NetworkPacket() {
|
||||||
meta.type = Type::NONE;
|
meta.type = Type::NONE;
|
||||||
|
|||||||
@@ -0,0 +1,299 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2014
|
||||||
|
*
|
||||||
|
* 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 "serial.hpp"
|
||||||
|
|
||||||
|
#include "map_generator.hpp"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//internal serialization functions
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void serializeType(NetworkPacket* packet, char* buffer) {
|
||||||
|
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type));
|
||||||
|
}
|
||||||
|
|
||||||
|
void serializeServer(NetworkPacket* packet, char* buffer) {
|
||||||
|
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type));
|
||||||
|
buffer += sizeof(NetworkPacket::Type);
|
||||||
|
memcpy(buffer, packet->serverInfo.name, PACKET_STRING_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void serializeClient(NetworkPacket* packet, char* buffer) {
|
||||||
|
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type));
|
||||||
|
buffer += sizeof(NetworkPacket::Type);
|
||||||
|
memcpy(buffer, &packet->clientInfo.index, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
void serializePlayer(NetworkPacket* packet, char* buffer) {
|
||||||
|
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type));
|
||||||
|
buffer += sizeof(NetworkPacket::Type);
|
||||||
|
|
||||||
|
//indexes
|
||||||
|
memcpy(buffer, &packet->playerInfo.clientIndex, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
memcpy(buffer, &packet->playerInfo.playerIndex, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
|
||||||
|
//text
|
||||||
|
memcpy(buffer, packet->playerInfo.handle, PACKET_STRING_SIZE);
|
||||||
|
buffer += PACKET_STRING_SIZE;
|
||||||
|
memcpy(buffer, packet->playerInfo.avatar, PACKET_STRING_SIZE);
|
||||||
|
buffer += PACKET_STRING_SIZE;
|
||||||
|
|
||||||
|
//vectors
|
||||||
|
memcpy(buffer, &packet->playerInfo.position.x, sizeof(double));
|
||||||
|
buffer += sizeof(double);
|
||||||
|
memcpy(buffer, &packet->playerInfo.position.y, sizeof(double));
|
||||||
|
buffer += sizeof(double);
|
||||||
|
memcpy(buffer, &packet->playerInfo.motion.x, sizeof(double));
|
||||||
|
buffer += sizeof(double);
|
||||||
|
memcpy(buffer, &packet->playerInfo.motion.y, sizeof(double));
|
||||||
|
}
|
||||||
|
|
||||||
|
void serializeRegionFormat(NetworkPacket* packet, char* buffer) {
|
||||||
|
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type));
|
||||||
|
buffer += sizeof(NetworkPacket::Type);
|
||||||
|
|
||||||
|
//size
|
||||||
|
memcpy(buffer, &packet->regionInfo.width, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
memcpy(buffer, &packet->regionInfo.height, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
memcpy(buffer, &packet->regionInfo.depth, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
|
||||||
|
//x & y
|
||||||
|
memcpy(buffer, &packet->regionInfo.x, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
memcpy(buffer, &packet->regionInfo.y, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
void serializeRegionContent(NetworkPacket* packet, char* buffer) {
|
||||||
|
//format
|
||||||
|
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type));
|
||||||
|
buffer += sizeof(NetworkPacket::Type);
|
||||||
|
|
||||||
|
//size
|
||||||
|
*reinterpret_cast<int*>(buffer) = packet->regionInfo.region->GetWidth();
|
||||||
|
buffer += sizeof(int);
|
||||||
|
*reinterpret_cast<int*>(buffer) = packet->regionInfo.region->GetHeight();
|
||||||
|
buffer += sizeof(int);
|
||||||
|
*reinterpret_cast<int*>(buffer) = packet->regionInfo.region->GetDepth();
|
||||||
|
buffer += sizeof(int);
|
||||||
|
|
||||||
|
//x & y
|
||||||
|
*reinterpret_cast<int*>(buffer) = packet->regionInfo.region->GetX();
|
||||||
|
buffer += sizeof(int);
|
||||||
|
*reinterpret_cast<int*>(buffer) = packet->regionInfo.region->GetY();
|
||||||
|
buffer += sizeof(int);
|
||||||
|
|
||||||
|
//content
|
||||||
|
for (register int i = 0; i < packet->regionInfo.region->GetWidth(); i++) {
|
||||||
|
for (register int j = 0; j < packet->regionInfo.region->GetHeight(); j++) {
|
||||||
|
for (register int k = 0; k < packet->regionInfo.region->GetDepth(); k++) {
|
||||||
|
*reinterpret_cast<Region::type_t*>(buffer) = packet->regionInfo.region->GetTile(i, j, k);
|
||||||
|
buffer += sizeof(Region::type_t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//internal deserialization functions
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void deserializeType(NetworkPacket* packet, char* buffer) {
|
||||||
|
memcpy(&packet->meta.type, buffer, sizeof(NetworkPacket::Type));
|
||||||
|
}
|
||||||
|
|
||||||
|
void deserializeServer(NetworkPacket* packet, char* buffer) {
|
||||||
|
memcpy(&packet->meta.type, buffer, sizeof(NetworkPacket::Type));
|
||||||
|
buffer += sizeof(NetworkPacket::Type);
|
||||||
|
memcpy(packet->serverInfo.name, buffer, PACKET_STRING_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deserializeClient(NetworkPacket* packet, char* buffer) {
|
||||||
|
memcpy(&packet->meta.type, buffer, sizeof(NetworkPacket::Type));
|
||||||
|
buffer += sizeof(NetworkPacket::Type);
|
||||||
|
memcpy(&packet->clientInfo.index, buffer, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
void deserializePlayer(NetworkPacket* packet, char* buffer) {
|
||||||
|
memcpy(&packet->meta.type, buffer, sizeof(NetworkPacket::Type));
|
||||||
|
buffer += sizeof(NetworkPacket::Type);
|
||||||
|
|
||||||
|
//indexes
|
||||||
|
memcpy(&packet->playerInfo.clientIndex, buffer, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
memcpy(&packet->playerInfo.playerIndex, buffer, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
|
||||||
|
//text
|
||||||
|
memcpy(packet->playerInfo.handle, buffer, PACKET_STRING_SIZE);
|
||||||
|
buffer += PACKET_STRING_SIZE;
|
||||||
|
memcpy(packet->playerInfo.avatar, buffer, PACKET_STRING_SIZE);
|
||||||
|
buffer += PACKET_STRING_SIZE;
|
||||||
|
|
||||||
|
//vectors
|
||||||
|
memcpy(&packet->playerInfo.position.x, buffer, sizeof(double));
|
||||||
|
buffer += sizeof(double);
|
||||||
|
memcpy(&packet->playerInfo.position.y, buffer, sizeof(double));
|
||||||
|
buffer += sizeof(double);
|
||||||
|
memcpy(&packet->playerInfo.motion.x, buffer, sizeof(double));
|
||||||
|
buffer += sizeof(double);
|
||||||
|
memcpy(&packet->playerInfo.motion.y, buffer, sizeof(double));
|
||||||
|
}
|
||||||
|
|
||||||
|
void deserializeRegionFormat(NetworkPacket* packet, char* buffer) {
|
||||||
|
memcpy(&packet->meta.type, buffer, sizeof(NetworkPacket::Type));
|
||||||
|
buffer += sizeof(NetworkPacket::Type);
|
||||||
|
|
||||||
|
//size
|
||||||
|
memcpy(&packet->regionInfo.width, buffer, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
memcpy(&packet->regionInfo.height, buffer, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
memcpy(&packet->regionInfo.depth, buffer, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
|
||||||
|
//x & y
|
||||||
|
memcpy(&packet->regionInfo.x, buffer, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
memcpy(&packet->regionInfo.y, buffer, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
void deserializeRegionContent(NetworkPacket* packet, char* buffer) {
|
||||||
|
//format
|
||||||
|
deserializeRegionFormat(packet, buffer);
|
||||||
|
buffer += sizeof(int) * 5 + sizeof(NetworkPacket::Type);
|
||||||
|
|
||||||
|
//content
|
||||||
|
BlankGenerator().Create(
|
||||||
|
&packet->regionInfo.region,
|
||||||
|
packet->regionInfo.width,
|
||||||
|
packet->regionInfo.height,
|
||||||
|
packet->regionInfo.depth,
|
||||||
|
packet->regionInfo.x,
|
||||||
|
packet->regionInfo.y
|
||||||
|
);
|
||||||
|
|
||||||
|
for (register int i = 0; i < packet->regionInfo.region->GetWidth(); i++) {
|
||||||
|
for (register int j = 0; j < packet->regionInfo.region->GetHeight(); j++) {
|
||||||
|
for (register int k = 0; k < packet->regionInfo.region->GetDepth(); k++) {
|
||||||
|
packet->regionInfo.region->SetTile(i, j, k, *reinterpret_cast<Region::type_t*>(buffer));
|
||||||
|
buffer += sizeof(Region::type_t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//the interface functions
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void serialize(NetworkPacket* packet, void* buffer) {
|
||||||
|
switch(packet->meta.type) {
|
||||||
|
//No extra data
|
||||||
|
case NetworkPacket::Type::NONE:
|
||||||
|
case NetworkPacket::Type::PING:
|
||||||
|
case NetworkPacket::Type::PONG:
|
||||||
|
case NetworkPacket::Type::BROADCAST_REQUEST:
|
||||||
|
case NetworkPacket::Type::JOIN_REQUEST:
|
||||||
|
case NetworkPacket::Type::SYNCHRONIZE:
|
||||||
|
serializeType(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
break;
|
||||||
|
|
||||||
|
//Server info
|
||||||
|
case NetworkPacket::Type::BROADCAST_RESPONSE:
|
||||||
|
serializeServer(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
break;
|
||||||
|
|
||||||
|
//Client info
|
||||||
|
case NetworkPacket::Type::JOIN_RESPONSE:
|
||||||
|
case NetworkPacket::Type::DISCONNECT:
|
||||||
|
case NetworkPacket::Type::SHUTDOWN:
|
||||||
|
serializeClient(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
break;
|
||||||
|
|
||||||
|
//Player info
|
||||||
|
case NetworkPacket::Type::PLAYER_NEW:
|
||||||
|
case NetworkPacket::Type::PLAYER_DELETE:
|
||||||
|
case NetworkPacket::Type::PLAYER_UPDATE:
|
||||||
|
serializePlayer(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
break;
|
||||||
|
|
||||||
|
//region info
|
||||||
|
case NetworkPacket::Type::REGION_REQUEST:
|
||||||
|
serializeRegionFormat(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NetworkPacket::Type::REGION_CONTENT:
|
||||||
|
serializeRegionContent(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void deserialize(NetworkPacket* packet, void* buffer) {
|
||||||
|
//find the type, so that you can actually deserialize the packet!
|
||||||
|
deserializeType(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
switch(packet->meta.type) {
|
||||||
|
//No extra data
|
||||||
|
case NetworkPacket::Type::NONE:
|
||||||
|
case NetworkPacket::Type::PING:
|
||||||
|
case NetworkPacket::Type::PONG:
|
||||||
|
case NetworkPacket::Type::BROADCAST_REQUEST:
|
||||||
|
case NetworkPacket::Type::JOIN_REQUEST:
|
||||||
|
case NetworkPacket::Type::SYNCHRONIZE:
|
||||||
|
//NOTHING
|
||||||
|
break;
|
||||||
|
|
||||||
|
//Server info
|
||||||
|
case NetworkPacket::Type::BROADCAST_RESPONSE:
|
||||||
|
deserializeServer(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
break;
|
||||||
|
|
||||||
|
//Client info
|
||||||
|
case NetworkPacket::Type::JOIN_RESPONSE:
|
||||||
|
case NetworkPacket::Type::DISCONNECT:
|
||||||
|
case NetworkPacket::Type::SHUTDOWN:
|
||||||
|
deserializeClient(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
break;
|
||||||
|
|
||||||
|
//Player info
|
||||||
|
case NetworkPacket::Type::PLAYER_NEW:
|
||||||
|
case NetworkPacket::Type::PLAYER_DELETE:
|
||||||
|
case NetworkPacket::Type::PLAYER_UPDATE:
|
||||||
|
deserializePlayer(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
break;
|
||||||
|
|
||||||
|
//region info
|
||||||
|
case NetworkPacket::Type::REGION_REQUEST:
|
||||||
|
deserializeRegionFormat(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NetworkPacket::Type::REGION_CONTENT:
|
||||||
|
deserializeRegionContent(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright: (c) Kayne Ruse 2013
|
/* Copyright: (c) Kayne Ruse 2014
|
||||||
*
|
*
|
||||||
* This software is provided 'as-is', without any express or implied
|
* This software is provided 'as-is', without any express or implied
|
||||||
* warranty. In no event will the authors be held liable for any damages
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -19,25 +19,19 @@
|
|||||||
* 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 PLAYER_HPP_
|
#ifndef SERIAL_HPP_
|
||||||
#define PLAYER_HPP_
|
#define SERIAL_HPP_
|
||||||
|
|
||||||
#include "vector2.hpp"
|
#include "network_packet.hpp"
|
||||||
|
|
||||||
#include <string>
|
/* Sending regions are the largest type of packet
|
||||||
#include <map>
|
* content: width * height * depth * sizoeof(type)
|
||||||
|
* map format: sizeof(int) * 5
|
||||||
/* Hold the player info.
|
* metadata: sizeof(metadata)
|
||||||
*/
|
*/
|
||||||
|
#define PACKET_BUFFER_SIZE REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH * sizeof(Region::type_t) + sizeof(int) * 5 + sizeof(NetworkPacket::Metadata)
|
||||||
|
|
||||||
struct Player {
|
void serialize(NetworkPacket* const, void*);
|
||||||
int clientIndex;
|
void deserialize(NetworkPacket* const, void*);
|
||||||
std::string handle;
|
|
||||||
std::string avatar;
|
|
||||||
Vector2 position;
|
|
||||||
Vector2 motion;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::map<int, Player> PlayerMap;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
** $Id: linit.c,v 1.32 2011/04/08 19:17:36 roberto Exp $
|
||||||
|
** Initialization of libraries for lua.c and other clients
|
||||||
|
** See Copyright Notice in lua.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Modified for use in Tortuga, renamed to linit.cpp
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** If you embed Lua in your program and need to open the standard
|
||||||
|
** libraries, call luaL_openlibs in your program. If you need a
|
||||||
|
** different set of libraries, copy this file to your project and edit
|
||||||
|
** it to suit your needs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define linit_c
|
||||||
|
#define LUA_LIB
|
||||||
|
|
||||||
|
#include "lua/lua.hpp"
|
||||||
|
#include "region_api.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** these libs are loaded by lua.c and are readily available to any Lua
|
||||||
|
** program
|
||||||
|
*/
|
||||||
|
static const luaL_Reg loadedlibs[] = {
|
||||||
|
/* Standard libs */
|
||||||
|
{"_G", luaopen_base},
|
||||||
|
{LUA_LOADLIBNAME, luaopen_package},
|
||||||
|
{LUA_COLIBNAME, luaopen_coroutine},
|
||||||
|
{LUA_TABLIBNAME, luaopen_table},
|
||||||
|
{LUA_IOLIBNAME, luaopen_io},
|
||||||
|
{LUA_OSLIBNAME, luaopen_os},
|
||||||
|
{LUA_STRLIBNAME, luaopen_string},
|
||||||
|
{LUA_BITLIBNAME, luaopen_bit32},
|
||||||
|
{LUA_MATHLIBNAME, luaopen_math},
|
||||||
|
{LUA_DBLIBNAME, luaopen_debug},
|
||||||
|
|
||||||
|
/* custom libs */
|
||||||
|
{LUA_REGIONLIBNAME, luaopen_regionapi},
|
||||||
|
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** these libs are preloaded and must be required before used
|
||||||
|
*/
|
||||||
|
static const luaL_Reg preloadedlibs[] = {
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
LUALIB_API void luaL_openlibs (lua_State *L) {
|
||||||
|
const luaL_Reg *lib;
|
||||||
|
/* call open functions from 'loadedlibs' and set results to global table */
|
||||||
|
for (lib = loadedlibs; lib->func; lib++) {
|
||||||
|
luaL_requiref(L, lib->name, lib->func, 1);
|
||||||
|
lua_pop(L, 1); /* remove lib */
|
||||||
|
}
|
||||||
|
/* add open functions from 'preloadedlibs' into 'package.preload' table */
|
||||||
|
luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
|
||||||
|
for (lib = preloadedlibs; lib->func; lib++) {
|
||||||
|
lua_pushcfunction(L, lib->func);
|
||||||
|
lua_setfield(L, -2, lib->name);
|
||||||
|
}
|
||||||
|
lua_pop(L, 1); /* remove _PRELOAD table */
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#config
|
||||||
|
INCLUDES+=. .. ../map
|
||||||
|
LIBS+=
|
||||||
|
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
|
||||||
|
#source
|
||||||
|
CXXSRC=$(wildcard *.cpp)
|
||||||
|
CSRC=$(wildcard *.c)
|
||||||
|
|
||||||
|
#objects
|
||||||
|
OBJDIR=obj
|
||||||
|
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||||
|
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
|
||||||
|
|
||||||
|
#output
|
||||||
|
OUTDIR=../..
|
||||||
|
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
|
||||||
|
|
||||||
|
#targets
|
||||||
|
all: $(OBJ) $(OUT)
|
||||||
|
ar -crs $(OUT) $(OBJ)
|
||||||
|
|
||||||
|
$(OBJ): | $(OBJDIR)
|
||||||
|
|
||||||
|
$(OUT): | $(OUTDIR)
|
||||||
|
|
||||||
|
$(OBJDIR):
|
||||||
|
mkdir $(OBJDIR)
|
||||||
|
|
||||||
|
$(OUTDIR):
|
||||||
|
mkdir $(OUTDIR)
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.cpp
|
||||||
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) *.o *.a *.exe
|
||||||
|
|
||||||
|
rebuild: clean all
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2014
|
||||||
|
*
|
||||||
|
* 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 "region_api.hpp"
|
||||||
|
|
||||||
|
#include "region.hpp"
|
||||||
|
|
||||||
|
static int setTile(lua_State* L) {
|
||||||
|
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||||
|
ptr->SetTile(lua_tointeger(L, 2)-1, lua_tointeger(L, 3)-1, lua_tointeger(L, 4)-1, lua_tointeger(L, 5));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getTile(lua_State* L) {
|
||||||
|
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||||
|
int ret = ptr->GetTile(lua_tointeger(L, 2)-1, lua_tointeger(L, 3)-1, lua_tointeger(L, 4)-1);
|
||||||
|
lua_pushnumber(L, ret);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getWidth(lua_State* L) {
|
||||||
|
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||||
|
lua_pushinteger(L, ptr->GetWidth());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getHeight(lua_State* L) {
|
||||||
|
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||||
|
lua_pushinteger(L, ptr->GetHeight());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getDepth(lua_State* L) {
|
||||||
|
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||||
|
lua_pushinteger(L, ptr->GetDepth());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getX(lua_State* L) {
|
||||||
|
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||||
|
lua_pushinteger(L, ptr->GetX());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getY(lua_State* L) {
|
||||||
|
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||||
|
lua_pushinteger(L, ptr->GetY());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dummy(lua_State* L) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const luaL_Reg regionlib[] = {
|
||||||
|
{"SetTile",setTile},
|
||||||
|
{"GetTile",getTile},
|
||||||
|
{"GetWidth",getWidth},
|
||||||
|
{"GetHeight",getHeight},
|
||||||
|
{"GetDepth",getDepth},
|
||||||
|
{"GetX",getX},
|
||||||
|
{"GetY",getY},
|
||||||
|
{"Create", dummy},
|
||||||
|
{"Unload", dummy},
|
||||||
|
{"Load", dummy},
|
||||||
|
{"Save", dummy},
|
||||||
|
{nullptr, nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
LUAMOD_API int luaopen_regionapi(lua_State* L) {
|
||||||
|
luaL_newlib(L, regionlib);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright: (c) Kayne Ruse 2013
|
/* Copyright: (c) Kayne Ruse 2014
|
||||||
*
|
*
|
||||||
* This software is provided 'as-is', without any express or implied
|
* This software is provided 'as-is', without any express or implied
|
||||||
* warranty. In no event will the authors be held liable for any damages
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -19,20 +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 CLIENT_HPP_
|
#ifndef REGIONAPI_HPP_
|
||||||
#define CLIENT_HPP_
|
#define REGIONAPI_HPP_
|
||||||
|
|
||||||
#include "SDL/SDL_net.h"
|
#include "lua/lua.hpp"
|
||||||
|
|
||||||
#include <map>
|
#define LUA_REGIONLIBNAME "Region"
|
||||||
|
LUAMOD_API int luaopen_regionapi(lua_State* L);
|
||||||
/* Hold the client info.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct Client {
|
|
||||||
IPaddress address;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::map<int, Client> ClientMap;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
+2
-2
@@ -27,9 +27,9 @@ int snapToBase(int base, int x) {
|
|||||||
//snap to a grid
|
//snap to a grid
|
||||||
if (x < 0) {
|
if (x < 0) {
|
||||||
x++;
|
x++;
|
||||||
return x - x % base - base;
|
return x / base * base - base;
|
||||||
}
|
}
|
||||||
return x - x % base;
|
return x / base * base;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string truncatePath(std::string pathname) {
|
std::string truncatePath(std::string pathname) {
|
||||||
|
|||||||
+98
-145
@@ -50,25 +50,24 @@ EditorScene::EditorScene(ConfigUtility* const arg1):
|
|||||||
menuBar.SetImage(&buttonImage);
|
menuBar.SetImage(&buttonImage);
|
||||||
|
|
||||||
menuBar.SetEntries({
|
menuBar.SetEntries({
|
||||||
{"File", "-New", "-Open", "-Save", "-Save As...", "-Close", "Exit"},
|
{"File", "New", "Open", "Save", "Close"},
|
||||||
{"Edit", "-Set Tile", "-Load Sheet", "-Delete Sheet", "-Metadata", "-Run Script"},
|
{"Edit", "Set Tile", "Set Brush", "Script"},
|
||||||
{"Debugging", "Debug On", "Debug Off", "Toggle Debug", "Testificate"}
|
{"Debug", "Debug On", "Debug Off", "Toggle", "Testificate"}
|
||||||
});
|
});
|
||||||
|
|
||||||
//setup the pager
|
//setup the map
|
||||||
pager.SetOnNew([](Region* const ptr){
|
pager.SetRegionWidth(REGION_WIDTH);
|
||||||
printf("New Region: %d, %d\n", ptr->GetX(), ptr->GetY());
|
pager.SetRegionHeight(REGION_HEIGHT);
|
||||||
});
|
pager.SetRegionDepth(REGION_DEPTH);
|
||||||
|
|
||||||
pager.SetOnDelete([](Region* const ptr){
|
//debug
|
||||||
printf("Delete Region: %d, %d\n", ptr->GetX(), ptr->GetY());
|
tsheet.Load(config["dir.tilesets"] + "terrain.bmp", 12, 15);
|
||||||
});
|
for (int i = 0; i < REGION_WIDTH; i++) {
|
||||||
|
for (int j = 0; j < REGION_HEIGHT; j++) {
|
||||||
//Set a resonable size for the regions
|
pager.SetTile(i, j, 0, 14);
|
||||||
pager.SetWidth(32*4);
|
}
|
||||||
pager.SetHeight(32*4);
|
}
|
||||||
|
pager.SetTile(5, 10, 1, 48);
|
||||||
sheetMgr.LoadSheet(config["dir.tilesets"] + "terrain.bmp", 32, 32);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorScene::~EditorScene() {
|
EditorScene::~EditorScene() {
|
||||||
@@ -84,7 +83,7 @@ void EditorScene::FrameStart() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EditorScene::Update(double delta) {
|
void EditorScene::Update(double delta) {
|
||||||
pager.Prune(camera.x, camera.y, camera.x + GetScreen()->w, camera.y + GetScreen()->h);
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorScene::FrameEnd() {
|
void EditorScene::FrameEnd() {
|
||||||
@@ -92,10 +91,23 @@ void EditorScene::FrameEnd() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EditorScene::Render(SDL_Surface* const screen) {
|
void EditorScene::Render(SDL_Surface* const screen) {
|
||||||
//draw the map
|
tsheet.DrawRegionTo(screen, pager.GetRegion(0, 0), camera.x, camera.y);
|
||||||
pager.DrawTo(screen, &sheetMgr, camera.x, camera.y);
|
/* //debug
|
||||||
|
for (int i = 0; i < pager.GetRegionWidth()*2; i++) {
|
||||||
//draw a big bar across the top
|
for (int j = 0; j < pager.GetRegionHeight()*2; j++) {
|
||||||
|
for (int k = 0; k < pager.GetRegionDepth(); k++) {
|
||||||
|
//TODO: skip the out-of-bounds regions
|
||||||
|
tsheet.DrawTo(
|
||||||
|
screen,
|
||||||
|
i*tsheet.GetTileW()-camera.x,
|
||||||
|
j*tsheet.GetTileH()-camera.y,
|
||||||
|
pager.GetTile(i,j,k)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
//draw a big bar across the top (hackish)
|
||||||
buttonImage.SetClipY(0);
|
buttonImage.SetClipY(0);
|
||||||
for (int i = 0; i < screen->w; i += buttonImage.GetClipW()) {
|
for (int i = 0; i < screen->w; i += buttonImage.GetClipW()) {
|
||||||
buttonImage.DrawTo(screen, i, 0);
|
buttonImage.DrawTo(screen, i, 0);
|
||||||
@@ -114,13 +126,15 @@ void EditorScene::Render(SDL_Surface* const screen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EditorScene::DrawToDebugInfo(std::string str, int line) {
|
void EditorScene::DrawToDebugInfo(std::string str, int line) {
|
||||||
//draw the debug info on the right
|
//draw the debug info on the right, with a grey background
|
||||||
font.DrawStringTo(
|
SDL_Rect clip = {
|
||||||
str,
|
Sint16(debugInfo.GetClipW() - str.size() * font.GetCharW()),
|
||||||
debugInfo.GetSurface(),
|
Sint16(font.GetCharH() * line),
|
||||||
debugInfo.GetClipW() - str.size() * font.GetCharW(),
|
Uint16(str.size() * font.GetCharW()),
|
||||||
font.GetCharH() * line
|
Uint16(font.GetCharH())
|
||||||
);
|
};
|
||||||
|
SDL_FillRect(debugInfo.GetSurface(), &clip, SDL_MapRGB(debugInfo.GetSurface()->format, 64, 64, 64));
|
||||||
|
font.DrawStringTo(str, debugInfo.GetSurface(), clip.x, clip.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
@@ -130,24 +144,6 @@ void EditorScene::DrawToDebugInfo(std::string str, int line) {
|
|||||||
void EditorScene::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
void EditorScene::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||||
menuBar.MouseMotion(motion);
|
menuBar.MouseMotion(motion);
|
||||||
|
|
||||||
if (motion.state & SDL_BUTTON_LMASK && motion.y >= buttonImage.GetClipH()) {
|
|
||||||
Region* regionPtr = pager.GetRegion(
|
|
||||||
snapToBase(pager.GetWidth(), motion.x + camera.x),
|
|
||||||
snapToBase(pager.GetHeight(), motion.y + camera.y)
|
|
||||||
);
|
|
||||||
|
|
||||||
TileSheet* sheetPtr = sheetMgr.GetSheetByIndex(tileCounter);
|
|
||||||
|
|
||||||
regionPtr->NewTileA({
|
|
||||||
snapToBase(sheetPtr->GetTileW(), motion.x + camera.x), //x
|
|
||||||
snapToBase(sheetPtr->GetTileH(), motion.y + camera.y), //y
|
|
||||||
0, //depth
|
|
||||||
sheetPtr->GetTileW(), //width
|
|
||||||
sheetPtr->GetTileH(), //height
|
|
||||||
tileCounter++ //value
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (motion.state & SDL_BUTTON_RMASK) {
|
if (motion.state & SDL_BUTTON_RMASK) {
|
||||||
camera.x -= motion.xrel;
|
camera.x -= motion.xrel;
|
||||||
camera.y -= motion.yrel;
|
camera.y -= motion.yrel;
|
||||||
@@ -156,108 +152,12 @@ void EditorScene::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
|||||||
|
|
||||||
void EditorScene::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
void EditorScene::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||||
menuBar.MouseButtonDown(button);
|
menuBar.MouseButtonDown(button);
|
||||||
|
|
||||||
if (button.button == SDL_BUTTON_LEFT && button.y >= buttonImage.GetClipH()) {
|
|
||||||
Region* regionPtr = pager.GetRegion(
|
|
||||||
snapToBase(pager.GetWidth(), button.x + camera.x),
|
|
||||||
snapToBase(pager.GetHeight(), button.y + camera.y)
|
|
||||||
);
|
|
||||||
|
|
||||||
TileSheet* sheetPtr = sheetMgr.GetSheetByIndex(tileCounter);
|
|
||||||
|
|
||||||
regionPtr->NewTileA({
|
|
||||||
snapToBase(sheetPtr->GetTileW(), button.x + camera.x), //x
|
|
||||||
snapToBase(sheetPtr->GetTileH(), button.y + camera.y), //y
|
|
||||||
0, //depth
|
|
||||||
sheetPtr->GetTileW(), //width
|
|
||||||
sheetPtr->GetTileH(), //height
|
|
||||||
tileCounter++ //value
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorScene::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
void EditorScene::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||||
int entry, drop;
|
int entry, drop;
|
||||||
menuBar.MouseButtonUp(button, &entry, &drop);
|
menuBar.MouseButtonUp(button, &entry, &drop);
|
||||||
|
HandleMenuOption(entry, drop);
|
||||||
//manage input from the menu bar
|
|
||||||
switch(entry) {
|
|
||||||
case 0: //File
|
|
||||||
switch(drop) {
|
|
||||||
case 0:
|
|
||||||
//TODO: NEW
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
//TODO: OPEN
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
//TODO: SAVE
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
//TODO: SAVE AS
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
//TODO: CLOSE
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 5: {
|
|
||||||
//Quit
|
|
||||||
SDL_Event e;
|
|
||||||
e.type = SDL_QUIT;
|
|
||||||
SDL_PushEvent(&e);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1: //Edit
|
|
||||||
switch(drop) {
|
|
||||||
case 0:
|
|
||||||
//TODO: SET TILE
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
//TODO: LOAD SHEET
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
//TODO: DELETE SHEET
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
//TODO: METADATA
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
//TODO: RUN SCRIPT
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2: //Debug
|
|
||||||
switch(drop) {
|
|
||||||
case 0:
|
|
||||||
debugOpen = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
debugOpen = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
debugOpen = !debugOpen;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
SetNextScene(SceneList::TESTIFICATESCENE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorScene::KeyDown(SDL_KeyboardEvent const& key) {
|
void EditorScene::KeyDown(SDL_KeyboardEvent const& key) {
|
||||||
@@ -265,12 +165,10 @@ void EditorScene::KeyDown(SDL_KeyboardEvent const& key) {
|
|||||||
case SDLK_ESCAPE:
|
case SDLK_ESCAPE:
|
||||||
QuitEvent();
|
QuitEvent();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_SPACE:
|
case SDLK_SPACE:
|
||||||
camera.x = 0;
|
camera.x = 0;
|
||||||
camera.y = 0;
|
camera.y = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_TAB:
|
case SDLK_TAB:
|
||||||
debugOpen = !debugOpen;
|
debugOpen = !debugOpen;
|
||||||
break;
|
break;
|
||||||
@@ -280,3 +178,58 @@ void EditorScene::KeyDown(SDL_KeyboardEvent const& key) {
|
|||||||
void EditorScene::KeyUp(SDL_KeyboardEvent const& key) {
|
void EditorScene::KeyUp(SDL_KeyboardEvent const& key) {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Members
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void EditorScene::HandleMenuOption(int entry, int drop) {
|
||||||
|
//manage input from the menu bar
|
||||||
|
switch(entry) {
|
||||||
|
case 0: //File
|
||||||
|
switch(drop) {
|
||||||
|
case 0:
|
||||||
|
//TODO: NEW
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
//TODO: OPEN
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
//TODO: SAVE
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
//TODO: CLOSE
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1: //Edit
|
||||||
|
switch(drop) {
|
||||||
|
case 0:
|
||||||
|
//TODO: SET TILE
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
//TODO: SET BRUSH
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
//TODO: SCRIPT
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: //Debug
|
||||||
|
switch(drop) {
|
||||||
|
case 0:
|
||||||
|
debugOpen = true;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
debugOpen = false;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
debugOpen = !debugOpen;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
SetNextScene(SceneList::TESTIFICATESCENE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,15 +24,15 @@
|
|||||||
|
|
||||||
#include "base_scene.hpp"
|
#include "base_scene.hpp"
|
||||||
|
|
||||||
#include "region_pager.hpp"
|
|
||||||
#include "tile_sheet_manager.hpp"
|
|
||||||
|
|
||||||
#include "config_utility.hpp"
|
#include "config_utility.hpp"
|
||||||
#include "image.hpp"
|
#include "image.hpp"
|
||||||
#include "raster_font.hpp"
|
#include "raster_font.hpp"
|
||||||
#include "menu_bar.hpp"
|
#include "menu_bar.hpp"
|
||||||
|
|
||||||
//#include "map_loader.hpp"
|
#include "region_pager.hpp"
|
||||||
|
#include "map_generator.hpp"
|
||||||
|
#include "map_file_format.hpp"
|
||||||
|
#include "tile_sheet.hpp"
|
||||||
|
|
||||||
class EditorScene : public BaseScene {
|
class EditorScene : public BaseScene {
|
||||||
public:
|
public:
|
||||||
@@ -54,6 +54,9 @@ protected:
|
|||||||
void KeyDown(SDL_KeyboardEvent const&);
|
void KeyDown(SDL_KeyboardEvent const&);
|
||||||
void KeyUp(SDL_KeyboardEvent const&);
|
void KeyUp(SDL_KeyboardEvent const&);
|
||||||
|
|
||||||
|
//members
|
||||||
|
void HandleMenuOption(int entry, int drop);
|
||||||
|
|
||||||
//globals
|
//globals
|
||||||
ConfigUtility& config;
|
ConfigUtility& config;
|
||||||
|
|
||||||
@@ -62,19 +65,16 @@ protected:
|
|||||||
Image debugInfo;
|
Image debugInfo;
|
||||||
bool debugOpen = true;
|
bool debugOpen = true;
|
||||||
|
|
||||||
RegionPager pager;
|
|
||||||
TileSheetManager sheetMgr;
|
|
||||||
|
|
||||||
RasterFont font;
|
RasterFont font;
|
||||||
Image buttonImage;
|
Image buttonImage;
|
||||||
|
|
||||||
MenuBar menuBar;
|
MenuBar menuBar;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int x = 0, y = 0;
|
int x = 0, y = 0;
|
||||||
} camera;
|
} camera;
|
||||||
|
|
||||||
int tileCounter = 0;
|
RegionPager<BlankGenerator, DummyFormat> pager;
|
||||||
|
TileSheet tsheet;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
#config
|
#config
|
||||||
INCLUDES+=../common ../common/graphics ../common/map ../common/ui
|
INCLUDES+=../common ../common/graphics ../common/map ../common/ui
|
||||||
LIBS+=../libcommon.a -lmingw32 -lSDLmain -lSDL
|
LIBS+=../libcommon.a -lmingw32 -lSDLmain -lSDL -llua
|
||||||
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
|
||||||
|
|||||||
@@ -33,18 +33,7 @@ using std::endl;
|
|||||||
TestificateScene::TestificateScene(ConfigUtility* const arg1):
|
TestificateScene::TestificateScene(ConfigUtility* const arg1):
|
||||||
config(*arg1)
|
config(*arg1)
|
||||||
{
|
{
|
||||||
sheetMgr.LoadSheet(config["dir.tilesets"] + "grass.bmp", 32, 32);
|
//
|
||||||
sheetMgr.LoadSheet(config["dir.tilesets"] + "longgrass.bmp", 32, 32);
|
|
||||||
sheetMgr.LoadSheet(config["dir.tilesets"] + "sand.bmp", 32, 32);
|
|
||||||
sheetMgr.LoadSheet(config["dir.tilesets"] + "dirt.bmp", 32, 32);
|
|
||||||
sheetMgr.LoadSheet(config["dir.tilesets"] + "water.bmp", 32, 32);
|
|
||||||
|
|
||||||
cout << "Range End: " << sheetMgr.GetRangeEnd() << endl;
|
|
||||||
|
|
||||||
pager.SetWidth(128);
|
|
||||||
pager.SetHeight(128);
|
|
||||||
|
|
||||||
pager.GetRegion(0, 0)->NewTileR({0, 0, 0, 32, 32, 0});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TestificateScene::~TestificateScene() {
|
TestificateScene::~TestificateScene() {
|
||||||
@@ -68,12 +57,7 @@ void TestificateScene::FrameEnd() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TestificateScene::Render(SDL_Surface* const screen) {
|
void TestificateScene::Render(SDL_Surface* const screen) {
|
||||||
//dump all tile graphics to the screen
|
//
|
||||||
for (int i = 0; i < sheetMgr.GetRangeEnd(); i++) {
|
|
||||||
sheetMgr.DrawTo(screen, i * 32 % screen->w, i * 32 / screen->w * 32, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// pager.DrawTo(screen, &sheetMgr, 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|||||||
@@ -25,8 +25,6 @@
|
|||||||
#include "base_scene.hpp"
|
#include "base_scene.hpp"
|
||||||
|
|
||||||
#include "config_utility.hpp"
|
#include "config_utility.hpp"
|
||||||
#include "tile_Sheet_manager.hpp"
|
|
||||||
#include "region_pager.hpp"
|
|
||||||
|
|
||||||
class TestificateScene : public BaseScene {
|
class TestificateScene : public BaseScene {
|
||||||
public:
|
public:
|
||||||
@@ -50,10 +48,6 @@ protected:
|
|||||||
|
|
||||||
//globals
|
//globals
|
||||||
ConfigUtility& config;
|
ConfigUtility& config;
|
||||||
|
|
||||||
//members
|
|
||||||
TileSheetManager sheetMgr;
|
|
||||||
RegionPager pager;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -17,6 +17,11 @@ dir.tilesets = rsc/graphics/tilesets/
|
|||||||
dir.interface = rsc/graphics/interface/
|
dir.interface = rsc/graphics/interface/
|
||||||
dir.scripts = rsc/scripts/
|
dir.scripts = rsc/scripts/
|
||||||
|
|
||||||
|
#map system
|
||||||
|
map.pager.width = 20
|
||||||
|
map.pager.height = 20
|
||||||
|
map.pager.depth = 3
|
||||||
|
|
||||||
#player options
|
#player options
|
||||||
player.handle = username
|
player.handle = username
|
||||||
player.avatar = elliot2.bmp
|
player.avatar = elliot2.bmp
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 18 KiB |
@@ -0,0 +1,29 @@
|
|||||||
|
print("Lua script check OK (./rsc)")
|
||||||
|
|
||||||
|
function Region.Create(r)
|
||||||
|
print("Region:Create(r", Region.GetX(r), Region.GetY(r), ")")
|
||||||
|
for i = 1, Region.GetWidth(r) do
|
||||||
|
for j = 1, Region.GetHeight(r) do
|
||||||
|
if math.abs(i) == math.abs(j) then
|
||||||
|
Region.SetTile(r, i, j, 1, 50)
|
||||||
|
else
|
||||||
|
Region.SetTile(r, i, j, 1, 14)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print("done")
|
||||||
|
end
|
||||||
|
|
||||||
|
function Region.Unload(r)
|
||||||
|
print("Region:Unload(r", Region.GetX(r), Region.GetY(r), ")")
|
||||||
|
end
|
||||||
|
|
||||||
|
--return true if file loaded, otherwise return false
|
||||||
|
function Region.Load(r, saveDir)
|
||||||
|
print("Region:Load(r,", saveDir, Region.GetX(r), Region.GetY(r), ")")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function Region.Save(r, saveDir)
|
||||||
|
print("Region:Save(r,", saveDir, Region.GetX(r), Region.GetY(r), ")")
|
||||||
|
end
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
#config
|
#config
|
||||||
INCLUDES+=. ../common ../common/map ../common/network
|
INCLUDES+=. ../common ../common/map ../common/script ../common/network
|
||||||
LIBS+=../libcommon.a -lSDL_net -lwsock32 -liphlpapi -lmingw32 -lSDLmain -lSDL -llua -lsqlite3
|
LIBS+=../libcommon.a -lSDL_net -lwsock32 -liphlpapi -lmingw32 -lSDLmain -lSDL -llua -lsqlite3
|
||||||
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
|||||||
+135
-74
@@ -30,20 +30,28 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
//-------------------------
|
int runSQLScript(sqlite3* db, std::string fname) {
|
||||||
//Define the ServerApplication
|
ifstream is(fname);
|
||||||
//-------------------------
|
if (!is.is_open()) {
|
||||||
|
return -1;
|
||||||
ServerApplication::ServerApplication() {
|
}
|
||||||
//
|
string script;
|
||||||
|
getline(is, script, '\0');
|
||||||
|
is.close();
|
||||||
|
//TODO: flesh out this error if needed
|
||||||
|
if (sqlite3_exec(db, script.c_str(), nullptr, nullptr, nullptr) != SQLITE_OK) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerApplication::~ServerApplication() {
|
//-------------------------
|
||||||
//
|
//Define the public members
|
||||||
}
|
//-------------------------
|
||||||
|
|
||||||
void ServerApplication::Init(int argc, char** argv) {
|
void ServerApplication::Init(int argc, char** argv) {
|
||||||
//TODO: proper command line option parsing
|
cout << "Beginning startup" << endl;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
//load config
|
//load config
|
||||||
config.Load("rsc\\config.cfg");
|
config.Load("rsc\\config.cfg");
|
||||||
@@ -52,101 +60,129 @@ void ServerApplication::Init(int argc, char** argv) {
|
|||||||
if (SDL_Init(0)) {
|
if (SDL_Init(0)) {
|
||||||
throw(runtime_error("Failed to initialize SDL"));
|
throw(runtime_error("Failed to initialize SDL"));
|
||||||
}
|
}
|
||||||
cout << "initialized SDL" << endl;
|
cout << "Initialized SDL" << endl;
|
||||||
|
|
||||||
//Init SDL_net
|
//Init SDL_net
|
||||||
if (SDLNet_Init()) {
|
if (SDLNet_Init()) {
|
||||||
throw(runtime_error("Failed to init SDL_net"));
|
throw(runtime_error("Failed to initialize SDL_net"));
|
||||||
}
|
}
|
||||||
network.Open(config.Int("server.port"), sizeof(NetworkPacket));
|
network.Open(config.Int("server.port"), PACKET_BUFFER_SIZE);
|
||||||
cout << "initialized SDL_net" << endl;
|
cout << "Initialized SDL_net" << endl;
|
||||||
|
|
||||||
//Init SQL
|
//Init SQL
|
||||||
string dbname = (config["server.dbname"].size()) ? config["server.dbname"] : std::string(argv[0]) + ".db"; //fancy and unnecessary
|
ret = sqlite3_open_v2(config["server.dbname"].c_str(), &database, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, nullptr);
|
||||||
int ret = sqlite3_open_v2(dbname.c_str(), &database, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_FULLMUTEX, nullptr);
|
|
||||||
if (ret != SQLITE_OK || !database) {
|
if (ret != SQLITE_OK || !database) {
|
||||||
throw(runtime_error("Failed to open the server database"));
|
throw(runtime_error(string() + "Failed to initialize SQL: " + sqlite3_errmsg(database) ));
|
||||||
}
|
}
|
||||||
cout << "initialized SQL" << endl;
|
cout << "Initialized SQL" << endl;
|
||||||
cout << "Database filename: " << dbname << endl;
|
|
||||||
|
|
||||||
//TODO: move this into a function?
|
//setup the database
|
||||||
//Run setup scripts
|
if (runSQLScript(database, config["dir.scripts"] + "setup_server.sql")) {
|
||||||
ifstream is("rsc\\scripts\\setup_server.sql");
|
throw(runtime_error("Failed to initialize SQL's setup script"));
|
||||||
if (!is.is_open()) {
|
|
||||||
throw(runtime_error("Failed to run database setup script"));
|
|
||||||
}
|
}
|
||||||
string script;
|
cout << "Initialized SQL's setup script" << endl;
|
||||||
getline(is, script, '\0');
|
|
||||||
is.close();
|
//lua
|
||||||
sqlite3_exec(database, script.c_str(), nullptr, nullptr, nullptr);
|
luaState = luaL_newstate();
|
||||||
|
if (!luaState) {
|
||||||
|
throw(runtime_error("Failed to initialize lua"));
|
||||||
|
}
|
||||||
|
luaL_openlibs(luaState);
|
||||||
|
cout << "Initialized lua" << endl;
|
||||||
|
|
||||||
|
//run the startup script
|
||||||
|
if (luaL_dofile(luaState, (config["dir.scripts"] + "setup_server.lua").c_str())) {
|
||||||
|
throw(runtime_error(string() + "Failed to initialize lua's setup script: " + lua_tostring(luaState, -1) ));
|
||||||
|
}
|
||||||
|
cout << "Initialized lua's setup script" << endl;
|
||||||
|
|
||||||
|
//setup the map object
|
||||||
|
mapPager.SetRegionWidth(REGION_WIDTH);
|
||||||
|
mapPager.SetRegionHeight(REGION_HEIGHT);
|
||||||
|
mapPager.SetRegionDepth(REGION_DEPTH);
|
||||||
|
mapPager.GetGenerator()->SetLuaState(luaState);
|
||||||
|
mapPager.GetFormat()->SetLuaState(luaState);
|
||||||
|
mapPager.GetFormat()->SetSaveDir("save/mapname/");
|
||||||
|
//TODO: pass args to the generator & format as needed
|
||||||
|
//NOTE: I might need to rearrange the init process so that lua & SQL can interact
|
||||||
|
// with the map system as needed.
|
||||||
|
cout << "Initialized the map system" << endl;
|
||||||
|
cout << "\tsizeof(NetworkPacket): " << sizeof(NetworkPacket) << endl;
|
||||||
|
cout << "\tPACKET_BUFFER_SIZE: " << PACKET_BUFFER_SIZE << endl;
|
||||||
|
|
||||||
|
//finalize the startup
|
||||||
|
cout << "Startup completed successfully" << endl;
|
||||||
|
|
||||||
|
//debugging
|
||||||
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::Loop() {
|
void ServerApplication::Loop() {
|
||||||
NetworkPacket packet;
|
NetworkPacket packet;
|
||||||
|
|
||||||
while(running) {
|
while(running) {
|
||||||
//suck in the waiting packets & process them
|
//suck in the waiting packets & process them
|
||||||
try {
|
|
||||||
while(network.Receive()) {
|
while(network.Receive()) {
|
||||||
memcpy(&packet, network.GetInData(), sizeof(NetworkPacket));
|
//get the packet
|
||||||
|
deserialize(&packet, network.GetInData());
|
||||||
|
//cache the source address
|
||||||
packet.meta.srcAddress = network.GetInPacket()->address;
|
packet.meta.srcAddress = network.GetInPacket()->address;
|
||||||
|
//we need to go deeper
|
||||||
HandlePacket(packet);
|
HandlePacket(packet);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch(exception& e) {
|
|
||||||
cerr << "Network Error: " << e.what() << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
//give the computer a break
|
//give the computer a break
|
||||||
SDL_Delay(10);
|
SDL_Delay(10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::Quit() {
|
void ServerApplication::Quit() {
|
||||||
//members
|
cout << "Shutting down" << endl;
|
||||||
network.Close();
|
//empty the members
|
||||||
|
mapPager.UnloadAll();
|
||||||
|
//TODO: player manager
|
||||||
|
//TODO: client manager
|
||||||
|
|
||||||
//APIs
|
//APIs
|
||||||
|
lua_close(luaState);
|
||||||
sqlite3_close_v2(database);
|
sqlite3_close_v2(database);
|
||||||
|
network.Close();
|
||||||
SDLNet_Quit();
|
SDLNet_Quit();
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
|
cout << "Shutdown finished" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Define the uber switch
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
void ServerApplication::HandlePacket(NetworkPacket packet) {
|
void ServerApplication::HandlePacket(NetworkPacket packet) {
|
||||||
switch(packet.meta.type) {
|
switch(packet.meta.type) {
|
||||||
case NetworkPacket::Type::BROADCAST_REQUEST:
|
case NetworkPacket::Type::BROADCAST_REQUEST:
|
||||||
HandleBroadcastRequest(packet);
|
HandleBroadcastRequest(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NetworkPacket::Type::JOIN_REQUEST:
|
case NetworkPacket::Type::JOIN_REQUEST:
|
||||||
HandleJoinRequest(packet);
|
HandleJoinRequest(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NetworkPacket::Type::DISCONNECT:
|
case NetworkPacket::Type::DISCONNECT:
|
||||||
HandleDisconnect(packet);
|
HandleDisconnect(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NetworkPacket::Type::SYNCHRONIZE:
|
case NetworkPacket::Type::SYNCHRONIZE:
|
||||||
HandleSynchronize(packet);
|
HandleSynchronize(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NetworkPacket::Type::SHUTDOWN:
|
case NetworkPacket::Type::SHUTDOWN:
|
||||||
HandleShutdown(packet);
|
HandleShutdown(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NetworkPacket::Type::PLAYER_NEW:
|
case NetworkPacket::Type::PLAYER_NEW:
|
||||||
HandlePlayerNew(packet);
|
HandlePlayerNew(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NetworkPacket::Type::PLAYER_DELETE:
|
case NetworkPacket::Type::PLAYER_DELETE:
|
||||||
HandlePlayerDelete(packet);
|
HandlePlayerDelete(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NetworkPacket::Type::PLAYER_UPDATE:
|
case NetworkPacket::Type::PLAYER_UPDATE:
|
||||||
HandlePlayerUpdate(packet);
|
HandlePlayerUpdate(packet);
|
||||||
break;
|
break;
|
||||||
|
case NetworkPacket::Type::REGION_REQUEST:
|
||||||
|
HandleRegionRequest(packet);
|
||||||
|
break;
|
||||||
//handle errors
|
//handle errors
|
||||||
default:
|
default:
|
||||||
throw(runtime_error("Unknown NetworkPacket::Type encountered"));
|
throw(runtime_error("Unknown NetworkPacket::Type encountered"));
|
||||||
@@ -154,61 +190,73 @@ void ServerApplication::HandlePacket(NetworkPacket packet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Handle various network input
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
void ServerApplication::HandleBroadcastRequest(NetworkPacket packet) {
|
void ServerApplication::HandleBroadcastRequest(NetworkPacket packet) {
|
||||||
//send back the server's name
|
//send back the server's metadata
|
||||||
packet.meta.type = NetworkPacket::Type::BROADCAST_RESPONSE;
|
packet.meta.type = NetworkPacket::Type::BROADCAST_RESPONSE;
|
||||||
|
//TODO: version info
|
||||||
snprintf(packet.serverInfo.name, PACKET_STRING_SIZE, "%s", config["server.name"].c_str());
|
snprintf(packet.serverInfo.name, PACKET_STRING_SIZE, "%s", config["server.name"].c_str());
|
||||||
network.Send(&packet.meta.srcAddress, &packet, sizeof(NetworkPacket));
|
//TODO: player count
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
serialize(&packet, buffer);
|
||||||
|
network.Send(&packet.meta.srcAddress, buffer, PACKET_BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::HandleJoinRequest(NetworkPacket packet) {
|
void ServerApplication::HandleJoinRequest(NetworkPacket packet) {
|
||||||
//TODO: prevent duplicate logins from the same address?
|
//register the new client
|
||||||
|
ClientEntry c;
|
||||||
//create the new client, filling it with the correct info
|
c.address = packet.meta.srcAddress;
|
||||||
Client newClient;
|
clientMap[clientCounter] = c;
|
||||||
newClient.address = packet.meta.srcAddress;
|
|
||||||
|
|
||||||
//push the new client
|
|
||||||
clientMap[clientCounter] = newClient;
|
|
||||||
|
|
||||||
//send the client their info
|
//send the client their info
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
packet.meta.type = NetworkPacket::Type::JOIN_RESPONSE;
|
packet.meta.type = NetworkPacket::Type::JOIN_RESPONSE;
|
||||||
packet.clientInfo.index = clientCounter;
|
packet.clientInfo.index = clientCounter;
|
||||||
network.Send(&newClient.address, &packet, sizeof(NetworkPacket));
|
serialize(&packet, buffer);
|
||||||
|
|
||||||
|
network.Send(&clientMap[clientCounter].address, buffer, PACKET_BUFFER_SIZE);
|
||||||
|
|
||||||
//finished this routine
|
//finished this routine
|
||||||
clientCounter++;
|
clientCounter++;
|
||||||
cout << "connect, total: " << clientMap.size() << endl;
|
cout << "Connect, total: " << clientMap.size() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::HandleDisconnect(NetworkPacket packet) {
|
void ServerApplication::HandleDisconnect(NetworkPacket packet) {
|
||||||
//disconnect the specified client
|
//disconnect the specified client
|
||||||
network.Send(&clientMap[packet.clientInfo.index].address, &packet, sizeof(NetworkPacket));
|
//TODO: authenticate who is disconnecting/kicking
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
serialize(&packet, buffer);
|
||||||
|
network.Send(&clientMap[packet.clientInfo.index].address, buffer, PACKET_BUFFER_SIZE);
|
||||||
clientMap.erase(packet.clientInfo.index);
|
clientMap.erase(packet.clientInfo.index);
|
||||||
|
|
||||||
//delete players
|
//delete players from all clients
|
||||||
erase_if(playerMap, [&](pair<int, Player> it) -> bool {
|
|
||||||
if (it.second.clientIndex == packet.clientInfo.index) {
|
|
||||||
NetworkPacket delPacket;
|
NetworkPacket delPacket;
|
||||||
|
|
||||||
//data to delete one specific player
|
|
||||||
delPacket.meta.type = NetworkPacket::Type::PLAYER_DELETE;
|
delPacket.meta.type = NetworkPacket::Type::PLAYER_DELETE;
|
||||||
|
|
||||||
|
erase_if(playerMap, [&](std::pair<int, PlayerEntry> it) -> bool {
|
||||||
|
//find the internal players to delete
|
||||||
|
if (it.second.clientIndex == packet.clientInfo.index) {
|
||||||
delPacket.playerInfo.playerIndex = it.first;
|
delPacket.playerInfo.playerIndex = it.first;
|
||||||
|
//send the delete player command to all clients
|
||||||
//send to all
|
|
||||||
PumpPacket(delPacket);
|
PumpPacket(delPacket);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
cout << "disconnect, total: " << clientMap.size() << endl;
|
//finished this routine
|
||||||
|
cout << "Disconnect, total: " << clientMap.size() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::HandleSynchronize(NetworkPacket packet) {
|
void ServerApplication::HandleSynchronize(NetworkPacket packet) {
|
||||||
//send all the server's data to this client
|
//send all the server's data to this client
|
||||||
|
//TODO: compensate for large distances
|
||||||
NetworkPacket newPacket;
|
NetworkPacket newPacket;
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
//players
|
//players
|
||||||
newPacket.meta.type = NetworkPacket::Type::PLAYER_UPDATE;
|
newPacket.meta.type = NetworkPacket::Type::PLAYER_UPDATE;
|
||||||
@@ -218,7 +266,8 @@ void ServerApplication::HandleSynchronize(NetworkPacket packet) {
|
|||||||
snprintf(newPacket.playerInfo.avatar, PACKET_STRING_SIZE, "%s", it.second.avatar.c_str());
|
snprintf(newPacket.playerInfo.avatar, PACKET_STRING_SIZE, "%s", it.second.avatar.c_str());
|
||||||
newPacket.playerInfo.position = it.second.position;
|
newPacket.playerInfo.position = it.second.position;
|
||||||
newPacket.playerInfo.motion = it.second.motion;
|
newPacket.playerInfo.motion = it.second.motion;
|
||||||
network.Send(&clientMap[packet.clientInfo.index].address, &newPacket, sizeof(NetworkPacket));
|
serialize(&newPacket, buffer);
|
||||||
|
network.Send(&clientMap[packet.clientInfo.index].address, buffer, PACKET_BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,13 +279,15 @@ void ServerApplication::HandleShutdown(NetworkPacket packet) {
|
|||||||
packet.meta.type = NetworkPacket::Type::DISCONNECT;
|
packet.meta.type = NetworkPacket::Type::DISCONNECT;
|
||||||
PumpPacket(packet);
|
PumpPacket(packet);
|
||||||
|
|
||||||
cout << "shutting down" << endl;
|
//finished this routine
|
||||||
|
cout << "Shutdown signal accepted" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::HandlePlayerNew(NetworkPacket packet) {
|
void ServerApplication::HandlePlayerNew(NetworkPacket packet) {
|
||||||
//create the new player object
|
//create the new player object
|
||||||
Player newPlayer;
|
PlayerEntry newPlayer;
|
||||||
newPlayer.clientIndex = packet.playerInfo.clientIndex;
|
newPlayer.clientIndex = packet.playerInfo.clientIndex;
|
||||||
|
newPlayer.mapIndex = 0;
|
||||||
newPlayer.handle = packet.playerInfo.handle;
|
newPlayer.handle = packet.playerInfo.handle;
|
||||||
newPlayer.avatar = packet.playerInfo.avatar;
|
newPlayer.avatar = packet.playerInfo.avatar;
|
||||||
newPlayer.position = {0,0};
|
newPlayer.position = {0,0};
|
||||||
@@ -263,7 +314,7 @@ void ServerApplication::HandlePlayerDelete(NetworkPacket packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//delete players
|
//delete players
|
||||||
erase_if(playerMap, [&](pair<int, Player> it) -> bool {
|
erase_if(playerMap, [&](pair<int, PlayerEntry> it) -> bool {
|
||||||
if (it.first == packet.playerInfo.playerIndex) {
|
if (it.first == packet.playerInfo.playerIndex) {
|
||||||
NetworkPacket delPacket;
|
NetworkPacket delPacket;
|
||||||
|
|
||||||
@@ -292,9 +343,19 @@ void ServerApplication::HandlePlayerUpdate(NetworkPacket packet) {
|
|||||||
PumpPacket(packet);
|
PumpPacket(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServerApplication::HandleRegionRequest(NetworkPacket packet) {
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
packet.meta.type = NetworkPacket::Type::REGION_CONTENT;
|
||||||
|
packet.regionInfo.region = mapPager.GetRegion(packet.regionInfo.x, packet.regionInfo.y);
|
||||||
|
serialize(&packet, buffer);
|
||||||
|
network.Send(&packet.meta.srcAddress, buffer, PACKET_BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
void ServerApplication::PumpPacket(NetworkPacket packet) {
|
void ServerApplication::PumpPacket(NetworkPacket packet) {
|
||||||
//send this packet to all clients
|
//I don't really like this, but it'll do for now
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
serialize(&packet, buffer);
|
||||||
for (auto& it : clientMap) {
|
for (auto& it : clientMap) {
|
||||||
network.Send(&it.second.address, &packet, sizeof(NetworkPacket));
|
network.Send(&it.second.address, buffer, PACKET_BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -22,31 +22,48 @@
|
|||||||
#ifndef SERVERAPPLICATION_HPP_
|
#ifndef SERVERAPPLICATION_HPP_
|
||||||
#define SERVERAPPLICATION_HPP_
|
#define SERVERAPPLICATION_HPP_
|
||||||
|
|
||||||
|
//maps
|
||||||
|
#include "map_generator.hpp"
|
||||||
|
#include "map_file_format.hpp"
|
||||||
|
#include "region_pager.hpp"
|
||||||
|
|
||||||
//networking
|
//networking
|
||||||
#include "network_packet.hpp"
|
#include "network_packet.hpp"
|
||||||
#include "udp_network_utility.hpp"
|
#include "udp_network_utility.hpp"
|
||||||
|
#include "serial.hpp"
|
||||||
|
|
||||||
//APIs
|
//common
|
||||||
#include "sqlite3/sqlite3.h"
|
|
||||||
#include "SDL/SDL.h"
|
|
||||||
|
|
||||||
//misc
|
|
||||||
#include "config_utility.hpp"
|
#include "config_utility.hpp"
|
||||||
#include "vector2.hpp"
|
#include "vector2.hpp"
|
||||||
|
|
||||||
#include "client.hpp"
|
//APIs
|
||||||
#include "player.hpp"
|
#include "lua/lua.hpp"
|
||||||
|
#include "sqlite3/sqlite3.h"
|
||||||
|
#include "SDL/SDL.h"
|
||||||
|
|
||||||
//STL
|
//STL
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
struct ClientEntry {
|
||||||
|
IPaddress address;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PlayerEntry {
|
||||||
|
int clientIndex;
|
||||||
|
int mapIndex;
|
||||||
|
std::string handle;
|
||||||
|
std::string avatar;
|
||||||
|
Vector2 position;
|
||||||
|
Vector2 motion;
|
||||||
|
};
|
||||||
|
|
||||||
//The main application class
|
//The main application class
|
||||||
class ServerApplication {
|
class ServerApplication {
|
||||||
public:
|
public:
|
||||||
//standard functions
|
//standard functions
|
||||||
ServerApplication();
|
ServerApplication() = default;
|
||||||
~ServerApplication();
|
~ServerApplication() = default;
|
||||||
|
|
||||||
void Init(int argc, char** argv);
|
void Init(int argc, char** argv);
|
||||||
void Loop();
|
void Loop();
|
||||||
@@ -64,22 +81,28 @@ private:
|
|||||||
void HandlePlayerNew(NetworkPacket);
|
void HandlePlayerNew(NetworkPacket);
|
||||||
void HandlePlayerDelete(NetworkPacket);
|
void HandlePlayerDelete(NetworkPacket);
|
||||||
void HandlePlayerUpdate(NetworkPacket);
|
void HandlePlayerUpdate(NetworkPacket);
|
||||||
|
void HandleRegionRequest(NetworkPacket);
|
||||||
|
|
||||||
void PumpPacket(NetworkPacket);
|
void PumpPacket(NetworkPacket);
|
||||||
|
|
||||||
|
//maps
|
||||||
|
RegionPager<LuaGenerator, LuaFormat> mapPager;
|
||||||
|
|
||||||
//networking
|
//networking
|
||||||
UDPNetworkUtility network;
|
UDPNetworkUtility network;
|
||||||
|
|
||||||
//database
|
//database
|
||||||
sqlite3* database = nullptr;
|
sqlite3* database = nullptr;
|
||||||
|
|
||||||
|
//lua
|
||||||
|
lua_State* luaState = nullptr;
|
||||||
|
|
||||||
//misc
|
//misc
|
||||||
bool running = true;
|
bool running = true;
|
||||||
ConfigUtility config;
|
ConfigUtility config;
|
||||||
|
|
||||||
//global lists
|
std::map<int, ClientEntry> clientMap;
|
||||||
ClientMap clientMap;
|
std::map<int, PlayerEntry> playerMap;
|
||||||
PlayerMap playerMap;
|
|
||||||
|
|
||||||
int clientCounter = 0;
|
int clientCounter = 0;
|
||||||
int playerCounter = 0;
|
int playerCounter = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user