|
@@ -2,12 +2,10 @@
|
|
|
|
|
|
#include <Logging.h>
|
|
|
|
|
|
-#include "AddEntityUpdate.h"
|
|
|
#include "AsynchronCall.h"
|
|
|
#include "Chat.h"
|
|
|
#include "Dimension.h"
|
|
|
#include "Entity.h"
|
|
|
-#include "EntityRemovedUpdate.h"
|
|
|
#include "ItemEntity.h"
|
|
|
#include "JsonUtils.h"
|
|
|
#include "MultiblockTree.h"
|
|
@@ -30,316 +28,11 @@ using namespace Framework;
|
|
|
Framework::ConsoleHandler* Game::consoleHandler = 0;
|
|
|
Framework::InputLine* Game::consoleInput = 0;
|
|
|
|
|
|
-GameClient::GameClient(Player* zPlayer, FCKlient* client)
|
|
|
- : Thread(),
|
|
|
- zPlayer(zPlayer),
|
|
|
- client(client),
|
|
|
- viewDistance(DEFAULT_VIEW_DISTANCE),
|
|
|
- first(1),
|
|
|
- online(1),
|
|
|
- finished(0),
|
|
|
- backgroundFinished(0),
|
|
|
- foregroundFinished(0)
|
|
|
-{
|
|
|
- new AsynchronCall("Game Client Updates", [this]() {
|
|
|
- while (online)
|
|
|
- {
|
|
|
- other.lock();
|
|
|
- if (updateQueue.hat(0))
|
|
|
- {
|
|
|
- WorldUpdate* update = updateQueue.get(0);
|
|
|
- updateQueue.remove(0);
|
|
|
- other.unlock();
|
|
|
- background.lock();
|
|
|
- this->client->zBackgroundWriter()->schreibe(
|
|
|
- (char*)&Message::WORLD_UPDATE, 1);
|
|
|
- update->writeAndCheck(this->client->zBackgroundWriter());
|
|
|
- background.unlock();
|
|
|
- update->release();
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- other.unlock();
|
|
|
- updateSync.wait();
|
|
|
- }
|
|
|
- }
|
|
|
- finished = 1;
|
|
|
- });
|
|
|
- start();
|
|
|
-}
|
|
|
-
|
|
|
-GameClient::~GameClient()
|
|
|
-{
|
|
|
- online = 0;
|
|
|
- updateSync.notify();
|
|
|
- emptyForegroundQueueSync.notifyAll();
|
|
|
- emptyBackgroundQueueSync.notifyAll();
|
|
|
- foregroundQueueSync.notify();
|
|
|
- backgroundQueueSync.notify();
|
|
|
- while (!finished || !foregroundFinished || !backgroundFinished)
|
|
|
- Sleep(100);
|
|
|
- client->release();
|
|
|
-}
|
|
|
-
|
|
|
-void GameClient::thread()
|
|
|
-{
|
|
|
- new AsynchronCall("Game Client Background", [this]() {
|
|
|
- while (online)
|
|
|
- {
|
|
|
- queueCs.lock();
|
|
|
- if (backgroundQueue.hat(0))
|
|
|
- {
|
|
|
- NetworkMessage* message = backgroundQueue.get(0);
|
|
|
- backgroundQueue.remove(0);
|
|
|
- queueCs.unlock();
|
|
|
- background.lock();
|
|
|
- message->writeTo(client->zBackgroundWriter());
|
|
|
- background.unlock();
|
|
|
- message->release();
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- queueCs.unlock();
|
|
|
- emptyBackgroundQueueSync.notifyAll();
|
|
|
- while (!backgroundQueueSync.wait(1000))
|
|
|
- {
|
|
|
- emptyBackgroundQueueSync.notifyAll();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- backgroundFinished = 1;
|
|
|
- });
|
|
|
- while (online)
|
|
|
- {
|
|
|
- queueCs.lock();
|
|
|
- if (foregroundQueue.hat(0))
|
|
|
- {
|
|
|
- NetworkMessage* message = foregroundQueue.get(0);
|
|
|
- foregroundQueue.remove(0);
|
|
|
- queueCs.unlock();
|
|
|
- foreground.lock();
|
|
|
- message->writeTo(client->zForegroundWriter());
|
|
|
- foreground.unlock();
|
|
|
- message->release();
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- queueCs.unlock();
|
|
|
- emptyForegroundQueueSync.notifyAll();
|
|
|
- while (!foregroundQueueSync.wait(1000))
|
|
|
- {
|
|
|
- emptyForegroundQueueSync.notifyAll();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- foregroundFinished = 1;
|
|
|
-}
|
|
|
-
|
|
|
-void GameClient::sendWorldUpdate(WorldUpdate* update)
|
|
|
-{
|
|
|
- bool add = 0;
|
|
|
- if (zPlayer->getDimensionId() == update->getAffectedDimension())
|
|
|
- {
|
|
|
- auto pos = (Vec3<int>)zPlayer->getPosition();
|
|
|
- int dist = update->distanceTo(pos.x, pos.y);
|
|
|
- if (dist < viewDistance * CHUNK_SIZE)
|
|
|
- {
|
|
|
- other.lock();
|
|
|
- updateQueue.add(update);
|
|
|
- other.unlock();
|
|
|
- updateSync.notify();
|
|
|
- add = 1;
|
|
|
- }
|
|
|
- }
|
|
|
- if (!add) update->release();
|
|
|
-}
|
|
|
-
|
|
|
-void GameClient::reply()
|
|
|
-{
|
|
|
- other.lock();
|
|
|
- for (auto req : requests)
|
|
|
- Game::INSTANCE->api(req, this);
|
|
|
- requests.leeren();
|
|
|
- other.unlock();
|
|
|
- if (first)
|
|
|
- {
|
|
|
- foreground.lock();
|
|
|
- int id = zPlayer->getId();
|
|
|
- client->zForegroundWriter()->schreibe(
|
|
|
- (char*)&Message::POSITION_UPDATE, 1);
|
|
|
- client->zForegroundWriter()->schreibe((char*)&id, 4);
|
|
|
- id = zPlayer->getDimensionId();
|
|
|
- client->zForegroundWriter()->schreibe((char*)&id, 4);
|
|
|
- client->zForegroundWriter()->schreibe((char*)&Message::API_MESSAGE, 1);
|
|
|
- int len = 10;
|
|
|
- client->zForegroundWriter()->schreibe((char*)&len, 4);
|
|
|
- client->zForegroundWriter()->schreibe("\1", 1);
|
|
|
- client->zForegroundWriter()->schreibe((char*)&id, 4);
|
|
|
- client->zForegroundWriter()->schreibe("\6", 1);
|
|
|
- float gravity = Game::INSTANCE->zDimension(zPlayer->getDimensionId())
|
|
|
- ->getGravity();
|
|
|
- client->zForegroundWriter()->schreibe((char*)&gravity, 4);
|
|
|
- foreground.unlock();
|
|
|
- first = 0;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void GameClient::logout()
|
|
|
-{
|
|
|
- online = 0;
|
|
|
- updateSync.notify();
|
|
|
- emptyForegroundQueueSync.notifyAll();
|
|
|
- emptyBackgroundQueueSync.notifyAll();
|
|
|
- foregroundQueueSync.notify();
|
|
|
- backgroundQueueSync.notify();
|
|
|
-}
|
|
|
-
|
|
|
-void GameClient::addMessage(StreamReader* reader)
|
|
|
-{
|
|
|
- short len = 0;
|
|
|
- reader->lese((char*)&len, 2);
|
|
|
- InMemoryBuffer* buffer = new InMemoryBuffer();
|
|
|
- char* tmp = new char[len];
|
|
|
- reader->lese(tmp, len);
|
|
|
- buffer->schreibe(tmp, len);
|
|
|
- delete[] tmp;
|
|
|
- other.lock();
|
|
|
- requests.add(buffer);
|
|
|
- other.unlock();
|
|
|
-}
|
|
|
-
|
|
|
-bool GameClient::isOnline() const
|
|
|
-{
|
|
|
- return online;
|
|
|
-}
|
|
|
-
|
|
|
-void GameClient::sendResponse(NetworkMessage* response)
|
|
|
-{
|
|
|
- queueCs.lock();
|
|
|
- if (response->isUseBackground())
|
|
|
- {
|
|
|
- if (backgroundQueue.getEintragAnzahl() > 20)
|
|
|
- {
|
|
|
- queueCs.unlock();
|
|
|
- while (!emptyBackgroundQueueSync.wait(1000))
|
|
|
- {
|
|
|
- backgroundQueueSync.notify();
|
|
|
- }
|
|
|
- queueCs.lock();
|
|
|
- }
|
|
|
- backgroundQueue.add(response);
|
|
|
- queueCs.unlock();
|
|
|
- backgroundQueueSync.notify();
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- if (foregroundQueue.getEintragAnzahl() > 100)
|
|
|
- {
|
|
|
- queueCs.unlock();
|
|
|
- Framework::Logging::warning()
|
|
|
- << "Game paused because nework connection to "
|
|
|
- << zPlayer->getName() << " is to slow.";
|
|
|
- ZeitMesser m;
|
|
|
- m.messungStart();
|
|
|
- while (foregroundQueue.getEintragAnzahl() > 0)
|
|
|
- {
|
|
|
- foregroundQueueSync.notify();
|
|
|
- emptyForegroundQueueSync.wait(100);
|
|
|
- }
|
|
|
- m.messungEnde();
|
|
|
- Framework::Logging::warning()
|
|
|
- << "Game resumed after " << m.getSekunden() << " seconds.";
|
|
|
- queueCs.lock();
|
|
|
- }
|
|
|
- foregroundQueue.add(response);
|
|
|
- queueCs.unlock();
|
|
|
- foregroundQueueSync.notify();
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-Player* GameClient::zEntity() const
|
|
|
-{
|
|
|
- return zPlayer;
|
|
|
-}
|
|
|
-
|
|
|
-void GameClient::sendTypes()
|
|
|
-{
|
|
|
- foreground.lock();
|
|
|
- int count = 0;
|
|
|
- for (int i = 0; i < Game::INSTANCE->getBlockTypeCount(); i++)
|
|
|
- {
|
|
|
- if (Game::INSTANCE->zBlockType(i)) count++;
|
|
|
- }
|
|
|
- client->zForegroundWriter()->schreibe((char*)&count, 4);
|
|
|
- for (int i = 0; i < Game::INSTANCE->getBlockTypeCount(); i++)
|
|
|
- {
|
|
|
- const BlockType* t = Game::INSTANCE->zBlockType(i);
|
|
|
- if (t)
|
|
|
- {
|
|
|
- t->writeTypeInfo(client->zForegroundWriter());
|
|
|
- }
|
|
|
- }
|
|
|
- count = 0;
|
|
|
- for (int i = 0; i < Game::INSTANCE->getItemTypeCount(); i++)
|
|
|
- {
|
|
|
- if (Game::INSTANCE->zItemType(i)) count++;
|
|
|
- }
|
|
|
- client->zForegroundWriter()->schreibe((char*)&count, 4);
|
|
|
- for (int i = 0; i < Game::INSTANCE->getItemTypeCount(); i++)
|
|
|
- {
|
|
|
- const ItemType* t = Game::INSTANCE->zItemType(i);
|
|
|
- if (t)
|
|
|
- {
|
|
|
- int id = t->getId();
|
|
|
- client->zForegroundWriter()->schreibe((char*)&id, 4);
|
|
|
- char len = (char)t->getName().getLength();
|
|
|
- client->zForegroundWriter()->schreibe((char*)&len, 1);
|
|
|
- client->zForegroundWriter()->schreibe(t->getName().getText(), len);
|
|
|
- short tlen = (short)t->getTooltipUIML().getLength();
|
|
|
- client->zForegroundWriter()->schreibe((char*)&tlen, 2);
|
|
|
- client->zForegroundWriter()->schreibe(
|
|
|
- t->getTooltipUIML().getText(), tlen);
|
|
|
- if (t->zModel())
|
|
|
- {
|
|
|
- t->zModel()->writeTo(client->zForegroundWriter());
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- ModelInfo("", Framework::RCArray<Framework::Text>(), false, 1.f)
|
|
|
- .writeTo(client->zForegroundWriter());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- count = 0;
|
|
|
- for (int i = 0; i < Game::INSTANCE->getEntityTypeCount(); i++)
|
|
|
- {
|
|
|
- if (Game::INSTANCE->zEntityType(i)) count++;
|
|
|
- }
|
|
|
- client->zForegroundWriter()->schreibe((char*)&count, 4);
|
|
|
- for (int i = 0; i < count; i++)
|
|
|
- {
|
|
|
- const EntityType* t = Game::INSTANCE->zEntityType(i);
|
|
|
- int id = t->getId();
|
|
|
- client->zForegroundWriter()->schreibe((char*)&id, 4);
|
|
|
- if (t->zModel())
|
|
|
- {
|
|
|
- t->zModel()->writeTo(client->zForegroundWriter());
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- ModelInfo("", Framework::RCArray<Framework::Text>(), false, 1.f)
|
|
|
- .writeTo(client->zForegroundWriter());
|
|
|
- }
|
|
|
- }
|
|
|
- foreground.unlock();
|
|
|
-}
|
|
|
-
|
|
|
Game::Game(Framework::Text name, Framework::Text worldsDir)
|
|
|
: Thread(),
|
|
|
name(name),
|
|
|
typeRegistry(new TypeRegistry()),
|
|
|
dimensions(new RCArray<Dimension>()),
|
|
|
- updates(new RCArray<WorldUpdate>()),
|
|
|
clients(new RCArray<GameClient>()),
|
|
|
questManager(new QuestManager()),
|
|
|
ticker(new TickOrganizer()),
|
|
@@ -382,7 +75,6 @@ Game::Game(Framework::Text name, Framework::Text worldsDir)
|
|
|
Game::~Game()
|
|
|
{
|
|
|
dimensions->release();
|
|
|
- updates->release();
|
|
|
clients->release();
|
|
|
generator->release();
|
|
|
loader->release();
|
|
@@ -707,10 +399,14 @@ void Game::thread()
|
|
|
Dimension* dim
|
|
|
= zDimension(player->zEntity()->getDimensionId());
|
|
|
dim->removeSubscriptions(player->zEntity());
|
|
|
- this->requestWorldUpdate(
|
|
|
- new EntityRemovedUpdate(player->zEntity()->getId(),
|
|
|
- player->zEntity()->getDimensionId(),
|
|
|
- player->zEntity()->getPosition()));
|
|
|
+ Chunk* chunk = dim->zChunk(
|
|
|
+ getChunkCenter((int)player->zEntity()->getLocation().x,
|
|
|
+ (int)player->zEntity()->getLocation().y));
|
|
|
+ if (chunk)
|
|
|
+ {
|
|
|
+ chunk->onEntityLeaves(player->zEntity(), 0);
|
|
|
+ }
|
|
|
+ dim->removeEntity(player->zEntity()->getId());
|
|
|
}
|
|
|
else
|
|
|
{
|
|
@@ -748,30 +444,6 @@ void Game::thread()
|
|
|
waitForLock.messungEnde();
|
|
|
waitTotal += waitForLock.getSekunden();
|
|
|
worldUpdates.messungStart();
|
|
|
- while (updates->hat(0))
|
|
|
- {
|
|
|
- WorldUpdate* update = updates->z(0);
|
|
|
- for (auto client : *clients)
|
|
|
- client->sendWorldUpdate(
|
|
|
- dynamic_cast<WorldUpdate*>(update->getThis()));
|
|
|
- if (!zDimension(update->getAffectedDimension()))
|
|
|
- {
|
|
|
- Dimension* dim = generator->createDimension(
|
|
|
- update->getAffectedDimension());
|
|
|
- if (dim)
|
|
|
- addDimension(dim);
|
|
|
- else
|
|
|
- {
|
|
|
- Framework::Logging::error()
|
|
|
- << "could not create dimension "
|
|
|
- << update->getAffectedDimension()
|
|
|
- << ". No Factory was provided.";
|
|
|
- }
|
|
|
- }
|
|
|
- if (zDimension(update->getAffectedDimension()))
|
|
|
- update->onUpdate(zDimension(update->getAffectedDimension()));
|
|
|
- updates->remove(0);
|
|
|
- }
|
|
|
worldUpdates.messungEnde();
|
|
|
cs.unlock();
|
|
|
clientReply.messungStart();
|
|
@@ -984,14 +656,6 @@ void Game::sendMessage(NetworkMessage* response, Entity* zTargetPlayer)
|
|
|
response->release();
|
|
|
}
|
|
|
|
|
|
-bool Game::requestWorldUpdate(WorldUpdate* update)
|
|
|
-{
|
|
|
- cs.lock();
|
|
|
- updates->add(update);
|
|
|
- cs.unlock();
|
|
|
- return 1;
|
|
|
-}
|
|
|
-
|
|
|
bool Game::checkPlayer(Framework::Text name, Framework::Text secret)
|
|
|
{
|
|
|
if (playerRegister->checkSecret(name, secret))
|
|
@@ -1096,7 +760,18 @@ GameClient* Game::addPlayer(FCKlient* client, Framework::Text name)
|
|
|
player->setPosition(
|
|
|
{player->getPosition().x, player->getPosition().y, (float)h + 2.f});
|
|
|
}
|
|
|
- requestWorldUpdate(new AddEntityUpdate(player, player->getDimensionId()));
|
|
|
+ Dimension* zDim = zDimension(player->getDimensionId());
|
|
|
+ if (zDim)
|
|
|
+ {
|
|
|
+ zDim->addEntity(player);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Framework::Logging::error()
|
|
|
+ << "could not add player to dimension "
|
|
|
+ << (int)player->getDimensionId() << ". Dimension not loaded.";
|
|
|
+ player->release();
|
|
|
+ }
|
|
|
chat->addObserver(gameClient->zEntity()->getId());
|
|
|
chat->broadcastMessage(name + " joined the game.", Chat::CHANNEL_INFO);
|
|
|
cs.unlock();
|
|
@@ -1158,7 +833,19 @@ void Game::spawnItem(
|
|
|
location, dimensionId, Game::INSTANCE->getNextEntityId());
|
|
|
itemEntity->unsaveAddItem(stack, NO_DIRECTION, 0);
|
|
|
stack->release();
|
|
|
- requestWorldUpdate(new AddEntityUpdate(itemEntity, dimensionId));
|
|
|
+ Dimension* dim = zDimension(dimensionId);
|
|
|
+ if (dim)
|
|
|
+ {
|
|
|
+ dim->addEntity(itemEntity);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Framework::Logging::error()
|
|
|
+ << "could not spawn item entity in dimension " << dimensionId
|
|
|
+ << ". Dimension not loaded.";
|
|
|
+ itemEntity->release();
|
|
|
+ return;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
Framework::Either<Block*, int> Game::zBlockAt(
|