Simplified registration of game actions and avoid duplicate code.

This commit is contained in:
ZehM4tt 2017-07-14 07:57:49 +02:00 committed by Michał Janiszewski
parent 149a854c51
commit f20a6863cd
4 changed files with 186 additions and 131 deletions

View File

@ -16,119 +16,83 @@
#pragma once
#include <functional>
#include "../common.h"
#include "../core/IStream.hpp"
extern "C"
{
#include "../game.h"
#include "../world/map.h"
}
/**
* Common error codes for game actions.
*/
enum class GA_ERROR : uint16
{
OK,
INVALID_PARAMETERS,
DISALLOWED,
GAME_PAUSED,
INSUFFICIENT_FUNDS,
NOT_IN_EDITOR_MODE,
NOT_OWNED,
TOO_LOW,
TOO_HIGH,
NO_CLEARANCE,
ITEM_ALREADY_PLACED,
NO_FREE_ELEMENTS,
UNKNOWN = UINT16_MAX,
};
namespace GA_FLAGS
{
constexpr uint16 ALLOW_WHILE_PAUSED = 1 << 0;
constexpr uint16 CLIENT_ONLY = 1 << 1;
constexpr uint16 EDITOR_ONLY = 1 << 2;
}
/**
* Represents the result of a game action query or execution.
*/
struct GameActionResult
{
GA_ERROR Error = GA_ERROR::OK;
rct_string_id ErrorTitle = (rct_string_id)-1;
rct_string_id ErrorMessage = (rct_string_id)-1;
uint8 ErrorMessageArgs[8] = { 0 };
rct_xyz32 Position = { 0 };
money32 Cost = 0;
uint16 ExpenditureType = 0;
void * Tag = nullptr;
GameActionResult();
GameActionResult(GA_ERROR error, rct_string_id message);
};
/**
* Represents an action that changes the state of the game. Can be serialised and
* deserialised into a stream.
*/
interface IGameAction
{
virtual ~IGameAction() = default;
/**
* Gets the GA_FLAGS flags that are enabled for this game action.
*/
virtual uint16 GetFlags() const abstract;
virtual uint32 GetType() const abstract;
/**
* Reads the game action directly from the given stream. Used for
* sending across the network in multiplayer.
*/
virtual void Deserialise(IStream * stream) abstract;
/**
* Writes the game action directly to the given stream. Used for
* sending across the network in multiplayer.
*/
virtual void Serialise(IStream * stream) const abstract;
/**
* Query the result of the game action without changing the game state.
*/
virtual GameActionResult Query(uint32 flags = 0) const abstract;
/**
* Apply the game action and change the game state.
*/
virtual GameActionResult Execute(uint32 flags = 0) const abstract;
};
#include "IGameAction.h"
typedef IGameAction *(*GameActionFactory)();
using GameActionCallback = std::function<void(GameActionResult)>;
template<uint32 _TYPE, uint16 _FLAGS>
struct GameAction : public IGameAction
{
public:
constexpr static uint32 Type = _TYPE;
constexpr static uint16 Flags = _FLAGS;
private:
uint32 _playerId;
public:
GameAction() : _playerId(0)
{
}
/**
* Gets the GA_FLAGS flags that are enabled for this game action.
*/
virtual uint16 GetFlags() const override
{
return Flags;
}
virtual uint32 GetType() const override
{
return Type;
}
/**
* Reads the game action directly from the given stream. Used for
* sending across the network in multiplayer.
*/
virtual void Deserialise(IStream * stream)
{
stream->Read(&_playerId);
}
/**
* Writes the game action directly to the given stream. Used for
* sending across the network in multiplayer.
*/
virtual void Serialise(IStream * stream) const
{
stream->Write(&_playerId);
}
/**
* Query the result of the game action without changing the game state.
*/
virtual GameActionResult Query(uint32 flags = 0) const abstract;
/**
* Apply the game action and change the game state.
*/
virtual GameActionResult Execute(uint32 flags = 0) const abstract;
};
namespace GameActions
{
GameActionFactory Register(uint32 id, GameActionFactory action);
IGameAction * Create(uint32 id);
GameActionResult Query(const IGameAction * action, uint32 flags = 0);
GameActionResult Execute(const IGameAction * action, uint32 flags = 0, GameActionCallback callback = nullptr);
GameActionFactory Register(uint32 id, GameActionFactory action);
IGameAction * Create(uint32 id);
GameActionResult Query(const IGameAction * action, uint32 flags = 0);
GameActionResult Execute(const IGameAction * action, uint32 flags = 0, GameActionCallback callback = nullptr);
template<typename T>
static GameActionFactory Register(uint32 id)
template<typename T>
static GameActionFactory Register()
{
GameActionFactory factory = []() -> IGameAction *
{
GameActionFactory factory = []() -> IGameAction *
{
return new T();
};
Register(id, factory);
return factory;
}
return new T();
};
Register(T::Type, factory);
return factory;
}
}

