Merge branch 'login' (read more)

This branch was originally intended to rewrite the login system, but I've discovered some serious problems that could not wait. See the previous commit for more information. Hopefully I can get back to this soon.

I believe this version deserves a new release tag.
This commit is contained in:
Kayne Ruse
2014-04-21 04:00:37 +10:00
12 changed files with 113 additions and 86 deletions
+1
View File
@@ -25,6 +25,7 @@
#include "vector2.hpp" #include "vector2.hpp"
#include "sprite_sheet.hpp" #include "sprite_sheet.hpp"
//TODO: correct the PlayerCharacter class and it's movement system
class PlayerCharacter { class PlayerCharacter {
public: public:
enum class Direction { enum class Direction {
+19 -61
View File
@@ -404,76 +404,34 @@ void InWorld::RequestRegion(int x, int y) {
//Utilities //Utilities
//------------------------- //-------------------------
int InWorld::CheckBufferDistance(Region* const region) { //TODO: convert this into a more generic function?; using parameters for the bounds
/* TODO: Remove InWorld::CheckBufferDistance(), and replace it with a simpler system
* 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 >= -REGION_WIDTH * tileSheet.GetTileW() && x < camera.width &&
y >= -REGION_HEIGHT * tileSheet.GetTileH() && y < camera.height) {
return -1;
}
//prune the screen's area from the algorithm; get the pseudo-indexes
if (x < 0) x /= (REGION_WIDTH * tileSheet.GetTileW());
if (y < 0) y /= (REGION_HEIGHT * tileSheet.GetTileH());
if (x > 0) x = (x - camera.width) / (REGION_WIDTH * tileSheet.GetTileW()) + 1;
if (y > 0) y = (y - camera.height) / (REGION_HEIGHT * tileSheet.GetTileH()) + 1;
//return the pseudo-index with the greatest magnitude
return std::max(abs(x), abs(y));
}
//TODO: eew ugly
void InWorld::UpdateMap() { void InWorld::UpdateMap() {
//these represent the zone of regions that the client needs loaded, including the mandatory buffers (+1/-1)
int xStart = snapToBase(REGION_WIDTH, camera.x/tileSheet.GetTileW()) - REGION_WIDTH;
int xEnd = snapToBase(REGION_WIDTH, (camera.x+camera.width)/tileSheet.GetTileW()) + REGION_WIDTH;
int yStart = snapToBase(REGION_HEIGHT, camera.y/tileSheet.GetTileH()) - REGION_HEIGHT;
int yEnd = snapToBase(REGION_HEIGHT, (camera.y+camera.height)/tileSheet.GetTileH()) + REGION_HEIGHT;
//prune distant regions //prune distant regions
for (auto it = regionPager.GetContainer()->begin(); it != regionPager.GetContainer()->end(); /* EMPTY */) { for (auto it = regionPager.GetContainer()->begin(); it != regionPager.GetContainer()->end(); /* EMPTY */) {
if (CheckBufferDistance(*it) > 2) { //check if the region is outside off this area
regionPager.UnloadRegion((*it)->GetX(), (*it)->GetY()); if ((*it)->GetX() < xStart || (*it)->GetX() > xEnd || (*it)->GetY() < yStart || (*it)->GetY() > yEnd) {
//reset //clunky, but the alternative was time consuming
it = regionPager.GetContainer()->begin(); int tmpX = (*it)->GetX();
int tmpY = (*it)->GetY();
++it;
regionPager.UnloadRegion(tmpX, tmpY);
continue; continue;
} }
++it; ++it;
} }
//TODO: make the region units official? //request empty regions within this zone
int regionUnitX = REGION_WIDTH * tileSheet.GetTileW(); for (int i = xStart; i <= xEnd; i += REGION_WIDTH) {
int regionUnitY = REGION_HEIGHT * tileSheet.GetTileH(); for (int j = yStart; j <= yEnd; j += REGION_HEIGHT) {
//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 (!regionPager.FindRegion(i, j)) { if (!regionPager.FindRegion(i, j)) {
RequestRegion(i, j); RequestRegion(i, j);
} }
-1
View File
@@ -86,7 +86,6 @@ protected:
void RequestRegion(int x, int y); void RequestRegion(int x, int y);
//utilities //utilities
int CheckBufferDistance(Region* const);
void UpdateMap(); void UpdateMap();
//globals //globals
+27 -2
View File
@@ -22,6 +22,7 @@
#include "lobby_menu.hpp" #include "lobby_menu.hpp"
#include "channels.hpp" #include "channels.hpp"
#include "utility.hpp"
#include <stdexcept> #include <stdexcept>
@@ -91,9 +92,13 @@ void LobbyMenu::FrameEnd() {
} }
void LobbyMenu::Render(SDL_Surface* const screen) { void LobbyMenu::Render(SDL_Surface* const screen) {
//TODO: I need a proper UI system for the entire client and the editor
//UI
search.DrawTo(screen); search.DrawTo(screen);
join.DrawTo(screen); join.DrawTo(screen);
back.DrawTo(screen); back.DrawTo(screen);
//TODO: draw headers for the server list
for (int i = 0; i < serverInfo.size(); i++) { for (int i = 0; i < serverInfo.size(); i++) {
//draw the selected server's highlight //draw the selected server's highlight
if (selection == &serverInfo[i]) { if (selection == &serverInfo[i]) {
@@ -104,6 +109,16 @@ void LobbyMenu::Render(SDL_Surface* const screen) {
//draw the server name //draw the server name
font.DrawStringTo(serverInfo[i].name, screen, listBox.x, listBox.y + i*listBox.h); font.DrawStringTo(serverInfo[i].name, screen, listBox.x, listBox.y + i*listBox.h);
//draw the player count
font.DrawStringTo(to_string_custom(serverInfo[i].playerCount), screen, listBox.x + listBox.w, listBox.y + i*listBox.h);
//compatible?
if (!serverInfo[i].compatible) {
font.DrawStringTo("?", screen, listBox.x - font.GetCharW(), listBox.y + i*listBox.h);
}
//TODO: ping?
} }
} }
@@ -139,7 +154,8 @@ void LobbyMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
selection = nullptr; selection = nullptr;
} }
else if (join.MouseButtonUp(button) == Button::State::HOVER && selection != nullptr) { else if (join.MouseButtonUp(button) == Button::State::HOVER && selection != nullptr && selection->compatible) {
//TODO: The player login information should be collected by the lobby screen
//the vars //the vars
SerialPacket packet; SerialPacket packet;
char buffer[PACKET_BUFFER_SIZE]; char buffer[PACKET_BUFFER_SIZE];
@@ -184,9 +200,18 @@ void LobbyMenu::KeyUp(SDL_KeyboardEvent const& key) {
void LobbyMenu::HandlePacket(SerialPacket packet) { void LobbyMenu::HandlePacket(SerialPacket packet) {
switch(packet.meta.type) { switch(packet.meta.type) {
case SerialPacket::Type::BROADCAST_RESPONSE: { case SerialPacket::Type::BROADCAST_RESPONSE: {
//extract the data
ServerInformation server; ServerInformation server;
server.name = packet.serverInfo.name;
server.address = packet.meta.srcAddress; server.address = packet.meta.srcAddress;
server.name = packet.serverInfo.name;
server.playerCount = packet.serverInfo.playerCount;
//NOTE: Check compatibility here
server.compatible = packet.serverInfo.regionWidth == REGION_WIDTH &&
packet.serverInfo.regionHeight == REGION_HEIGHT &&
packet.serverInfo.regionDepth == REGION_DEPTH;
//push
serverInfo.push_back(server); serverInfo.push_back(server);
} }
break; break;
+14 -4
View File
@@ -22,17 +22,24 @@
#ifndef LOBBYMENU_HPP_ #ifndef LOBBYMENU_HPP_
#define LOBBYMENU_HPP_ #define LOBBYMENU_HPP_
#include "base_scene.hpp" //graphics & utilities
#include "image.hpp" #include "image.hpp"
#include "raster_font.hpp" #include "raster_font.hpp"
#include "button.hpp" #include "button.hpp"
#include "config_utility.hpp" #include "config_utility.hpp"
//map
#include "region.hpp"
//network
#include "udp_network_utility.hpp" #include "udp_network_utility.hpp"
#include "serial_packet.hpp" #include "serial_packet.hpp"
#include "serial.hpp" #include "serial.hpp"
//client
#include "base_scene.hpp"
//STL
#include <vector> #include <vector>
class LobbyMenu : public BaseScene { class LobbyMenu : public BaseScene {
@@ -71,8 +78,11 @@ protected:
//server list //server list
struct ServerInformation { struct ServerInformation {
std::string name;
IPaddress address; IPaddress address;
//TODO: version info
std::string name;
int playerCount;
bool compatible;
}; };
std::vector<ServerInformation> serverInfo; std::vector<ServerInformation> serverInfo;
+2 -2
View File
@@ -53,8 +53,8 @@ void TileSheet::DrawRegionTo(SDL_Surface* const dest, Region* const region, int
image.SetClipX((tile-1) % XCount * image.GetClipW()); image.SetClipX((tile-1) % XCount * image.GetClipW());
image.SetClipY((tile-1) / XCount * image.GetClipH()); image.SetClipY((tile-1) / XCount * image.GetClipH());
image.DrawTo(dest, image.DrawTo(dest,
region->GetX() + i * image.GetClipW() - camX, (region->GetX() + i) * image.GetClipW() - camX,
region->GetY() + j * image.GetClipH() - camY); (region->GetY() + j) * image.GetClipH() - camY);
} }
} }
} }
+2 -5
View File
@@ -46,7 +46,7 @@ public:
virtual Region* SaveRegion(int x, int y) = 0; virtual Region* SaveRegion(int x, int y) = 0;
virtual Region* CreateRegion(int x, int y) = 0; virtual Region* CreateRegion(int x, int y) = 0;
virtual void UnloadRegion(int x, int y) = 0; virtual void UnloadRegion(int x, int y) = 0;
//TODO: delete? //TODO: delete existing regions
//accessors & mutators //accessors & mutators
std::list<Region*>* GetContainer() { return &regionList; } std::list<Region*>* GetContainer() { return &regionList; }
@@ -109,10 +109,7 @@ public:
for (std::list<Region*>::iterator it = regionList.begin(); it != regionList.end(); /* EMPTY */) { for (std::list<Region*>::iterator it = regionList.begin(); it != regionList.end(); /* EMPTY */) {
if ((*it)->GetX() == x && (*it)->GetY() == y) { if ((*it)->GetX() == x && (*it)->GetY() == y) {
allocator.Unload(*it); allocator.Unload(*it);
regionList.erase(it); it = regionList.erase(it);
//reset the loop, because of reasons
it = regionList.begin();
continue; continue;
} }
++it; ++it;
+26
View File
@@ -36,7 +36,20 @@ void serializeType(SerialPacket* packet, char* buffer) {
void serializeServer(SerialPacket* packet, char* buffer) { void serializeServer(SerialPacket* packet, char* buffer) {
memcpy(buffer, &packet->meta.type, sizeof(SerialPacket::Type)); memcpy(buffer, &packet->meta.type, sizeof(SerialPacket::Type));
buffer += sizeof(SerialPacket::Type); buffer += sizeof(SerialPacket::Type);
//server info
//Note: version info serialization goes here
memcpy(buffer, packet->serverInfo.name, PACKET_STRING_SIZE); memcpy(buffer, packet->serverInfo.name, PACKET_STRING_SIZE);
buffer += PACKET_STRING_SIZE;
memcpy(buffer, &packet->serverInfo.playerCount, sizeof(int));
buffer += sizeof(int);
//map format
memcpy(buffer, &packet->serverInfo.regionWidth, sizeof(int));
buffer += sizeof(int);
memcpy(buffer, &packet->serverInfo.regionHeight, sizeof(int));
buffer += sizeof(int);
memcpy(buffer, &packet->serverInfo.regionDepth, sizeof(int));
} }
void serializeClient(SerialPacket* packet, char* buffer) { void serializeClient(SerialPacket* packet, char* buffer) {
@@ -114,7 +127,20 @@ void deserializeType(SerialPacket* packet, char* buffer) {
void deserializeServer(SerialPacket* packet, char* buffer) { void deserializeServer(SerialPacket* packet, char* buffer) {
memcpy(&packet->meta.type, buffer, sizeof(SerialPacket::Type)); memcpy(&packet->meta.type, buffer, sizeof(SerialPacket::Type));
buffer += sizeof(SerialPacket::Type); buffer += sizeof(SerialPacket::Type);
//server info
//Note: version info deserialization goes here
memcpy(packet->serverInfo.name, buffer, PACKET_STRING_SIZE); memcpy(packet->serverInfo.name, buffer, PACKET_STRING_SIZE);
buffer += PACKET_STRING_SIZE;
memcpy(&packet->serverInfo.playerCount, buffer, sizeof(int));
buffer += sizeof(int);
//map format
memcpy(&packet->serverInfo.regionWidth, buffer, sizeof(int));
buffer += sizeof(int);
memcpy(&packet->serverInfo.regionHeight, buffer, sizeof(int));
buffer += sizeof(int);
memcpy(&packet->serverInfo.regionDepth, buffer, sizeof(int));
} }
void deserializeClient(SerialPacket* packet, char* buffer) { void deserializeClient(SerialPacket* packet, char* buffer) {
+1 -1
View File
@@ -24,7 +24,7 @@
#include "serial_packet.hpp" #include "serial_packet.hpp"
/* TODO: Keep the PACKET_BUFFER_SIZE up to date /* NOTE: Keep the PACKET_BUFFER_SIZE up to date
* NOTE: REGION_CONTENT is currently the largest type of packet * NOTE: REGION_CONTENT is currently the largest type of packet
* map content: REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH * sizoeof(region::type_t) * map content: REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH * sizoeof(region::type_t)
* map format: sizeof(int) * 2 * map format: sizeof(int) * 2
+7 -4
View File
@@ -79,8 +79,12 @@ union SerialPacket {
Metadata meta; Metadata meta;
//TODO: version info //TODO: version info
char name[PACKET_STRING_SIZE]; char name[PACKET_STRING_SIZE];
//TODO: player count int playerCount;
//TODO: map format
//map format
int regionWidth;
int regionHeight;
int regionDepth;
}serverInfo; }serverInfo;
//information about the client //information about the client
@@ -95,8 +99,7 @@ union SerialPacket {
Metadata meta; Metadata meta;
int clientIndex; int clientIndex;
int playerIndex; int playerIndex;
//TODO: should probably move these into the client info //TODO: should move handle/avatar into clientInfo; these might actually do better during the login system
//TODO: these might actually do better during the login system
char handle[PACKET_STRING_SIZE]; char handle[PACKET_STRING_SIZE];
char avatar[PACKET_STRING_SIZE]; char avatar[PACKET_STRING_SIZE];
Vector2 position; Vector2 position;
+13 -5
View File
@@ -110,7 +110,7 @@ void ServerApplication::Proc() {
HandlePacket(packet); HandlePacket(packet);
} }
//give the computer a break //give the computer a break
//TODO: remove this? //TODO: remove this delay?
SDL_Delay(10); SDL_Delay(10);
} }
} }
@@ -176,10 +176,16 @@ void ServerApplication::HandlePacket(SerialPacket packet) {
void ServerApplication::HandleBroadcastRequest(SerialPacket packet) { void ServerApplication::HandleBroadcastRequest(SerialPacket packet) {
//send back the server's metadata //send back the server's metadata
packet.meta.type = SerialPacket::Type::BROADCAST_RESPONSE; packet.meta.type = SerialPacket::Type::BROADCAST_RESPONSE;
//pack the data
//TODO: version info //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());
//TODO: player count packet.serverInfo.playerCount = playerMap.size();
//TODO: map format packet.serverInfo.regionWidth = REGION_WIDTH;
packet.serverInfo.regionHeight = REGION_HEIGHT;
packet.serverInfo.regionDepth = REGION_DEPTH;
//send the data
char buffer[PACKET_BUFFER_SIZE]; char buffer[PACKET_BUFFER_SIZE];
serialize(&packet, buffer); serialize(&packet, buffer);
network.Send(&packet.meta.srcAddress, buffer, PACKET_BUFFER_SIZE); network.Send(&packet.meta.srcAddress, buffer, PACKET_BUFFER_SIZE);
@@ -246,7 +252,7 @@ void ServerApplication::HandleSynchronize(SerialPacket packet) {
SerialPacket newPacket; SerialPacket newPacket;
char buffer[PACKET_BUFFER_SIZE]; char buffer[PACKET_BUFFER_SIZE];
//TODO: map? //TODO: syncronize the map?
//players //players
newPacket.meta.type = SerialPacket::Type::PLAYER_UPDATE; newPacket.meta.type = SerialPacket::Type::PLAYER_UPDATE;
@@ -308,13 +314,15 @@ void ServerApplication::HandlePlayerNew(SerialPacket packet) {
PlayerEntry::uidCounter++; PlayerEntry::uidCounter++;
} }
//TODO: differentiate between delete and unload
void ServerApplication::HandlePlayerDelete(SerialPacket packet) { void ServerApplication::HandlePlayerDelete(SerialPacket packet) {
//TODO: remove this?
//TODO: authenticate who is deleting this player //TODO: authenticate who is deleting this player
if (playerMap.find(packet.playerInfo.playerIndex) == playerMap.end()) { if (playerMap.find(packet.playerInfo.playerIndex) == playerMap.end()) {
throw(std::runtime_error("Cannot delete a non-existant player")); throw(std::runtime_error("Cannot delete a non-existant player"));
} }
//TODO: remove the deleted player from the database?
//prep the delete packet //prep the delete packet
SerialPacket delPacket; SerialPacket delPacket;
delPacket.meta.type = SerialPacket::Type::PLAYER_DELETE; delPacket.meta.type = SerialPacket::Type::PLAYER_DELETE;
+1 -1
View File
@@ -74,7 +74,7 @@ private:
void HandlePlayerUpdate(SerialPacket); void HandlePlayerUpdate(SerialPacket);
void HandleRegionRequest(SerialPacket); void HandleRegionRequest(SerialPacket);
//TODO: a function that sends to players in a certain proximity //TODO: a function that only sends to players in a certain proximity
void PumpPacket(SerialPacket); void PumpPacket(SerialPacket);
//APIs //APIs