View File

@ -0,0 +1,111 @@
#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#pragma once
#include <functional>
#include "../common.h"
#include "../core/IStream.hpp"
extern "C"
{
#include "../game.h"
#include "../world/map.h"
}
/**
* Common error codes for game actions.
*/
enum class GA_ERROR : uint16
{
OK,
INVALID_PARAMETERS,
DISALLOWED,
GAME_PAUSED,
INSUFFICIENT_FUNDS,
NOT_IN_EDITOR_MODE,
NOT_OWNED,
TOO_LOW,
TOO_HIGH,
NO_CLEARANCE,
ITEM_ALREADY_PLACED,
NO_FREE_ELEMENTS,
UNKNOWN = UINT16_MAX,
};
namespace GA_FLAGS
{
constexpr uint16 ALLOW_WHILE_PAUSED = 1 << 0;
constexpr uint16 CLIENT_ONLY = 1 << 1;
constexpr uint16 EDITOR_ONLY = 1 << 2;
}
/**
* Represents the result of a game action query or execution.
*/
struct GameActionResult
{
GA_ERROR Error = GA_ERROR::OK;
rct_string_id ErrorTitle = (rct_string_id)-1;
rct_string_id ErrorMessage = (rct_string_id)-1;
uint8 ErrorMessageArgs[8] = { 0 };
rct_xyz32 Position = { 0 };
money32 Cost = 0;
uint16 ExpenditureType = 0;
void * Tag = nullptr;
GameActionResult();
GameActionResult(GA_ERROR error, rct_string_id message);
};
/**
* Represents an action that changes the state of the game. Can be serialised and
* deserialised into a stream.
*/
struct IGameAction
{
public:
/**
* Gets the GA_FLAGS flags that are enabled for this game action.
*/
virtual uint16 GetFlags() const abstract;
virtual uint32 GetType() const abstract;
/**
* Reads the game action directly from the given stream. Used for
* sending across the network in multiplayer.
*/
virtual void Deserialise(IStream * stream) abstract;
/**
* Writes the game action directly to the given stream. Used for
* sending across the network in multiplayer.
*/
virtual void Serialise(IStream * stream) const abstract;
/**
* Query the result of the game action without changing the game state.
*/
virtual GameActionResult Query(uint32 flags = 0) const abstract;
/**
* Apply the game action and change the game state.
*/
virtual GameActionResult Execute(uint32 flags = 0) const abstract;
};

View File

@ -33,7 +33,7 @@ struct PlaceParkEntranceGameActionResult : public GameActionResult {
}
};
class PlaceParkEntranceAction : public IGameAction
struct PlaceParkEntranceAction : public GameAction<GAME_COMMAND_PLACE_PARK_ENTRANCE, GA_FLAGS::EDITOR_ONLY>
{
public:
sint16 x;
@ -41,16 +41,6 @@ public:
sint16 z;
uint8 direction;
uint16 GetFlags() const override
{
return GA_FLAGS::EDITOR_ONLY;
}
uint32 GetType() const override
{
return GAME_COMMAND_PLACE_PARK_ENTRANCE;
}
void Deserialise(IStream * stream) override
{
x = stream->ReadValue<sint16>();
@ -223,7 +213,7 @@ public:
}
};
static auto Factory UNUSED_ATTR = GameActions::Register<PlaceParkEntranceAction>(GAME_COMMAND_PLACE_PARK_ENTRANCE);
static auto Factory UNUSED_ATTR = GameActions::Register<PlaceParkEntranceAction>();
extern "C"
{

View File

@ -25,21 +25,11 @@ extern "C"
#include "../world/park.h"
}
class SetParkEntranceFeeAction : public IGameAction
struct SetParkEntranceFeeAction : public GameAction<GAME_COMMAND_SET_PARK_ENTRANCE_FEE, GA_FLAGS::ALLOW_WHILE_PAUSED>
{
public:
money16 Fee;
uint16 GetFlags() const override
{
return GA_FLAGS::ALLOW_WHILE_PAUSED;
}
uint32 GetType() const override
{
return GAME_COMMAND_SET_PARK_ENTRANCE_FEE;
}
void Deserialise(IStream * stream) override
{
Fee = stream->ReadValue<money16>();
@ -73,7 +63,7 @@ public:
}
};
static auto Factory UNUSED_ATTR = GameActions::Register<SetParkEntranceFeeAction>(GAME_COMMAND_SET_PARK_ENTRANCE_FEE);
static auto Factory UNUSED_ATTR = GameActions::Register<SetParkEntranceFeeAction>();
extern "C"
{