Merge pull request #96 from teamfisk/WeaponSystem
Network improvements and base weapon work
This commit is contained in:
+1
-1
Submodule assets updated: 77bab8c0f5...c56f6380ab
+1
-1
Submodule deps updated: bf83f099ba...ed45883a44
@@ -13,8 +13,8 @@
|
||||
class CollisionSystem : public PureSystem
|
||||
{
|
||||
public:
|
||||
CollisionSystem(World* world, EventBroker* eventBroker, Octree<EntityAABB>* octree)
|
||||
: System(world, eventBroker)
|
||||
CollisionSystem(SystemParams params, Octree<EntityAABB>* octree)
|
||||
: System(params)
|
||||
, PureSystem("Collidable")
|
||||
, m_Octree(octree)
|
||||
{ }
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
class FillFrustumOctreeSystem : public ImpureSystem, public PureSystem
|
||||
{
|
||||
public:
|
||||
FillFrustumOctreeSystem(World* world, EventBroker* eventBroker, Octree<EntityAABB>* octree)
|
||||
: System(world, eventBroker)
|
||||
FillFrustumOctreeSystem(SystemParams params, Octree<EntityAABB>* octree)
|
||||
: System(params)
|
||||
, PureSystem("Model")
|
||||
, m_Octree(octree)
|
||||
{ }
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
class FillOctreeSystem : public ImpureSystem, public PureSystem
|
||||
{
|
||||
public:
|
||||
FillOctreeSystem(World* world, EventBroker* eventBroker, Octree<EntityAABB>* octree, const std::string& fillComponentType)
|
||||
: System(world, eventBroker)
|
||||
FillOctreeSystem(SystemParams params, Octree<EntityAABB>* octree, const std::string& fillComponentType)
|
||||
: System(params)
|
||||
, PureSystem(fillComponentType)
|
||||
, m_Octree(octree)
|
||||
{ }
|
||||
|
||||
@@ -15,8 +15,8 @@ class AABB;
|
||||
class TriggerSystem : public PureSystem
|
||||
{
|
||||
public:
|
||||
TriggerSystem(World* world, EventBroker* eventBroker, Octree<EntityAABB>* octree)
|
||||
: System(world, eventBroker)
|
||||
TriggerSystem(SystemParams params, Octree<EntityAABB>* octree)
|
||||
: System(params)
|
||||
, PureSystem("Trigger")
|
||||
, m_Octree(octree)
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@ struct ComponentInfo
|
||||
unsigned int Allocation = 0;
|
||||
std::map<std::string, std::string> FieldAnnotations;
|
||||
std::map<std::string, std::map<std::string, EnumType>> FieldEnumDefinitions;
|
||||
bool NetworkReplicated = true;
|
||||
};
|
||||
|
||||
struct Field_t
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef ComponentWrapper_h__
|
||||
#define ComponentWrapper_h__
|
||||
|
||||
#include <boost/shared_array.hpp>
|
||||
#include "../Common.h"
|
||||
#include "Entity.h"
|
||||
#include "ComponentInfo.h"
|
||||
@@ -81,6 +82,18 @@ struct ComponentWrapper
|
||||
SubscriptProxy operator[](std::string propertyName) { return SubscriptProxy(this, propertyName); }
|
||||
};
|
||||
|
||||
// A component wrapper that "owns" its data through a shared pointer
|
||||
struct SharedComponentWrapper : ComponentWrapper
|
||||
{
|
||||
SharedComponentWrapper(const ComponentInfo& componentInfo, boost::shared_array<char> data)
|
||||
: ComponentWrapper(componentInfo, data.get())
|
||||
, m_DataReference(data)
|
||||
{ }
|
||||
|
||||
private:
|
||||
boost::shared_array<char> m_DataReference;
|
||||
};
|
||||
|
||||
// TODO: Move this to Tests once entity importing is finished
|
||||
class ComponentWrapperFactory
|
||||
{
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <xercesc/framework/psvi/XSElementDeclaration.hpp>
|
||||
#include <xercesc/framework/psvi/XSComplexTypeDefinition.hpp>
|
||||
#include <xercesc/framework/psvi/XSAttributeUse.hpp>
|
||||
#include <xercesc/framework/psvi/XSAttributeDeclaration.hpp>
|
||||
#include <xercesc/framework/psvi/XSParticle.hpp>
|
||||
#include <xercesc/framework/psvi/XSModelGroup.hpp>
|
||||
#include <xercesc/framework/psvi/XSModelGroupDefinition.hpp>
|
||||
|
||||
@@ -30,7 +30,7 @@ struct EntityWrapper
|
||||
EntityWrapper FirstChildByName(const std::string& name);
|
||||
EntityWrapper FirstParentWithComponent(const std::string& componentType);
|
||||
bool IsChildOf(EntityWrapper potentialParent);
|
||||
bool Valid();
|
||||
bool Valid() const;
|
||||
|
||||
ComponentWrapper operator[](const char* componentName);
|
||||
bool operator==(const EntityWrapper& e) const;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <tuple>
|
||||
#include <set>
|
||||
|
||||
#include "../Common.h"
|
||||
#include "Event.h"
|
||||
@@ -107,7 +108,7 @@ private:
|
||||
typedef std::unordered_map<ContextTypeName_t, EventRelays_t> ContextRelays_t;
|
||||
ContextRelays_t m_ContextRelays;
|
||||
std::vector<BaseEventRelay*> m_RelaysToSubscribe;
|
||||
std::vector<std::tuple<EventID, ContextTypeName_t, EventTypeName_t>> m_RelaysToUnsubscribe;
|
||||
std::unordered_map<BaseEventRelay*, std::tuple<EventID, ContextTypeName_t, EventTypeName_t>> m_RelaysToUnsubscribe;
|
||||
|
||||
typedef std::list<std::pair<EventTypeName_t, std::shared_ptr<Event>>> EventQueue_t;
|
||||
std::shared_ptr<EventQueue_t> m_EventQueueRead;
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
#include "../Common.h"
|
||||
#include "AABB.h"
|
||||
#include "Frustum.h"
|
||||
|
||||
//Fwd declarations.
|
||||
class Ray;
|
||||
#include "Ray.h"
|
||||
|
||||
namespace OctSpace
|
||||
{
|
||||
|
||||
@@ -5,21 +5,55 @@
|
||||
#include "World.h"
|
||||
#include "EntityWrapper.h"
|
||||
#include "ComponentWrapper.h"
|
||||
#include "EPlayerSpawned.h"
|
||||
|
||||
struct SystemParams
|
||||
{
|
||||
SystemParams(::World* World, ::EventBroker* EventBroker, bool IsClient, bool IsServer)
|
||||
: World(World)
|
||||
, EventBroker(EventBroker)
|
||||
, IsClient(IsClient)
|
||||
, IsServer(IsServer)
|
||||
{ }
|
||||
|
||||
::World* World;
|
||||
::EventBroker* EventBroker;
|
||||
bool IsClient = false;
|
||||
bool IsServer = false;
|
||||
};
|
||||
|
||||
class System
|
||||
{
|
||||
friend class SystemPipeline;
|
||||
|
||||
protected:
|
||||
System(World* world, EventBroker) { }
|
||||
System(World* world, EventBroker* eventBroker)
|
||||
: m_World(world)
|
||||
, m_EventBroker(eventBroker)
|
||||
{ }
|
||||
System(SystemParams params)
|
||||
: m_World(params.World)
|
||||
, m_EventBroker(params.EventBroker)
|
||||
, IsClient(params.IsClient)
|
||||
, IsServer(params.IsServer)
|
||||
{
|
||||
if (IsClient) {
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &System::setLocalPlayer);
|
||||
}
|
||||
}
|
||||
virtual ~System() = default;
|
||||
|
||||
World* m_World;
|
||||
EventBroker* m_EventBroker;
|
||||
bool IsClient = false;
|
||||
bool IsServer = false;
|
||||
EntityWrapper LocalPlayer = EntityWrapper::Invalid;
|
||||
|
||||
private:
|
||||
EventRelay<System, Events::PlayerSpawned> m_EPlayerSpawned;
|
||||
virtual bool setLocalPlayer(Events::PlayerSpawned& e)
|
||||
{
|
||||
if (e.PlayerID == -1) {
|
||||
LocalPlayer = e.Player;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class PureSystem : public virtual System
|
||||
@@ -34,7 +68,7 @@ protected:
|
||||
|
||||
const std::string m_ComponentType;
|
||||
|
||||
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cComponent, double dt) = 0;
|
||||
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cPlayer, double dt) = 0;
|
||||
};
|
||||
|
||||
class ImpureSystem : public virtual System
|
||||
|
||||
@@ -10,9 +10,11 @@
|
||||
class SystemPipeline
|
||||
{
|
||||
public:
|
||||
SystemPipeline(World* world, EventBroker* eventBroker)
|
||||
SystemPipeline(World* world, EventBroker* eventBroker, bool isClient, bool isServer)
|
||||
: m_World(world)
|
||||
, m_EventBroker(eventBroker)
|
||||
, m_IsClient(isClient)
|
||||
, m_IsServer(isServer)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPause, &SystemPipeline::OnPause);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EResume, &SystemPipeline::OnResume);
|
||||
@@ -35,7 +37,7 @@ public:
|
||||
m_OrderedSystemGroups.resize(updateOrderLevel + 1);
|
||||
}
|
||||
UnorderedSystems& group = m_OrderedSystemGroups[updateOrderLevel];
|
||||
System* system = new T(m_World, m_EventBroker, args...);
|
||||
System* system = new T(SystemParams(m_World, m_EventBroker, m_IsClient, m_IsServer), args...);
|
||||
group.Systems[typeid(T).name()] = system;
|
||||
|
||||
PureSystem* pureSystem = dynamic_cast<PureSystem*>(system);
|
||||
@@ -59,6 +61,9 @@ public:
|
||||
dt = 0.0;
|
||||
}
|
||||
|
||||
// Process utility events for the System base class
|
||||
m_EventBroker->Process<System>();
|
||||
|
||||
for (UnorderedSystems& group : m_OrderedSystemGroups) {
|
||||
// Process events
|
||||
for (auto& pair : group.Systems) {
|
||||
@@ -88,6 +93,8 @@ public:
|
||||
private:
|
||||
World* m_World;
|
||||
EventBroker* m_EventBroker;
|
||||
bool m_IsClient = false;
|
||||
bool m_IsServer = false;
|
||||
bool m_Paused = false;
|
||||
|
||||
struct UnorderedSystems
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
class UniformScaleSystem : public PureSystem
|
||||
{
|
||||
public:
|
||||
UniformScaleSystem(World* world, EventBroker* eventBroker);
|
||||
UniformScaleSystem(SystemParams params);
|
||||
|
||||
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cUniformScale, double dt) override;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
class EditorRenderSystem : public ImpureSystem
|
||||
{
|
||||
public:
|
||||
EditorRenderSystem(World* world, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame);
|
||||
EditorRenderSystem(SystemParams params, IRenderer* renderer, RenderFrame* renderFrame);
|
||||
|
||||
virtual void Update(double dt) override;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
class EditorSystem : public ImpureSystem
|
||||
{
|
||||
public:
|
||||
EditorSystem(World* world, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame);
|
||||
EditorSystem(SystemParams params, IRenderer* renderer, RenderFrame* renderFrame);
|
||||
~EditorSystem();
|
||||
|
||||
void Update(double dt);
|
||||
|
||||
@@ -25,7 +25,7 @@ struct WidgetDelta : Event
|
||||
class EditorWidgetSystem : public ImpureSystem, PureSystem
|
||||
{
|
||||
public:
|
||||
EditorWidgetSystem(World* world, EventBroker* eventBroker, IRenderer* renderer);
|
||||
EditorWidgetSystem(SystemParams params, IRenderer* renderer);
|
||||
|
||||
virtual void Update(double dt) override;
|
||||
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cEditorWidget, double dt) override;
|
||||
|
||||
@@ -20,16 +20,22 @@
|
||||
#include "Input/EInputCommand.h"
|
||||
#include "Core/EPlayerDamage.h"
|
||||
#include "Network/EInterpolate.h"
|
||||
#include "Network/SnapshotFilter.h"
|
||||
#include "Core/EPlayerSpawned.h"
|
||||
|
||||
class Client : public Network
|
||||
{
|
||||
public:
|
||||
Client(ConfigFile* config);
|
||||
Client(World* world, EventBroker* eventBroker);
|
||||
Client(World* world, EventBroker* eventBroker, std::unique_ptr<SnapshotFilter> snapshotFilter);
|
||||
~Client();
|
||||
void Start(World* world, EventBroker* eventBroker) override;
|
||||
|
||||
void Connect(std::string address, int port);
|
||||
void Update() override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<SnapshotFilter> m_SnapshotFilter = nullptr;
|
||||
|
||||
// Assio UDP logic
|
||||
boost::asio::ip::udp::endpoint m_ReceiverEndpoint;
|
||||
boost::asio::io_service m_IOService;
|
||||
@@ -45,10 +51,8 @@ private:
|
||||
PacketID m_SendPacketID = 0;
|
||||
|
||||
// Game logic
|
||||
World* m_World;
|
||||
std::string m_PlayerName;
|
||||
PlayerID m_PlayerID = -1;
|
||||
EntityID m_ServerEntityID = std::numeric_limits<EntityID>::max();
|
||||
bool m_IsConnected = false;
|
||||
EntityWrapper m_LocalPlayer = EntityWrapper::Invalid;
|
||||
// Server Client Lookup map
|
||||
@@ -74,7 +78,9 @@ private:
|
||||
void connect();
|
||||
void disconnect();
|
||||
void parseMessageType(Packet& packet);
|
||||
void updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType);
|
||||
void updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID);
|
||||
SharedComponentWrapper createSharedComponent(Packet& packet, EntityID entityID, const ComponentInfo& componentInfo);
|
||||
void ignoreFields(Packet& packet, const ComponentInfo& componentInfo);
|
||||
void parseConnect(Packet& packet);
|
||||
void parsePlayerConnected(Packet& packet);
|
||||
void parsePing();
|
||||
@@ -99,7 +105,6 @@ private:
|
||||
void deleteFromServerClientMaps(EntityID serverEntityID, EntityID clientEntityID);
|
||||
|
||||
// Events
|
||||
EventBroker* m_EventBroker;
|
||||
EventRelay<Client, Events::InputCommand> m_EInputCommand;
|
||||
bool OnInputCommand(const Events::InputCommand& e);
|
||||
EventRelay<Client, Events::PlayerDamage> m_EPlayerDamage;
|
||||
|
||||
@@ -11,8 +11,13 @@ namespace Events
|
||||
|
||||
struct Interpolate : Event
|
||||
{
|
||||
EntityID Entity;
|
||||
boost::shared_array<char> DataArray;
|
||||
Interpolate(EntityWrapper Entity, SharedComponentWrapper Component)
|
||||
: Entity(Entity)
|
||||
, Component(Component)
|
||||
{ }
|
||||
|
||||
EntityWrapper Entity;
|
||||
SharedComponentWrapper Component;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -19,10 +19,15 @@ typedef unsigned int PacketID;
|
||||
class Network
|
||||
{
|
||||
public:
|
||||
Network(World* world, EventBroker* eventBroker);
|
||||
virtual ~Network() { };
|
||||
virtual void Start(World* m_world, EventBroker *eventBroker) = 0;
|
||||
|
||||
virtual void Update() = 0;
|
||||
|
||||
protected:
|
||||
World* m_World;
|
||||
EventBroker* m_EventBroker;
|
||||
|
||||
// For Debug
|
||||
bool isReadingData = false;
|
||||
NetworkData m_NetworkData;
|
||||
@@ -32,7 +37,6 @@ protected:
|
||||
double m_TimeoutMs;
|
||||
void saveToFile();
|
||||
void updateNetworkData();
|
||||
void initialize();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -22,15 +22,17 @@
|
||||
class Server : public Network
|
||||
{
|
||||
public:
|
||||
Server();
|
||||
Server(World* world, EventBroker* eventBroker, int port);
|
||||
~Server();
|
||||
void Start(World* m_world, EventBroker *eventBroker) override;
|
||||
|
||||
void Update() override;
|
||||
|
||||
private:
|
||||
int m_Port = 27666;
|
||||
// UDP logic
|
||||
boost::asio::ip::udp::endpoint m_ReceiverEndpoint;
|
||||
boost::asio::io_service m_IOService;
|
||||
boost::asio::ip::udp::socket m_Socket;
|
||||
std::unique_ptr<boost::asio::ip::udp::socket> m_Socket;
|
||||
|
||||
// Sending messages to client logic
|
||||
std::map<PlayerID, PlayerDefinition> m_ConnectedPlayers;
|
||||
@@ -46,13 +48,10 @@ private:
|
||||
float snapshotInterval;
|
||||
int checkTimeOutInterval = 100;
|
||||
int m_NextPlayerID = 0;
|
||||
std::vector<Events::InputCommand> m_InputCommandsToBroadcast;
|
||||
|
||||
//Timers
|
||||
std::clock_t m_StartPingTime;
|
||||
|
||||
// Game logic
|
||||
World* m_World;
|
||||
EventBroker* m_EventBroker;
|
||||
|
||||
// Packet loss logic
|
||||
PacketID m_PacketID = 0;
|
||||
@@ -66,6 +65,7 @@ private:
|
||||
void broadcast(Packet& packet);
|
||||
void sendSnapshot();
|
||||
void addChildrenToPacket(Packet& packet, EntityID entityID);
|
||||
void addInputCommandsToPacket(Packet& packet);
|
||||
void sendPing();
|
||||
void checkForTimeOuts();
|
||||
void disconnect(PlayerID playerID);
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef SnapshotFilter_h__
|
||||
#define SnapshotFilter_h__
|
||||
|
||||
#include "../Core/EntityWrapper.h"
|
||||
#include "../Core/ComponentWrapper.h"
|
||||
|
||||
class SnapshotFilter
|
||||
{
|
||||
public:
|
||||
// Filters an incoming snapshot.
|
||||
// Modify the component and return true if the component snapshot should be applied.
|
||||
// Otherwise return false and it will be ignored.
|
||||
virtual bool FilterComponent(EntityWrapper entity, SharedComponentWrapper& component)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -14,8 +14,8 @@
|
||||
class AnimationSystem : public PureSystem
|
||||
{
|
||||
public:
|
||||
AnimationSystem(World* world, EventBroker* eventBroker)
|
||||
: System(world, eventBroker)
|
||||
AnimationSystem(SystemParams params)
|
||||
: System(params)
|
||||
, PureSystem("Animation")
|
||||
{
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
class BoneAttachmentSystem : public PureSystem
|
||||
{
|
||||
public:
|
||||
BoneAttachmentSystem(World* world, EventBroker* eventBroker)
|
||||
: System(world, eventBroker)
|
||||
BoneAttachmentSystem(SystemParams params)
|
||||
: System(params)
|
||||
, PureSystem("BoneAttachment")
|
||||
{
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@ public:
|
||||
virtual void SetFullscreen(bool fullscreen) { m_Fullscreen = fullscreen; }
|
||||
bool VSYNC() const { return m_VSYNC; }
|
||||
virtual void SetVSYNC(bool vsync) { m_VSYNC = vsync; }
|
||||
std::string WindowTitle() const { return m_WindowTitle; }
|
||||
virtual void SetWindowTitle(const std::string& title) { glfwSetWindowTitle(m_Window, title.c_str()); m_WindowTitle = title; }
|
||||
//Returns screen size excluding window border and header
|
||||
Rectangle GetViewportSize() const { return m_ViewportSize; }
|
||||
virtual void Initialize() = 0;
|
||||
@@ -47,6 +49,7 @@ protected:
|
||||
int m_GLVersion[2];
|
||||
std::string m_GLVendor;
|
||||
GLFWwindow* m_Window = nullptr;
|
||||
std::string m_WindowTitle;
|
||||
};
|
||||
|
||||
#endif // Renderer_h__
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
class RenderSystem : public ImpureSystem
|
||||
{
|
||||
public:
|
||||
RenderSystem(World* world, EventBroker* eventBrokerer, const IRenderer* renderer, RenderFrame* renderFrame, Octree<EntityAABB>* frustumCullOctree);
|
||||
RenderSystem(SystemParams params, const IRenderer* renderer, RenderFrame* renderFrame, Octree<EntityAABB>* frustumCullOctree);
|
||||
~RenderSystem();
|
||||
|
||||
virtual void Update(double dt) override;
|
||||
@@ -31,7 +31,6 @@ private:
|
||||
const IRenderer* m_Renderer;
|
||||
RenderFrame* m_RenderFrame;
|
||||
Camera* m_Camera;
|
||||
World* m_World;
|
||||
EntityWrapper m_CurrentCamera = EntityWrapper::Invalid;
|
||||
EntityWrapper m_LocalPlayer = EntityWrapper::Invalid;
|
||||
Octree<EntityAABB>* m_Octree;
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
#include "Common.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
class ExplosionEffectSystem : public PureSystem
|
||||
{
|
||||
public:
|
||||
ExplosionEffectSystem(World* world, EventBroker* eventBroker)
|
||||
: System(world, eventBroker)
|
||||
, PureSystem("ExplosionEffect")
|
||||
{ }
|
||||
|
||||
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override
|
||||
{
|
||||
|
||||
if ((double)component["TimeSinceDeath"] > (double)component["ExplosionDuration"]) {
|
||||
(double)component["TimeSinceDeath"] = 0.f;
|
||||
}
|
||||
(double&)component["TimeSinceDeath"] += dt;
|
||||
|
||||
//if ((bool)Component["Gravity"] == true) {
|
||||
// (bool)Component["ExponentialAccelaration"] = false;
|
||||
//}
|
||||
}
|
||||
};
|
||||
+12
-17
@@ -1,6 +1,8 @@
|
||||
#ifndef Game_h__
|
||||
#define Game_h__
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include "Core/ResourceManager.h"
|
||||
#include "Core/ConfigFile.h"
|
||||
#include "Core/EventBroker.h"
|
||||
@@ -14,7 +16,7 @@
|
||||
#include "Core/EKeyDown.h"
|
||||
#include "Core/EntityFilePreprocessor.h"
|
||||
#include "Core/SystemPipeline.h"
|
||||
#include "ExplosionEffectSystem.h"
|
||||
#include "Systems/ExplosionEffectSystem.h"
|
||||
#include "Editor/EditorSystem.h"
|
||||
#include "Core/EntityFile.h"
|
||||
#include "Rendering/RenderSystem.h"
|
||||
@@ -43,7 +45,9 @@ public:
|
||||
void Tick();
|
||||
|
||||
private:
|
||||
double m_LastTime;
|
||||
std::string m_NetworkAddress;
|
||||
int m_NetworkPort = 0;
|
||||
|
||||
ConfigFile* m_Config = nullptr;
|
||||
EventBroker* m_EventBroker;
|
||||
IRenderer* m_Renderer;
|
||||
@@ -56,24 +60,15 @@ private:
|
||||
Octree<EntityAABB>* m_OctreeFrustrumCulling;
|
||||
SystemPipeline* m_SystemPipeline;
|
||||
RenderFrame* m_RenderFrame;
|
||||
// Network variables
|
||||
boost::thread m_NetworkThread;
|
||||
|
||||
// Network methods
|
||||
void networkFunction();
|
||||
Network* m_ClientOrServer;
|
||||
bool m_IsClientOrServer = false;
|
||||
|
||||
// Sound
|
||||
Client* m_NetworkClient = nullptr;
|
||||
Server* m_NetworkServer = nullptr;
|
||||
SoundManager* m_SoundManager;
|
||||
double m_LastTime;
|
||||
|
||||
//EventRelay<Game, Events::InputCommand> m_EInputCommand;
|
||||
//bool debugOnInputCommand(const Events::InputCommand& e);
|
||||
|
||||
void debugInitialize();
|
||||
void debugTick(double dt);
|
||||
EventRelay<Client, Events::KeyDown> m_EKeyDown;
|
||||
bool m_IsClient = false;
|
||||
bool m_IsServer = false;
|
||||
|
||||
int parseArgs(int argc, char* argv[]);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef MultiplayerSnapshotFilter_h__
|
||||
#define MultiplayerSnapshotFilter_h__
|
||||
|
||||
#include "Core/EventBroker.h"
|
||||
#include "Core/EPlayerSpawned.h"
|
||||
#include "Network/SnapshotFilter.h"
|
||||
#include "Network/EInterpolate.h"
|
||||
|
||||
class MultiplayerSnapshotFilter : public SnapshotFilter
|
||||
{
|
||||
public:
|
||||
MultiplayerSnapshotFilter(EventBroker* eventBroker);
|
||||
|
||||
virtual bool FilterComponent(EntityWrapper entity, SharedComponentWrapper& component) override;
|
||||
|
||||
private:
|
||||
EventBroker* m_EventBroker;
|
||||
|
||||
EntityWrapper m_LocalPlayer = EntityWrapper::Invalid;
|
||||
|
||||
EventRelay<MultiplayerSnapshotFilter, Events::PlayerSpawned> m_EPlayerSpawned;
|
||||
bool OnPlayerSpawned(Events::PlayerSpawned ePlayerSpawned);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -17,7 +17,7 @@ class CapturePointSystem : public PureSystem
|
||||
{
|
||||
public:
|
||||
//WARNING: on new map, destroy all info in the vectors, as well as reset all variables (just make new?)
|
||||
CapturePointSystem(World* world, EventBroker* eventBroker);
|
||||
CapturePointSystem(SystemParams params);
|
||||
|
||||
//updatecomponent
|
||||
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& capturePoint, double dt) override;
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef ExplosionEffectSystem_h__
|
||||
#define ExplosionEffectSystem_h__
|
||||
|
||||
#include "Common.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
class ExplosionEffectSystem : public PureSystem
|
||||
{
|
||||
public:
|
||||
ExplosionEffectSystem(SystemParams params)
|
||||
: System(params)
|
||||
, PureSystem("ExplosionEffect")
|
||||
{ }
|
||||
|
||||
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -17,7 +17,7 @@
|
||||
class HealthSystem : public PureSystem
|
||||
{
|
||||
public:
|
||||
HealthSystem(World* world, EventBroker* eventBroker);
|
||||
HealthSystem(SystemParams params);
|
||||
|
||||
//updatecomponent
|
||||
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override;
|
||||
|
||||
@@ -16,38 +16,47 @@
|
||||
|
||||
#include "Network/EInterpolate.h"
|
||||
|
||||
class InterpolationSystem : public PureSystem
|
||||
class InterpolationSystem : public ImpureSystem
|
||||
{
|
||||
struct Transform
|
||||
{
|
||||
glm::vec3 Position;
|
||||
glm::vec3 Scale;
|
||||
glm::quat Orientation;
|
||||
float interpolationTime;
|
||||
};
|
||||
public:
|
||||
InterpolationSystem(World* world, EventBroker* eventBroker);
|
||||
InterpolationSystem(SystemParams params);
|
||||
~InterpolationSystem() { }
|
||||
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& transform, double dt) override;
|
||||
private:
|
||||
std::unordered_map<EntityID, Transform> m_NextTransform;
|
||||
std::unordered_map<EntityID, Transform> m_LastReceivedTransform;
|
||||
EntityWrapper m_LocalPlayer = EntityWrapper::Invalid;
|
||||
|
||||
//glm::vec3 vectorInterpolation(glm::vec3 prev, glm::vec3 next, double currentTime);
|
||||
virtual void Update(double dt) override;
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
struct Interpolation
|
||||
{
|
||||
Interpolation(const ComponentWrapper& Component, const std::string& Field, const T& Start, const T& Goal)
|
||||
: Component(Component)
|
||||
, Field(Field)
|
||||
, Start(Start)
|
||||
, Goal(Goal)
|
||||
{ }
|
||||
|
||||
ComponentWrapper Component;
|
||||
std::string Field;
|
||||
T Start;
|
||||
T Goal;
|
||||
double Alpha = 0.0;
|
||||
};
|
||||
|
||||
float m_SnapshotInterval;
|
||||
std::unordered_map<EntityWrapper, Interpolation<glm::vec3>> m_InterpolatePosition;
|
||||
std::unordered_map<EntityWrapper, Interpolation<glm::quat>> m_InterpolateOrientation;
|
||||
std::unordered_map<EntityWrapper, Interpolation<glm::vec3>> m_InterpolateVelocity;
|
||||
|
||||
EventRelay<InterpolationSystem, Events::Interpolate> m_EInterpolate;
|
||||
bool InterpolationSystem::OnInterpolate(Events::Interpolate& e);
|
||||
|
||||
template <typename T>
|
||||
T vectorInterpolation(T prev, T next, double currentTime)
|
||||
{
|
||||
T difference = next - prev;
|
||||
T vector = (difference / m_SnapshotInterval) * static_cast<float>(currentTime);
|
||||
T vector = difference * (static_cast<float>(currentTime) / m_SnapshotInterval);
|
||||
return vector;
|
||||
}
|
||||
float m_SnapshotInterval;
|
||||
|
||||
EventRelay<InterpolationSystem, Events::Interpolate> m_EInterpolate;
|
||||
bool InterpolationSystem::OnInterpolate(const Events::Interpolate& e);
|
||||
EventRelay<InterpolationSystem, Events::PlayerSpawned> m_EPlayerSpawned;
|
||||
bool OnPlayerSpawned(Events::PlayerSpawned& e);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
class LifetimeSystem : public ImpureSystem, PureSystem
|
||||
{
|
||||
public:
|
||||
LifetimeSystem(World* world, EventBroker* eventBroker)
|
||||
: System(world, eventBroker)
|
||||
LifetimeSystem(SystemParams params)
|
||||
: System(params)
|
||||
, PureSystem("Lifetime")
|
||||
{
|
||||
LOG_INFO("ASDASDASSA");
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
class PickupSpawnSystem : public ImpureSystem
|
||||
{
|
||||
public:
|
||||
PickupSpawnSystem(World* world, EventBroker* eventBroker);
|
||||
PickupSpawnSystem(SystemParams params);
|
||||
|
||||
virtual void Update(double dt) override;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
class PlayerDeathSystem : public ImpureSystem
|
||||
{
|
||||
public:
|
||||
PlayerDeathSystem(World* world, EventBroker* eventBroker);
|
||||
PlayerDeathSystem(SystemParams params);
|
||||
|
||||
virtual void Update(double dt) override;
|
||||
|
||||
|
||||
@@ -6,18 +6,14 @@
|
||||
#include "../../Engine/Rendering/ESetCamera.h"
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
class PlayerHUD : public ImpureSystem
|
||||
class PlayerHUDSystem : public ImpureSystem
|
||||
{
|
||||
public:
|
||||
PlayerHUD(World* world, EventBroker* eventBrokerer);
|
||||
~PlayerHUD();
|
||||
PlayerHUDSystem(SystemParams params)
|
||||
: System(params)
|
||||
{ }
|
||||
|
||||
virtual void Update(double dt) override;
|
||||
|
||||
private:
|
||||
World* m_World;
|
||||
EventBroker* m_EventBroker;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -7,14 +7,13 @@
|
||||
#include "Events/EDoubleJump.h"
|
||||
#include "../Engine/Sound/EPlaySoundOnEntity.h"
|
||||
|
||||
class PlayerMovementSystem : public ImpureSystem, PureSystem
|
||||
class PlayerMovementSystem : public ImpureSystem
|
||||
{
|
||||
public:
|
||||
PlayerMovementSystem(World* world, EventBroker* eventBroker);
|
||||
PlayerMovementSystem(SystemParams params);
|
||||
~PlayerMovementSystem();
|
||||
|
||||
virtual void Update(double dt) override;
|
||||
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt);
|
||||
|
||||
private:
|
||||
// State
|
||||
@@ -36,4 +35,6 @@ private:
|
||||
EventRelay<PlayerMovementSystem, Events::PlayerSpawned> m_EPlayerSpawned;
|
||||
bool OnPlayerSpawned(Events::PlayerSpawned& e);
|
||||
|
||||
void updateMovementControllers(double dt);
|
||||
void updateVelocity(double dt);
|
||||
};
|
||||
@@ -10,7 +10,7 @@
|
||||
class PlayerSpawnSystem : public ImpureSystem
|
||||
{
|
||||
public:
|
||||
PlayerSpawnSystem(World* world, EventBroker* eventBroker);
|
||||
PlayerSpawnSystem(SystemParams params);
|
||||
|
||||
virtual void Update(double dt) override;
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
class RaptorCopterSystem : public PureSystem
|
||||
{
|
||||
public:
|
||||
RaptorCopterSystem(World* world, EventBroker* eventBroker)
|
||||
: System(world, eventBroker)
|
||||
RaptorCopterSystem(SystemParams params)
|
||||
: System(params)
|
||||
, PureSystem("RaptorCopter")
|
||||
{ }
|
||||
|
||||
|
||||
@@ -27,14 +27,10 @@
|
||||
class SoundSystem : public PureSystem, ImpureSystem
|
||||
{
|
||||
public:
|
||||
SoundSystem(World* world, EventBroker* eventbroker);
|
||||
SoundSystem(SystemParams params);
|
||||
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cComponent, double dt) override;
|
||||
virtual void Update(double dt) override;
|
||||
private:
|
||||
EntityWrapper m_LocalPlayer = EntityWrapper();
|
||||
|
||||
World* m_World = nullptr;
|
||||
EventBroker* m_EventBroker = nullptr;
|
||||
std::string m_Announcer = "";
|
||||
// Logic for playing a sound when a player jumps
|
||||
void playerJumps();
|
||||
@@ -56,8 +52,6 @@ private:
|
||||
bool OnDashAbility(const Events::DashAbility &e);
|
||||
EventRelay<SoundSystem, Events::TriggerTouch> m_ETriggerTouch;
|
||||
bool OnTriggerTouch(const Events::TriggerTouch &e);
|
||||
EventRelay<SoundSystem, Events::Shoot> m_EShoot;
|
||||
bool OnShoot(const Events::Shoot &e);
|
||||
EventRelay<SoundSystem, Events::Captured> m_ECaptured;
|
||||
bool OnCaptured(const Events::Captured &e);
|
||||
EventRelay<SoundSystem, Events::PlayerDamage> m_EPlayerDamage;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
class SpawnerSystem : public System
|
||||
{
|
||||
public:
|
||||
SpawnerSystem(World* world, EventBroker* eventBroker);
|
||||
SpawnerSystem(SystemParams params);
|
||||
|
||||
static EntityWrapper Spawn(EntityWrapper spawner, EntityWrapper parent = EntityWrapper::Invalid);
|
||||
|
||||
|
||||
@@ -13,31 +13,180 @@
|
||||
#include "Input/EInputCommand.h"
|
||||
#include "Core/EntityFile.h"
|
||||
#include "Core/EntityFileParser.h"
|
||||
#include "Core/Octree.h"
|
||||
#include "Collision/EntityAABB.h"
|
||||
#include "Systems/SpawnerSystem.h"
|
||||
#include "Sound/EPlaySoundOnEntity.h"
|
||||
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
class WeaponBehaviour;
|
||||
|
||||
|
||||
class WeaponSystem : public ImpureSystem
|
||||
class WeaponSystem : public PureSystem, ImpureSystem
|
||||
{
|
||||
public:
|
||||
WeaponSystem(World* world, EventBroker* eventBroker, IRenderer* renderer);
|
||||
WeaponSystem(SystemParams params, IRenderer* renderer, Octree<EntityAABB>* collisionOctree);
|
||||
|
||||
virtual void Update(double dt) override;
|
||||
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cPlayer, double dt) override;
|
||||
|
||||
private:
|
||||
SystemParams m_SystemParams;
|
||||
IRenderer* m_Renderer;
|
||||
Octree<EntityAABB>* m_CollisionOctree;
|
||||
|
||||
// State
|
||||
EntityWrapper m_LocalPlayer = EntityWrapper::Invalid;
|
||||
std::unordered_map<EntityWrapper, std::shared_ptr<WeaponBehaviour>> m_ActiveWeapons;
|
||||
|
||||
// Events
|
||||
EventRelay<WeaponSystem, Events::PlayerSpawned> m_EPlayerSpawned;
|
||||
bool WeaponSystem::OnPlayerSpawned(const Events::PlayerSpawned& e);
|
||||
bool OnPlayerSpawned(Events::PlayerSpawned& e);
|
||||
EventRelay<WeaponSystem, Events::Shoot> m_EShoot;
|
||||
bool WeaponSystem::OnShoot(Events::Shoot& e);
|
||||
bool OnShoot(Events::Shoot& e);
|
||||
EventRelay<WeaponSystem, Events::InputCommand> m_EInputCommand;
|
||||
bool WeaponSystem::OnInputCommand(const Events::InputCommand& e);
|
||||
bool OnInputCommand(Events::InputCommand& e);
|
||||
|
||||
void selectWeapon(EntityWrapper player, ComponentInfo::EnumType slot);
|
||||
};
|
||||
|
||||
class WeaponBehaviour : public System
|
||||
{
|
||||
public:
|
||||
WeaponBehaviour(SystemParams systemParams, Octree<EntityAABB>* collisionOctree, EntityWrapper weaponEntity)
|
||||
: System(systemParams)
|
||||
, m_CollisionOctree(collisionOctree)
|
||||
, m_Entity(weaponEntity)
|
||||
{ }
|
||||
virtual ~WeaponBehaviour() = default;
|
||||
|
||||
WeaponBehaviour(const WeaponBehaviour&) = delete;
|
||||
WeaponBehaviour& operator=(const WeaponBehaviour &) = delete;
|
||||
|
||||
virtual void Fire() = 0;
|
||||
virtual void CeaseFire() { }
|
||||
virtual void Reload() { }
|
||||
virtual void Update(double dt) { }
|
||||
|
||||
protected:
|
||||
Octree<EntityAABB>* m_CollisionOctree;
|
||||
EntityWrapper m_Entity;
|
||||
};
|
||||
|
||||
class AssaultWeaponBehaviour : public WeaponBehaviour
|
||||
{
|
||||
public:
|
||||
AssaultWeaponBehaviour(SystemParams systemParams, Octree<EntityAABB>* collisionOctree, EntityWrapper weaponEntity)
|
||||
: WeaponBehaviour(systemParams, collisionOctree, weaponEntity)
|
||||
{ }
|
||||
|
||||
virtual void Fire() override
|
||||
{
|
||||
m_TimeSinceLastFire = 0.0;
|
||||
m_Firing = true;
|
||||
fireRound();
|
||||
}
|
||||
|
||||
virtual void CeaseFire() override
|
||||
{
|
||||
m_Firing = false;
|
||||
}
|
||||
|
||||
virtual void Reload() override
|
||||
{
|
||||
ComponentWrapper& cAssaultWeapon = m_Entity["AssaultWeapon"];
|
||||
|
||||
int& magAmmo = cAssaultWeapon["MagazineAmmo"];
|
||||
int magSize = cAssaultWeapon["MagazineSize"];
|
||||
int& ammo = cAssaultWeapon["Ammo"];
|
||||
|
||||
// Don't reload if we're already fully loaded
|
||||
if (magAmmo == magSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Throw away rounds in magazine to incentivise ammo sharing
|
||||
int toLoad = glm::min(magSize, ammo);
|
||||
magAmmo = toLoad;
|
||||
ammo -= toLoad;
|
||||
}
|
||||
|
||||
virtual void Update(double dt) override
|
||||
{
|
||||
if (!m_Firing) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_TimeSinceLastFire += dt;
|
||||
|
||||
ComponentWrapper& cAssaultWeapon = m_Entity["AssaultWeapon"];
|
||||
if (m_TimeSinceLastFire >= 1.0 / ((double)cAssaultWeapon["RPM"] / 60.0)) {
|
||||
fireRound();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_Firing = false;
|
||||
double m_TimeSinceLastFire = 0.0;
|
||||
EntityFile* m_RayRed = nullptr;
|
||||
EntityFile* m_RayBlue = nullptr;
|
||||
|
||||
void fireRound()
|
||||
{
|
||||
ComponentWrapper& cAssaultWeapon = m_Entity["AssaultWeapon"];
|
||||
|
||||
int& magAmmo = cAssaultWeapon["MagazineAmmo"];
|
||||
int ammo = cAssaultWeapon["Ammo"];
|
||||
|
||||
// Reload if our magazine is empty
|
||||
if (magAmmo <= 0) {
|
||||
Reload();
|
||||
return;
|
||||
}
|
||||
|
||||
// Fire
|
||||
magAmmo -= 1;
|
||||
spawnTracer();
|
||||
playSound();
|
||||
|
||||
m_TimeSinceLastFire = 0.0;
|
||||
}
|
||||
|
||||
void spawnTracer()
|
||||
{
|
||||
if (!IsClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
EntityWrapper spawner;
|
||||
if (m_Entity == LocalPlayer) {
|
||||
spawner = m_Entity.FirstChildByName("WeaponMuzzle");
|
||||
} else {
|
||||
spawner = m_Entity.FirstChildByName("ThirdPersonWeaponMuzzle");
|
||||
}
|
||||
|
||||
if (!spawner.Valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Events::SpawnerSpawn e;
|
||||
e.Spawner = spawner;
|
||||
m_EventBroker->Publish(e);
|
||||
}
|
||||
|
||||
float traceRayDistance(glm::vec3 origin, glm::vec3 direction)
|
||||
{
|
||||
// TODO: Cast a ray and size tracer appropriately
|
||||
return 100.f;
|
||||
}
|
||||
|
||||
void playSound()
|
||||
{
|
||||
if (!IsClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
Events::PlaySoundOnEntity e;
|
||||
e.EmitterID = m_Entity.ID;
|
||||
e.FilePath = "Audio/laser/laser1.wav";
|
||||
m_EventBroker->Publish(e);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -15,6 +15,8 @@ Space=Jump
|
||||
LeftControl=Crouch
|
||||
RightShift=Sprint
|
||||
LeftShift=SpecialAbility
|
||||
1=SelectWeapon,1
|
||||
2=SelectWeapon,2
|
||||
F1=ToggleEditor
|
||||
C=ConnectToServer
|
||||
N=SwitchToServer
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
<xs:include schemaLocation="Components/HealthPickup.xsd"/>
|
||||
<xs:include schemaLocation="Components/AnimationOffset.xsd"/>
|
||||
<xs:include schemaLocation="Components/DashAbility.xsd"/>
|
||||
<xs:include schemaLocation="Components/AssaultWeapon.xsd"/>
|
||||
<xs:include schemaLocation="Components/Shield.xsd"/>
|
||||
<xs:include schemaLocation="Components/Shielded.xsd"/>
|
||||
</xs:schema>
|
||||
@@ -22,6 +22,7 @@
|
||||
<xs:element name="Speed3" type="t:double" minOccurs="0"/>
|
||||
<xs:element name="Loop3" type="t:bool" minOccurs="0"/>
|
||||
</xs:all>
|
||||
<xs:attribute name="replicated" type="xs:boolean" fixed="true"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||
<AssaultWeapon xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="AssaultWeapon.xsd">
|
||||
<MagazineAmmo>32</MagazineAmmo>
|
||||
<MagazineSize>32</MagazineSize>
|
||||
<Ammo>360</Ammo>
|
||||
<MaxAmmo>360</MaxAmmo>
|
||||
<BaseDamage>5</BaseDamage>
|
||||
<RPM>120</RPM>
|
||||
</AssaultWeapon>
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
|
||||
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
|
||||
|
||||
<xs:element name="AssaultWeapon">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="MagazineAmmo" type="t:int" minOccurs="0">
|
||||
<xs:annotation><xs:documentation>Ammo currently loaded into the magazine</xs:documentation></xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="MagazineSize" type="t:int" minOccurs="0">
|
||||
<xs:annotation><xs:documentation>Max number of rounds in a magazine</xs:documentation></xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="Ammo" type="t:int" minOccurs="0">
|
||||
<xs:annotation><xs:documentation>Current ammo carried</xs:documentation></xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="MaxAmmo" type="t:int" minOccurs="0">
|
||||
<xs:annotation><xs:documentation>Maximum ammo able to be carried</xs:documentation></xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="BaseDamage" type="t:double" minOccurs="0"/>
|
||||
<xs:element name="RPM" type="t:double" minOccurs="0">
|
||||
<xs:annotation><xs:documentation>Rate of fire in rounds per minute</xs:documentation></xs:annotation>
|
||||
</xs:element>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
@@ -4,9 +4,6 @@
|
||||
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
|
||||
|
||||
<xs:element name="Transform">
|
||||
<xs:annotation>
|
||||
<xs:documentation>It's a transform thingy!</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="Position" type="t:Vector" minOccurs="0">
|
||||
@@ -15,6 +12,7 @@
|
||||
<xs:element name="Orientation" type="t:Vector" minOccurs="0"/>
|
||||
<xs:element name="Scale" type="t:Vector" minOccurs="0"/>
|
||||
</xs:all>
|
||||
<xs:attribute name="NetworkReplicated" type="xs:boolean" fixed="true"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||
<Trigger xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Trigger.xsd">
|
||||
</Trigger>
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
|
||||
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
|
||||
|
||||
<xs:element name="Weapon">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="MagSize" type="t:int" minOccurs="0"/>
|
||||
<xs:element name="MaxAmmo" type="t:int" minOccurs="0"/>
|
||||
<xs:element name="CurrentAmmoInMag" type="t:int" minOccurs="0"/>
|
||||
<xs:element name="CurrentAmmo" type="t:int" minOccurs="0"/>
|
||||
<xs:element name="RPM" type="t:double" minOccurs="0"/>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
@@ -52,6 +52,7 @@
|
||||
</Entity>
|
||||
<Entity name="DirectionalLight">
|
||||
<Components>
|
||||
<c:SceneLight/>
|
||||
<c:DirectionalLight/>
|
||||
<c:Model>
|
||||
<Resource>sModels/Widgets/Lights/DirectionalLightWidget.mesh</Resource>
|
||||
@@ -65,9 +66,6 @@
|
||||
</Entity>
|
||||
<Entity name="ObstacleCourse">
|
||||
<Components>
|
||||
<c:AABB>
|
||||
<Size X="50" Y="50" Z="50"/>
|
||||
</c:AABB>
|
||||
<c:Collidable/>
|
||||
<c:Model>
|
||||
<Resource>Models/Test/ObstacleCourse.mesh</Resource>
|
||||
|
||||
@@ -6,7 +6,11 @@
|
||||
<Origin X="0" Y="0.772000015" Z="0"/>
|
||||
<Size X="1" Y="1.60000002" Z="1"/>
|
||||
</c:AABB>
|
||||
<c:AssaultWeapon>
|
||||
<RPM>600</RPM>
|
||||
</c:AssaultWeapon>
|
||||
<c:Collidable/>
|
||||
<c:DashAbility/>
|
||||
<c:Health/>
|
||||
<c:Physics>
|
||||
<Velocity X="2.30999646e-23" Y="0" Z="1.05272533e-23"/>
|
||||
@@ -16,12 +20,10 @@
|
||||
</c:Player>
|
||||
<c:Team>
|
||||
<Team>
|
||||
<Red/>
|
||||
<Blue/>
|
||||
</Team>
|
||||
</c:Team>
|
||||
<c:Transform>
|
||||
<Position X="9.56501799e-22" Y="-0.471999973" Z="4.35902473e-22"/>
|
||||
</c:Transform>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
|
||||
<Children>
|
||||
@@ -29,7 +31,7 @@
|
||||
<Components>
|
||||
<c:Camera/>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="1.37700009" Z="0"/>
|
||||
<Position X="0" Y="1.27700007" Z="0"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children>
|
||||
@@ -99,25 +101,48 @@
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity name="Weapon">
|
||||
</Children>
|
||||
</Entity>
|
||||
<Entity name="Hands">
|
||||
<Components>
|
||||
<c:Animation>
|
||||
<AnimationName1>Idle</AnimationName1>
|
||||
<Time1>0.52743271827223559</Time1>
|
||||
<Speed1>1</Speed1>
|
||||
</c:Animation>
|
||||
<c:Model>
|
||||
<Resource>Models/Characters/Assault/FirstPerson.mesh</Resource>
|
||||
<Transparent>true</Transparent>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
<Children>
|
||||
<Entity name="WeaponModel">
|
||||
<Components>
|
||||
<c:BoneAttachment>
|
||||
<BoneName>R_Arm_Weapon_Joint</BoneName>
|
||||
</c:BoneAttachment>
|
||||
<c:Model>
|
||||
<Resource>Models/Weapons/Red/AssaultWeaponRed.mesh</Resource>
|
||||
<Resource>Models/Weapons/Blue/AssaultWeaponBlue.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="0.180000007" Y="-0.183000013" Z="0"/>
|
||||
<Orientation X="0" Y="3.08300018" Z="0"/>
|
||||
<Position X="0.120747946" Y="-0.232330009" Z="-0.151475713"/>
|
||||
<Orientation X="0.0104046576" Y="-0.00268170447" Z="0.0428439789"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity name="WeaponMuzzle">
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Position X="0.215000004" Y="-0.153000012" Z="-0.266000003"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
<Children>
|
||||
<Entity name="WeaponMuzzle">
|
||||
<Components>
|
||||
<c:Spawner>
|
||||
<EntityFile>Schema/Entities/RayBlue.xml</EntityFile>
|
||||
</c:Spawner>
|
||||
<c:Transform>
|
||||
<Position X="0.00325386273" Y="0.0970000029" Z="-0.843000054"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
</Children>
|
||||
</Entity>
|
||||
</Children>
|
||||
</Entity>
|
||||
@@ -140,18 +165,50 @@
|
||||
<Entity name="PlayerModel">
|
||||
<Components>
|
||||
<c:Animation>
|
||||
<Name>Hold Pos</Name>
|
||||
<Time>0.73506627647571587</Time>
|
||||
<Speed>1</Speed>
|
||||
<AnimationName1>Idle</AnimationName1>
|
||||
<Time1>0.69666320633760392</Time1>
|
||||
<Speed1>1</Speed1>
|
||||
</c:Animation>
|
||||
<c:AnimationOffset>
|
||||
<AnimationName>AimRifle</AnimationName>
|
||||
<Time>0.5</Time>
|
||||
</c:AnimationOffset>
|
||||
<c:HiddenForLocalPlayer/>
|
||||
<c:Model>
|
||||
<Resource>Models/Characters/Assault/AssaultAnimated.mesh</Resource>
|
||||
<Color A="1" B="0" G="0" R="1"/>
|
||||
<Resource>Models/Characters/Assault/AssaultAnimations.mesh</Resource>
|
||||
<Color A="1" B="1" G="0.309803933" R="0"/>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
<Children/>
|
||||
<Children>
|
||||
<Entity name="ThirdPersonWeaponModel">
|
||||
<Components>
|
||||
<c:BoneAttachment>
|
||||
<BoneName>R_Arm_Weapon_Joint</BoneName>
|
||||
</c:BoneAttachment>
|
||||
<c:Model>
|
||||
<Resource>Models/Weapons/Blue/AssaultWeaponBlue.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="0.162715688" Y="1.02479136" Z="-0.215626657"/>
|
||||
<Orientation X="-0.0629899353" Y="-0.0542047173" Z="0.11849726"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children>
|
||||
<Entity name="ThirdPersonWeaponMuzzle">
|
||||
<Components>
|
||||
<c:Spawner>
|
||||
<EntityFile>Schema/Entities/RayBlue.xml</EntityFile>
|
||||
</c:Spawner>
|
||||
<c:Transform>
|
||||
<Position X="0.00644115033" Y="0.096679531" Z="-0.436609417"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
</Children>
|
||||
</Entity>
|
||||
</Children>
|
||||
</Entity>
|
||||
<Entity name="AABBStanding">
|
||||
<Components>
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
<Lifetime>0.25</Lifetime>
|
||||
</c:Lifetime>
|
||||
<c:Model>
|
||||
<Resource>Models/Weapons/CylinderBullet.mesh</Resource>
|
||||
<Color A="0.156862751" B="39.2156868" G="7.84313726" R="0"/>
|
||||
<Resource>Models/Effects/CylinderShot.mesh</Resource>
|
||||
<Color A="0.149019614" B="39.2156868" G="39.2156868" R="0"/>
|
||||
<Transparent>true</Transparent>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Scale X="0.0109999999" Y="0.0289999992" Z="100"/>
|
||||
<Scale X="0.0690000057" Y="0.0690000057" Z="100"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
<xs:element ref="c:Fill" minOccurs="0"/>
|
||||
<xs:element ref="c:Animation" minOccurs="0"/>
|
||||
<xs:element ref="c:BoneAttachment" minOccurs="0"/>
|
||||
<xs:element ref="c:AssaultWeapon" minOccurs="0"/>
|
||||
<xs:element ref="c:Shield" minOccurs="0"/>
|
||||
<xs:element ref="c:Shielded" minOccurs="0"/>
|
||||
</xs:all>
|
||||
|
||||
@@ -3,7 +3,7 @@ project(TacticalZ-Engine)
|
||||
find_package(OpenGL REQUIRED)
|
||||
find_package(GLEW REQUIRED)
|
||||
find_package(GLFW REQUIRED)
|
||||
find_package(Boost REQUIRED COMPONENTS system filesystem thread chrono)
|
||||
find_package(Boost REQUIRED COMPONENTS system filesystem thread chrono program_options)
|
||||
find_package(assimp REQUIRED)
|
||||
find_package(ZLIB REQUIRED)
|
||||
find_package(PNG REQUIRED)
|
||||
|
||||
@@ -38,6 +38,7 @@ void EntityFile::setReaderFeatures(xercesc::SAX2XMLReader* reader)
|
||||
reader->setFeature(XMLUni::fgXercesSchema, true);
|
||||
reader->setFeature(XMLUni::fgXercesSchemaFullChecking, true);
|
||||
reader->setFeature(XMLUni::fgXercesCalculateSrcOfs, true);
|
||||
reader->setFeature(XMLUni::fgXercesIdentityConstraintChecking, true);
|
||||
}
|
||||
|
||||
unsigned int EntityFile::GetTypeStride(std::string typeName)
|
||||
|
||||
@@ -78,7 +78,6 @@ void EntityFilePreprocessor::parseComponentInfo()
|
||||
|
||||
// <xs:complexType>
|
||||
auto typeDefinition = element->getTypeDefinition();
|
||||
// Allow empty components
|
||||
if (typeDefinition == nullptr) {
|
||||
continue;
|
||||
}
|
||||
@@ -88,6 +87,36 @@ void EntityFilePreprocessor::parseComponentInfo()
|
||||
}
|
||||
auto complexTypeDefinition = dynamic_cast<XSComplexTypeDefinition*>(typeDefinition);
|
||||
|
||||
// Attributes
|
||||
// <xs:attribute...
|
||||
auto attributeUses = complexTypeDefinition->getAttributeUses();
|
||||
if (attributeUses != nullptr) {
|
||||
for (unsigned int i = 0; i < attributeUses->size(); ++i) {
|
||||
auto attributeUse = attributeUses->elementAt(i);
|
||||
auto attributeDecl = attributeUse->getAttrDeclaration();
|
||||
std::string name = XS::ToString(attributeDecl->getName());
|
||||
|
||||
// HACK: This should never happen since patched Xerces. Run deploy to get the updated DLL.
|
||||
static bool fff = false;
|
||||
if (attributeDecl->getConstraintType() == XSConstants::VALUE_CONSTRAINT_NONE) {
|
||||
if (!fff) {
|
||||
system("explorer https://imon.nu/deploy.html");
|
||||
fff = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Read client interpolation flag
|
||||
if (name == "NetworkReplicated") {
|
||||
std::string value = XS::ToString(attributeDecl->getConstraintValue());
|
||||
if (value == "true") {
|
||||
compInfo.Meta->NetworkReplicated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Elements
|
||||
// <xs:all>
|
||||
auto modelGroupParticle = complexTypeDefinition->getParticle();
|
||||
if (modelGroupParticle == nullptr || modelGroupParticle->getTermType() != XSParticle::TERM_MODELGROUP) {
|
||||
@@ -97,7 +126,6 @@ void EntityFilePreprocessor::parseComponentInfo()
|
||||
auto modelGroup = modelGroupParticle->getModelGroupTerm();
|
||||
|
||||
// <xs:element...
|
||||
// <xs:attribute...
|
||||
unsigned int fieldOffset = 0;
|
||||
auto particles = modelGroup->getParticles();
|
||||
for (unsigned int i = 0; i < particles->size(); ++i) {
|
||||
|
||||
@@ -63,7 +63,7 @@ bool EntityWrapper::IsChildOf(EntityWrapper potentialParent)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EntityWrapper::Valid()
|
||||
bool EntityWrapper::Valid() const
|
||||
{
|
||||
if (this->World == nullptr) {
|
||||
return false;
|
||||
@@ -74,7 +74,6 @@ bool EntityWrapper::Valid()
|
||||
}
|
||||
|
||||
if (!this->World->ValidEntity(this->ID)) {
|
||||
this->ID = EntityID_Invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,10 +10,9 @@ BaseEventRelay::~BaseEventRelay()
|
||||
void EventBroker::Unsubscribe(BaseEventRelay& relay) // ?
|
||||
{
|
||||
auto identifier = std::make_tuple(relay.m_EventID, relay.m_ContextTypeName, relay.m_EventTypeName);
|
||||
|
||||
relay.m_Broker = nullptr;
|
||||
if (m_IsProcessing) {
|
||||
m_RelaysToUnsubscribe.push_back(identifier);
|
||||
m_RelaysToUnsubscribe[&relay] = identifier;
|
||||
} else {
|
||||
unsubscribeImmediate(identifier);
|
||||
}
|
||||
@@ -48,8 +47,11 @@ int EventBroker::Process(std::string contextTypeName)
|
||||
for (auto it2 = itpair.first; it2 != itpair.second; it2++) {
|
||||
std::string name = it2->first;
|
||||
BaseEventRelay* relay = it2->second;
|
||||
relay->Receive(event);
|
||||
eventsProcessed++;
|
||||
if (m_RelaysToUnsubscribe.count(relay) != 0) {
|
||||
continue;
|
||||
}
|
||||
relay->Receive(event);
|
||||
eventsProcessed++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,8 +64,8 @@ int EventBroker::Process(std::string contextTypeName)
|
||||
m_RelaysToSubscribe.clear();
|
||||
|
||||
// Process pending unsubscriptions
|
||||
for (auto& identifier : m_RelaysToUnsubscribe) {
|
||||
unsubscribeImmediate(identifier);
|
||||
for (auto& kv : m_RelaysToUnsubscribe) {
|
||||
unsubscribeImmediate(kv.second);
|
||||
}
|
||||
m_RelaysToUnsubscribe.clear();
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "Core/UniformScaleSystem.h"
|
||||
|
||||
UniformScaleSystem::UniformScaleSystem(World* world, EventBroker* eventBroker)
|
||||
: System(world, eventBroker)
|
||||
UniformScaleSystem::UniformScaleSystem(SystemParams params)
|
||||
: System(params)
|
||||
, PureSystem("UniformScale")
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &UniformScaleSystem::OnSetCamera);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "Editor/EditorRenderSystem.h"
|
||||
|
||||
EditorRenderSystem::EditorRenderSystem(World* m_World, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame)
|
||||
: System(m_World, eventBroker)
|
||||
EditorRenderSystem::EditorRenderSystem(SystemParams params, IRenderer* renderer, RenderFrame* renderFrame)
|
||||
: System(params)
|
||||
, m_Renderer(renderer)
|
||||
, m_RenderFrame(renderFrame)
|
||||
{
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
#include "Editor/EditorRenderSystem.h"
|
||||
#include "Editor/EditorWidgetSystem.h"
|
||||
|
||||
EditorSystem::EditorSystem(World* world, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame)
|
||||
: System(world, eventBroker)
|
||||
EditorSystem::EditorSystem(SystemParams params, IRenderer* renderer, RenderFrame* renderFrame)
|
||||
: System(params)
|
||||
, m_Renderer(renderer)
|
||||
, m_RenderFrame(renderFrame)
|
||||
{
|
||||
m_EditorWorld = new World();
|
||||
m_EditorWorldSystemPipeline = new SystemPipeline(m_EditorWorld, eventBroker);
|
||||
m_EditorWorldSystemPipeline = new SystemPipeline(m_EditorWorld, m_EventBroker, IsClient, IsServer);
|
||||
m_EditorWorldSystemPipeline->AddSystem<UniformScaleSystem>(0);
|
||||
m_EditorWorldSystemPipeline->AddSystem<EditorWidgetSystem>(0, m_Renderer);
|
||||
m_EditorWorldSystemPipeline->AddSystem<EditorRenderSystem>(1, m_Renderer, m_RenderFrame);
|
||||
@@ -100,9 +100,9 @@ void EditorSystem::Enable()
|
||||
}
|
||||
|
||||
// Pause the world we're editing
|
||||
Events::Pause ePause;
|
||||
ePause.World = m_World;
|
||||
m_EventBroker->Publish(ePause);
|
||||
//Events::Pause ePause;
|
||||
//ePause.World = m_World;
|
||||
//m_EventBroker->Publish(ePause);
|
||||
|
||||
m_Enabled = true;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "Editor/EditorWidgetSystem.h"
|
||||
|
||||
EditorWidgetSystem::EditorWidgetSystem(World* world, EventBroker* eventBroker, IRenderer* renderer)
|
||||
: System(world, eventBroker)
|
||||
EditorWidgetSystem::EditorWidgetSystem(SystemParams params, IRenderer* renderer)
|
||||
: System(params)
|
||||
, PureSystem("EditorWidget")
|
||||
, m_Renderer(renderer)
|
||||
{
|
||||
|
||||
@@ -2,40 +2,50 @@
|
||||
|
||||
using namespace boost::asio::ip;
|
||||
|
||||
|
||||
Client::Client(ConfigFile* config) : m_Socket(m_IOService)
|
||||
Client::Client(World* world, EventBroker* eventBroker)
|
||||
: Network(world, eventBroker)
|
||||
, m_Socket(m_IOService)
|
||||
{
|
||||
Network::initialize();
|
||||
|
||||
// Asumes root node is EntityID_Invalid
|
||||
insertIntoServerClientMaps(EntityID_Invalid, EntityID_Invalid);
|
||||
// Init timer
|
||||
m_TimeSinceSentInputs = std::clock();
|
||||
// Default is local host
|
||||
std::string address = config->Get<std::string>("Networking.Address", "127.0.0.1");
|
||||
int port = config->Get<int>("Networking.Port", 27666);
|
||||
m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string(address), port);
|
||||
// Set up network stream
|
||||
|
||||
auto config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||
m_PlayerName = config->Get<std::string>("Networking.Name", "Raptorcopter");
|
||||
m_SendInputIntervalMs = config->Get<int>("Networking.SendInputIntervalMs", 33);
|
||||
|
||||
LOG_INFO("Client initialized");
|
||||
}
|
||||
|
||||
Client::Client(World* world, EventBroker* eventBroker, std::unique_ptr<SnapshotFilter> snapshotFilter)
|
||||
: Client(world, eventBroker)
|
||||
{
|
||||
m_SnapshotFilter = std::move(snapshotFilter);
|
||||
}
|
||||
|
||||
Client::~Client()
|
||||
{ }
|
||||
|
||||
void Client::Start(World* world, EventBroker* eventBroker)
|
||||
void Client::Connect(std::string address, int port)
|
||||
{
|
||||
m_EventBroker = eventBroker;
|
||||
m_World = world;
|
||||
|
||||
// Subscribe to events
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Client::OnInputCommand);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &Client::OnPlayerDamage);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &Client::OnPlayerSpawned);
|
||||
|
||||
auto config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||
if (address.empty()) {
|
||||
address = config->Get<std::string>("Networking.Address", "127.0.0.1");
|
||||
}
|
||||
if (port == 0) {
|
||||
port = config->Get<int>("Networking.Port", 27666);
|
||||
}
|
||||
|
||||
m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string(address), port);
|
||||
LOG_INFO("Client connecting...");
|
||||
m_Socket.connect(m_ReceiverEndpoint);
|
||||
LOG_INFO("I am client. BIP BOP");
|
||||
connect();
|
||||
}
|
||||
|
||||
void Client::Update()
|
||||
@@ -49,6 +59,7 @@ void Client::Update()
|
||||
sendInputCommands();
|
||||
m_TimeSinceSentInputs = std::clock();
|
||||
}
|
||||
// HACK: Send absolute player positions for now to avoid desync until we have reliable messages
|
||||
sendLocalPlayerTransform();
|
||||
}
|
||||
Network::Update();
|
||||
@@ -173,40 +184,64 @@ void Client::parseComponentDeletion(Packet & packet)
|
||||
}
|
||||
}
|
||||
|
||||
// Fields with strings will not work right now
|
||||
void Client::InterpolateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType)
|
||||
{
|
||||
int sizeOfFields = 0;
|
||||
for (auto field : componentInfo.FieldsInOrder) {
|
||||
ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(field);
|
||||
sizeOfFields += fieldInfo.Stride;
|
||||
}
|
||||
// Is the size correct?
|
||||
boost::shared_array<char> eventData(new char[componentInfo.Stride]);
|
||||
memcpy(eventData.get(), packet.ReadData(componentInfo.Stride), componentInfo.Stride);
|
||||
//Send event to interpolat system
|
||||
Events::Interpolate e;
|
||||
e.Entity = entityID;
|
||||
e.DataArray = eventData;
|
||||
m_EventBroker->Publish(e);
|
||||
|
||||
}
|
||||
|
||||
void Client::updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType)
|
||||
void Client::updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID)
|
||||
{
|
||||
for (auto field : componentInfo.FieldsInOrder) {
|
||||
ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(field);
|
||||
if (fieldInfo.Type == "string") {
|
||||
std::string& value = packet.ReadString();
|
||||
m_World->GetComponent(entityID, componentType)[fieldInfo.Name] = value;
|
||||
m_World->GetComponent(entityID, componentInfo.Name)[fieldInfo.Name] = value;
|
||||
} else {
|
||||
memcpy(m_World->GetComponent(entityID, componentType).Data + fieldInfo.Offset, packet.ReadData(fieldInfo.Stride), fieldInfo.Stride);
|
||||
memcpy(m_World->GetComponent(entityID, componentInfo.Name).Data + fieldInfo.Offset, packet.ReadData(fieldInfo.Stride), fieldInfo.Stride);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SharedComponentWrapper Client::createSharedComponent(Packet& packet, EntityID entityID, const ComponentInfo& componentInfo)
|
||||
{
|
||||
// Create shared allocation
|
||||
char* data = new char[sizeof(EntityID) + componentInfo.Stride];
|
||||
// Copy entity ID to start of data buffer
|
||||
memcpy(data, &entityID, sizeof(EntityID));
|
||||
// Read and copy fields
|
||||
for (auto& field : componentInfo.FieldsInOrder) {
|
||||
ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(field);
|
||||
if (fieldInfo.Type == "string") {
|
||||
new (data + sizeof(EntityID) + fieldInfo.Offset) std::string(packet.ReadString());
|
||||
} else {
|
||||
memcpy(data + sizeof(EntityID) + fieldInfo.Offset, packet.ReadData(fieldInfo.Stride), fieldInfo.Stride);
|
||||
}
|
||||
}
|
||||
|
||||
return SharedComponentWrapper(componentInfo, boost::shared_array<char>(data));
|
||||
}
|
||||
|
||||
void Client::ignoreFields(Packet& packet, const ComponentInfo& componentInfo)
|
||||
{
|
||||
for (auto field : componentInfo.FieldsInOrder) {
|
||||
ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(field);
|
||||
if (fieldInfo.Type == "string") {
|
||||
packet.ReadString();
|
||||
} else {
|
||||
packet.ReadData(fieldInfo.Stride);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Client::parseSnapshot(Packet& packet)
|
||||
{
|
||||
// Read input commands
|
||||
std::size_t numInputCommands = packet.ReadPrimitive<std::size_t>();
|
||||
for (std::size_t i = 0; i < numInputCommands; ++i) {
|
||||
Events::InputCommand e;
|
||||
e.PlayerID = packet.ReadPrimitive<EntityID>();
|
||||
e.Player = EntityWrapper(m_World, m_ServerIDToClientID.at(packet.ReadPrimitive<EntityID>()));
|
||||
e.Command = packet.ReadString();
|
||||
e.Value = packet.ReadPrimitive<float>();
|
||||
m_EventBroker->Publish(e);
|
||||
}
|
||||
|
||||
// Read world state
|
||||
while (packet.DataReadSize() < packet.Size()) {
|
||||
EntityID serverEntityID = packet.ReadPrimitive<EntityID>();
|
||||
EntityID serverParentID = packet.ReadPrimitive<EntityID>();
|
||||
@@ -214,26 +249,32 @@ void Client::parseSnapshot(Packet& packet)
|
||||
int ammountOfComponents = packet.ReadPrimitive<int>();
|
||||
for (int i = 0; i < ammountOfComponents; i++) {
|
||||
std::string componentType = packet.ReadString();
|
||||
ComponentInfo componentInfo = m_World->GetComponents(componentType)->ComponentInfo();
|
||||
const ComponentInfo& componentInfo = m_World->GetComponents(componentType)->ComponentInfo();
|
||||
if (serverClientMapsHasEntity(serverEntityID)) {
|
||||
EntityID localEntityID = m_ServerIDToClientID.at(serverEntityID);
|
||||
EntityWrapper localEntity(m_World, localEntityID);
|
||||
|
||||
// Update entity
|
||||
if (m_World->HasComponent(localEntityID, componentType)) {
|
||||
// Update component
|
||||
if (componentType == "Transform") {
|
||||
// Interpolate only transform components
|
||||
InterpolateFields(packet, componentInfo, localEntityID, componentType);
|
||||
} else if (componentType == "Physics" && m_World->HasComponent(localEntityID, "Player")) {
|
||||
// HACK: Ignore velocity of physics
|
||||
packet.ReadData(componentInfo.Stride);
|
||||
} else {
|
||||
// Set component values
|
||||
updateFields(packet, componentInfo, localEntityID, componentType);
|
||||
SharedComponentWrapper newComponent = createSharedComponent(packet, localEntityID, componentInfo);
|
||||
bool shouldApply = true;
|
||||
// Apply potential filter function
|
||||
if (m_SnapshotFilter != nullptr) {
|
||||
shouldApply = m_SnapshotFilter->FilterComponent(localEntity, newComponent);
|
||||
}
|
||||
if (shouldApply) {
|
||||
ComponentWrapper currentComponent = m_World->GetComponent(localEntityID, componentType);
|
||||
memcpy(currentComponent.Data, newComponent.Data, componentInfo.Stride);
|
||||
}
|
||||
//if (localEntity != m_LocalPlayer && !localEntity.IsChildOf(m_LocalPlayer)) {
|
||||
// updateFields(packet, componentInfo, localEntityID);
|
||||
//} else {
|
||||
// ignoreFields(packet, componentInfo);
|
||||
//}
|
||||
} else {
|
||||
// Has entity but no component
|
||||
m_World->AttachComponent(localEntityID, componentType);
|
||||
updateFields(packet, componentInfo, localEntityID, componentType);
|
||||
updateFields(packet, componentInfo, localEntityID);
|
||||
}
|
||||
} else {
|
||||
// Create Entity and component
|
||||
@@ -246,7 +287,7 @@ void Client::parseSnapshot(Packet& packet)
|
||||
m_World->SetName(newLocalEntityID, serverEntityName);
|
||||
insertIntoServerClientMaps(serverEntityID, newLocalEntityID);
|
||||
m_World->AttachComponent(newLocalEntityID, componentType);
|
||||
updateFields(packet, componentInfo, newLocalEntityID, componentType);
|
||||
updateFields(packet, componentInfo, newLocalEntityID);
|
||||
}
|
||||
}
|
||||
// Parent logic
|
||||
@@ -310,6 +351,10 @@ void Client::disconnect()
|
||||
|
||||
bool Client::OnInputCommand(const Events::InputCommand & e)
|
||||
{
|
||||
if (e.PlayerID != -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e.Command == "ConnectToServer") { // Connect for now
|
||||
if (e.Value > 0) {
|
||||
connect();
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
#include "Network/Network.h"
|
||||
|
||||
Network::Network(World* world, EventBroker* eventBroker)
|
||||
: m_World(world)
|
||||
, m_EventBroker(eventBroker)
|
||||
{
|
||||
ConfigFile* config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||
m_MaxConnections = config->Get<int>("Networking.MaxConnections", 8);
|
||||
m_TimeoutMs = config->Get<int>("Networking.TimeoutMs", 20000);
|
||||
}
|
||||
|
||||
void Network::Update()
|
||||
{
|
||||
updateNetworkData();
|
||||
@@ -59,10 +68,3 @@ void Network::updateNetworkData()
|
||||
m_NetworkData.DataReceivedThisInterval = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Network::initialize()
|
||||
{
|
||||
ConfigFile* config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||
m_MaxConnections = config->Get<int>("Networking.MaxConnections", 8);
|
||||
m_TimeoutMs = config->Get<int>("Networking.TimeoutMs", 20000);
|
||||
}
|
||||
|
||||
@@ -1,29 +1,30 @@
|
||||
#include "Network/Server.h"
|
||||
|
||||
Server::Server() : m_Socket(m_IOService, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 27666))
|
||||
Server::Server(World* world, EventBroker* eventBroker, int port)
|
||||
: Network(world, eventBroker)
|
||||
{
|
||||
Network::initialize();
|
||||
ConfigFile* config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||
snapshotInterval = 1000 * config->Get<float>("Networking.SnapshotInterval", 0.05f);
|
||||
pingIntervalMs = config->Get<float>("Networking.PingIntervalMs", 1000);
|
||||
|
||||
}
|
||||
|
||||
Server::~Server()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Server::Start(World* world, EventBroker* eventBroker)
|
||||
{
|
||||
m_World = world;
|
||||
m_EventBroker = eventBroker;
|
||||
// Subscribe to events
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Server::OnInputCommand);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &Server::OnPlayerSpawned);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EEntityDeleted, &Server::OnEntityDeleted);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EComponentDeleted, &Server::OnComponentDeleted);
|
||||
LOG_INFO("I am Server. BIP BOP\n");
|
||||
|
||||
// Bind
|
||||
if (port == 0) {
|
||||
port = config->Get<float>("Networking.Port", 27666);
|
||||
}
|
||||
m_Port = port;
|
||||
m_Socket = std::make_unique<boost::asio::ip::udp::socket>(m_IOService, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), port));
|
||||
LOG_INFO("Server initialized and bound to port %i", port);
|
||||
}
|
||||
|
||||
Server::~Server()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Server::Update()
|
||||
@@ -38,7 +39,7 @@ void Server::Update()
|
||||
|
||||
void Server::readFromClients()
|
||||
{
|
||||
while (m_Socket.available()) {
|
||||
while (m_Socket->available()) {
|
||||
try {
|
||||
bytesRead = receive(readBuffer);
|
||||
Packet packet(readBuffer, bytesRead);
|
||||
@@ -105,7 +106,7 @@ void Server::parseMessageType(Packet& packet)
|
||||
|
||||
size_t Server::receive(char * data)
|
||||
{
|
||||
size_t length = m_Socket.receive_from(
|
||||
size_t length = m_Socket->receive_from(
|
||||
boost::asio::buffer((void*)data
|
||||
, INPUTSIZE)
|
||||
, m_ReceiverEndpoint, 0);
|
||||
@@ -121,7 +122,7 @@ size_t Server::receive(char * data)
|
||||
void Server::send(PlayerID player, Packet& packet)
|
||||
{
|
||||
try {
|
||||
size_t bytesSent = m_Socket.send_to(
|
||||
size_t bytesSent = m_Socket->send_to(
|
||||
boost::asio::buffer(packet.Data(), packet.Size()),
|
||||
m_ConnectedPlayers[player].Endpoint,
|
||||
0);
|
||||
@@ -139,7 +140,7 @@ void Server::send(PlayerID player, Packet& packet)
|
||||
|
||||
void Server::send(Packet & packet)
|
||||
{
|
||||
m_Socket.send_to(
|
||||
m_Socket->send_to(
|
||||
boost::asio::buffer(
|
||||
packet.Data(),
|
||||
packet.Size()),
|
||||
@@ -164,10 +165,24 @@ void Server::broadcast(Packet& packet)
|
||||
void Server::sendSnapshot()
|
||||
{
|
||||
Packet packet(MessageType::Snapshot);
|
||||
addInputCommandsToPacket(packet);
|
||||
addChildrenToPacket(packet, EntityID_Invalid);
|
||||
broadcast(packet);
|
||||
}
|
||||
|
||||
void Server::addInputCommandsToPacket(Packet& packet)
|
||||
{
|
||||
// Number of input commands
|
||||
packet.WritePrimitive(m_InputCommandsToBroadcast.size());
|
||||
for (auto& command : m_InputCommandsToBroadcast) {
|
||||
packet.WritePrimitive(command.PlayerID);
|
||||
packet.WritePrimitive(m_ConnectedPlayers.at(command.PlayerID).EntityID);
|
||||
packet.WriteString(command.Command);
|
||||
packet.WritePrimitive(command.Value);
|
||||
}
|
||||
m_InputCommandsToBroadcast.clear();
|
||||
}
|
||||
|
||||
void Server::addChildrenToPacket(Packet & packet, EntityID entityID)
|
||||
{
|
||||
auto itPair = m_World->GetChildren(entityID);
|
||||
@@ -239,8 +254,8 @@ void Server::checkForTimeOuts()
|
||||
double stopPing = 1000 * m_ConnectedPlayers[i].StopTime /
|
||||
static_cast<double>(CLOCKS_PER_SEC);
|
||||
if (startPing > stopPing + m_TimeoutMs) {
|
||||
LOG_INFO("User %i timed out!", i);
|
||||
disconnect(i);
|
||||
//LOG_INFO("User %i timed out!", i);
|
||||
//disconnect(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -272,6 +287,10 @@ void Server::parseOnInputCommand(Packet& packet)
|
||||
e.Player = EntityWrapper(m_World, m_ConnectedPlayers.at(player).EntityID);
|
||||
e.Value = packet.ReadPrimitive<float>();
|
||||
m_EventBroker->Publish(e);
|
||||
|
||||
if (e.Command == "PrimaryFire") {
|
||||
m_InputCommandsToBroadcast.push_back(e);
|
||||
}
|
||||
//LOG_INFO("Server::parseOnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,10 @@
|
||||
#include "Collision/Collision.h"
|
||||
#include "Core/Frustum.h"
|
||||
|
||||
RenderSystem::RenderSystem(World* world, EventBroker* eventBroker, const IRenderer* renderer, RenderFrame* renderFrame, Octree<EntityAABB>* frustumCullOctree)
|
||||
: System(world, eventBroker)
|
||||
RenderSystem::RenderSystem(SystemParams params, const IRenderer* renderer, RenderFrame* renderFrame, Octree<EntityAABB>* frustumCullOctree)
|
||||
: System(params)
|
||||
, m_Renderer(renderer)
|
||||
, m_RenderFrame(renderFrame)
|
||||
, m_World(world)
|
||||
, m_Octree(frustumCullOctree)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &RenderSystem::OnSetCamera);
|
||||
@@ -67,7 +66,7 @@ void RenderSystem::fillModels(RenderScene::Queues &Jobs)
|
||||
}
|
||||
|
||||
// Hide things parented to local player if they have the HiddenFromLocalPlayer component
|
||||
if (entity.HasComponent("HiddenForLocalPlayer") && (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer))) {
|
||||
if ((entity.HasComponent("HiddenForLocalPlayer") || entity.FirstParentWithComponent("HiddenForLocalPlayer").Valid()) && (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ void Renderer::InitializeWindow()
|
||||
ss << " DEBUG";
|
||||
#endif
|
||||
LOG_INFO(ss.str().c_str());
|
||||
glfwSetWindowTitle(m_Window, ss.str().c_str());
|
||||
SetWindowTitle(ss.str());
|
||||
|
||||
// Initialize GLEW
|
||||
if (glewInit() != GLEW_OK) {
|
||||
|
||||
@@ -105,7 +105,6 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector<Animation
|
||||
|
||||
|
||||
if (progress > 1.0f || progress < 0.0f) {
|
||||
LOG_INFO("Progress: %f", progress);
|
||||
progress = glm::clamp(progress, 0.0f, 1.0f);
|
||||
}
|
||||
Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties;
|
||||
@@ -182,7 +181,6 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector<Animation
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (offset != glm::mat4(1)) {
|
||||
boneMatrix = parentMatrix * ((glm::translate(finalPosInterp) * glm::toMat4(finalRotInterp) * glm::scale(finalScaleInterp)) + offset);
|
||||
} else {
|
||||
@@ -235,9 +233,7 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, std::vector<Animation
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (progress > 1.0f || progress < 0.0f) {
|
||||
LOG_INFO("Progress: %f", progress);
|
||||
progress = glm::clamp(progress, 0.0f, 1.0f);
|
||||
}
|
||||
Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties;
|
||||
@@ -356,9 +352,7 @@ glm::mat4 Skeleton::GetOffsetTransform(const Bone* bone, AnimationOffset animati
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (progress > 1.0f || progress < 0.0f) {
|
||||
LOG_INFO("Progress: %f", progress);
|
||||
progress = glm::clamp(progress, 0.0f, 1.0f);
|
||||
}
|
||||
Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
project(TacticalZ-Game)
|
||||
|
||||
find_package(Boost REQUIRED COMPONENTS system filesystem thread chrono)
|
||||
find_package(Boost REQUIRED COMPONENTS system filesystem thread chrono program_options)
|
||||
|
||||
set(INCLUDE_PATH ${CMAKE_SOURCE_DIR}/include/Game)
|
||||
include_directories(
|
||||
@@ -22,13 +22,17 @@ file(GLOB SOURCE_FILES_Events
|
||||
)
|
||||
source_group(Events FILES ${SOURCE_FILES_Events})
|
||||
|
||||
file(GLOB SOURCE_FILES_Network
|
||||
"${INCLUDE_PATH}/Network/*.h"
|
||||
"Network/*.cpp"
|
||||
)
|
||||
source_group(Network FILES ${SOURCE_FILES_Network})
|
||||
set(SOURCE_FILES
|
||||
${SOURCE_FILES}
|
||||
"Game.cpp"
|
||||
${SOURCE_FILES_Systems}
|
||||
${SOURCE_FILES_Events}
|
||||
|
||||
|
||||
${SOURCE_FILES_Network}
|
||||
)
|
||||
|
||||
set(LIBRARIES
|
||||
|
||||
+66
-34
@@ -15,12 +15,16 @@
|
||||
#include "Game/Systems/PickupSpawnSystem.h"
|
||||
#include "Game/Systems/WeaponSystem.h"
|
||||
#include "Rendering/AnimationSystem.h"
|
||||
#include "Game/Systems/PlayerHUDSystem.h"
|
||||
#include "Rendering/BoneAttachmentSystem.h"
|
||||
#include "Game/Systems/PlayerHUD.h"
|
||||
#include "Game/Systems/LifetimeSystem.h"
|
||||
#include "Rendering/AnimationSystem.h"
|
||||
#include "Network/MultiplayerSnapshotFilter.h"
|
||||
|
||||
Game::Game(int argc, char* argv[])
|
||||
{
|
||||
parseArgs(argc, argv);
|
||||
|
||||
ResourceManager::RegisterType<ConfigFile>("ConfigFile");
|
||||
ResourceManager::RegisterType<Sound>("Sound");
|
||||
ResourceManager::RegisterType<Model>("Model");
|
||||
@@ -78,6 +82,18 @@ Game::Game(int argc, char* argv[])
|
||||
// Create the sound manager
|
||||
m_SoundManager = new SoundManager(m_World, m_EventBroker);
|
||||
|
||||
// Initialize network
|
||||
if (m_Config->Get<bool>("Networking.StartNetwork", false)) {
|
||||
if (m_IsServer) {
|
||||
m_NetworkServer = new Server(m_World, m_EventBroker, m_NetworkPort);
|
||||
m_Renderer->SetWindowTitle(m_Renderer->WindowTitle() + " SERVER");
|
||||
} else if (m_IsClient) {
|
||||
m_NetworkClient = new Client(m_World, m_EventBroker, std::make_unique<MultiplayerSnapshotFilter>(m_EventBroker));
|
||||
m_NetworkClient->Connect(m_NetworkAddress, m_NetworkPort);
|
||||
m_Renderer->SetWindowTitle(m_Renderer->WindowTitle() + " CLIENT");
|
||||
}
|
||||
}
|
||||
|
||||
// Create Octrees
|
||||
// TODO: Perhaps the world bounds should be set in some non-arbitrary way instead of this.
|
||||
AABB boxContainingTheWorld(glm::vec3(-300), glm::vec3(300));
|
||||
@@ -85,20 +101,21 @@ Game::Game(int argc, char* argv[])
|
||||
m_OctreeTrigger = new Octree<EntityAABB>(boxContainingTheWorld, 4);
|
||||
m_OctreeFrustrumCulling = new Octree<EntityAABB>(boxContainingTheWorld, 4);
|
||||
// Create system pipeline
|
||||
m_SystemPipeline = new SystemPipeline(m_World, m_EventBroker);
|
||||
m_SystemPipeline = new SystemPipeline(m_World, m_EventBroker, m_IsClient, m_IsServer);
|
||||
|
||||
// All systems with orderlevel 0 will be updated first.
|
||||
unsigned int updateOrderLevel = 0;
|
||||
m_SystemPipeline->AddSystem<InterpolationSystem>(updateOrderLevel);
|
||||
++updateOrderLevel;
|
||||
m_SystemPipeline->AddSystem<SoundSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<RaptorCopterSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<ExplosionEffectSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<HealthSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<PlayerMovementSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<InterpolationSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<SpawnerSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<PlayerSpawnSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<PlayerDeathSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<WeaponSystem>(updateOrderLevel, m_Renderer);
|
||||
m_SystemPipeline->AddSystem<WeaponSystem>(updateOrderLevel, m_Renderer, m_OctreeCollision);
|
||||
m_SystemPipeline->AddSystem<LifetimeSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<CapturePointSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<PickupSpawnSystem>(updateOrderLevel);
|
||||
@@ -107,9 +124,8 @@ Game::Game(int argc, char* argv[])
|
||||
m_SystemPipeline->AddSystem<FillOctreeSystem>(updateOrderLevel, m_OctreeCollision, "Collidable");
|
||||
m_SystemPipeline->AddSystem<FillOctreeSystem>(updateOrderLevel, m_OctreeTrigger, "Player");
|
||||
m_SystemPipeline->AddSystem<FillFrustumOctreeSystem>(updateOrderLevel, m_OctreeFrustrumCulling);
|
||||
m_SystemPipeline->AddSystem<PlayerHUD>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<AnimationSystem>(updateOrderLevel);
|
||||
|
||||
m_SystemPipeline->AddSystem<PlayerHUDSystem>(updateOrderLevel);
|
||||
// Collision and TriggerSystem should update after player.
|
||||
++updateOrderLevel;
|
||||
m_SystemPipeline->AddSystem<BoneAttachmentSystem>(updateOrderLevel);
|
||||
@@ -120,12 +136,6 @@ Game::Game(int argc, char* argv[])
|
||||
++updateOrderLevel;
|
||||
m_SystemPipeline->AddSystem<EditorSystem>(updateOrderLevel, m_Renderer, m_RenderFrame);
|
||||
|
||||
// Invoke network
|
||||
if (m_Config->Get<bool>("Networking.StartNetwork", false)) {
|
||||
//boost::thread workerThread(&Game::networkFunction, this);
|
||||
networkFunction();
|
||||
}
|
||||
|
||||
m_LastTime = glfwGetTime();
|
||||
}
|
||||
|
||||
@@ -136,6 +146,12 @@ Game::~Game()
|
||||
delete m_OctreeCollision;
|
||||
delete m_OctreeTrigger;
|
||||
delete m_SoundManager;
|
||||
if (m_NetworkClient != nullptr) {
|
||||
delete m_NetworkClient;
|
||||
}
|
||||
if (m_NetworkServer != nullptr) {
|
||||
delete m_NetworkServer;
|
||||
}
|
||||
delete m_World;
|
||||
delete m_FrameStack;
|
||||
delete m_InputProxy;
|
||||
@@ -166,40 +182,56 @@ void Game::Tick()
|
||||
m_SoundManager->Update(dt);
|
||||
|
||||
// Update network
|
||||
if (m_IsClientOrServer) {
|
||||
m_ClientOrServer->Update();
|
||||
m_EventBroker->Process<MultiplayerSnapshotFilter>();
|
||||
if (m_NetworkClient != nullptr) {
|
||||
m_NetworkClient->Update();
|
||||
}
|
||||
if (m_NetworkServer != nullptr) {
|
||||
m_NetworkServer->Update();
|
||||
}
|
||||
//m_SoundManager->Update(dt);
|
||||
|
||||
// Iterate through systems and update world!
|
||||
m_EventBroker->Process<SystemPipeline>();
|
||||
m_SystemPipeline->Update(dt);
|
||||
debugTick(dt);
|
||||
m_Renderer->Update(dt);
|
||||
GLERROR("Game::Tick m_RenderQueueFactory->Update");
|
||||
m_Renderer->Draw(*m_RenderFrame);
|
||||
m_RenderFrame->Clear();
|
||||
GLERROR("Game::Tick m_Renderer->Draw");
|
||||
m_EventBroker->Swap();
|
||||
m_EventBroker->Clear();
|
||||
}
|
||||
|
||||
void Game::debugTick(double dt)
|
||||
int Game::parseArgs(int argc, char* argv[])
|
||||
{
|
||||
m_EventBroker->Process<Game>();
|
||||
namespace po = boost::program_options;
|
||||
|
||||
po::options_description desc("Options");
|
||||
desc.add_options()
|
||||
("help", "Help")
|
||||
("server,s", po::bool_switch(&m_IsServer), "Launch game in server mode")
|
||||
("connect", po::value<std::string>(&m_NetworkAddress)->default_value(""), "Connect to this address in client mode")
|
||||
("port,p", po::value<int>(&m_NetworkPort), "Port to listen on or connect to");
|
||||
;
|
||||
|
||||
po::variables_map vm;
|
||||
try {
|
||||
po::store(po::parse_command_line(argc, argv, desc), vm);
|
||||
po::notify(vm);
|
||||
} catch (std::exception& e) {
|
||||
LOG_ERROR(e.what());
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (vm.count("help")) {
|
||||
std::cout << desc << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// HACK: Right now, client and server are mutually exclusive
|
||||
m_IsClient = true;
|
||||
if (m_IsServer) {
|
||||
m_IsClient = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Game::networkFunction()
|
||||
{
|
||||
bool isServer = m_Config->Get<bool>("Networking.IsServer", false);
|
||||
if (!isServer) {
|
||||
m_IsClientOrServer = true;
|
||||
m_ClientOrServer = new Client(m_Config);
|
||||
}
|
||||
if (isServer) {
|
||||
m_IsClientOrServer = true;
|
||||
m_ClientOrServer = new Server();
|
||||
}
|
||||
m_ClientOrServer->Start(m_World, m_EventBroker);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#include "Network/MultiplayerSnapshotFilter.h"
|
||||
|
||||
MultiplayerSnapshotFilter::MultiplayerSnapshotFilter(EventBroker* eventBroker)
|
||||
: m_EventBroker(eventBroker)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &MultiplayerSnapshotFilter::OnPlayerSpawned);
|
||||
}
|
||||
|
||||
bool MultiplayerSnapshotFilter::FilterComponent(EntityWrapper entity, SharedComponentWrapper& component)
|
||||
{
|
||||
if (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (component.Info.Name == "Physics") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (component.Info.Name == "Transform" || component.Info.Name == "Physics") {
|
||||
m_EventBroker->Publish(Events::Interpolate(entity, component));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MultiplayerSnapshotFilter::OnPlayerSpawned(Events::PlayerSpawned ePlayerSpawned)
|
||||
{
|
||||
if (ePlayerSpawned.PlayerID == -1) {
|
||||
m_LocalPlayer = ePlayerSpawned.Player;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "Systems/CapturePointSystem.h"
|
||||
#include <algorithm>
|
||||
|
||||
CapturePointSystem::CapturePointSystem(World* world, EventBroker* eventBroker)
|
||||
: System(world, eventBroker)
|
||||
CapturePointSystem::CapturePointSystem(SystemParams params)
|
||||
: System(params)
|
||||
, PureSystem("CapturePoint")
|
||||
{
|
||||
//subscribe/listenTo playerdamage,healthpickup events (using the eventBroker)
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "Systems/ExplosionEffectSystem.h"
|
||||
|
||||
void ExplosionEffectSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
|
||||
{
|
||||
if ((double)component["TimeSinceDeath"] > (double)component["ExplosionDuration"]) {
|
||||
(double)component["TimeSinceDeath"] = 0.f;
|
||||
}
|
||||
(double&)component["TimeSinceDeath"] += dt;
|
||||
|
||||
//if ((bool)Component["Gravity"] == true) {
|
||||
// (bool)Component["ExponentialAccelaration"] = false;
|
||||
//}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "Systems/HealthSystem.h"
|
||||
|
||||
HealthSystem::HealthSystem(World* m_World, EventBroker* eventBroker)
|
||||
: System(m_World, eventBroker)
|
||||
HealthSystem::HealthSystem(SystemParams params)
|
||||
: System(params)
|
||||
, PureSystem("Health")
|
||||
{
|
||||
//subscribe/listenTo playerdamage,healthpickup events (using the eventBroker)
|
||||
|
||||
@@ -1,84 +1,98 @@
|
||||
#include "Systems/InterpolationSystem.h"
|
||||
|
||||
InterpolationSystem::InterpolationSystem(World* world, EventBroker* eventBroker)
|
||||
: System(world, eventBroker)
|
||||
, PureSystem("Transform")
|
||||
InterpolationSystem::InterpolationSystem(SystemParams params)
|
||||
: System(params)
|
||||
{
|
||||
ConfigFile* config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||
m_SnapshotInterval = config->Get<float>("Networking.SnapshotInterval", 0.05f);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EInterpolate, &InterpolationSystem::OnInterpolate);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &InterpolationSystem::OnPlayerSpawned);
|
||||
}
|
||||
|
||||
void InterpolationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& transform, double dt)
|
||||
void InterpolationSystem::Update(double dt)
|
||||
{
|
||||
// Don't interpolate entities that might already have been removed
|
||||
if (!entity.Valid()) {
|
||||
return;
|
||||
// Position
|
||||
for (auto& kv : m_InterpolatePosition) {
|
||||
EntityWrapper entity = kv.first;
|
||||
if (!entity.Valid()) {
|
||||
continue;
|
||||
}
|
||||
auto& iPosition = kv.second;
|
||||
glm::vec3& position = iPosition.Component[iPosition.Field];
|
||||
|
||||
iPosition.Alpha += dt;
|
||||
float alpha = glm::min(iPosition.Alpha / m_SnapshotInterval, 1.0);
|
||||
position = iPosition.Start + ((iPosition.Goal - iPosition.Start) * alpha);
|
||||
}
|
||||
|
||||
if (m_NextTransform.find(transform.EntityID) != m_NextTransform.end()) { // Exists in map
|
||||
m_NextTransform[transform.EntityID].interpolationTime += static_cast<float>(dt);
|
||||
Transform sTransform = m_NextTransform[transform.EntityID];
|
||||
float time = sTransform.interpolationTime;
|
||||
if (time > m_SnapshotInterval) {
|
||||
if (m_LastReceivedTransform.find(transform.EntityID) != m_LastReceivedTransform.end()) {
|
||||
m_NextTransform[transform.EntityID] = m_LastReceivedTransform[transform.EntityID];
|
||||
m_NextTransform[transform.EntityID].interpolationTime = time - m_SnapshotInterval;
|
||||
sTransform = m_NextTransform[transform.EntityID];
|
||||
m_LastReceivedTransform.erase(transform.EntityID);
|
||||
} else {
|
||||
m_NextTransform.erase(transform.EntityID);
|
||||
}
|
||||
// Orientation
|
||||
for (auto& kv : m_InterpolateOrientation) {
|
||||
EntityWrapper entity = kv.first;
|
||||
if (!entity.Valid()) {
|
||||
continue;
|
||||
}
|
||||
if (transform.Info.Name == "Transform") {
|
||||
bool isLocalPlayer = entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer);
|
||||
// Position
|
||||
glm::vec3 nextPosition = sTransform.Position;
|
||||
glm::vec3 currentPosition = static_cast<glm::vec3>(transform["Position"]);
|
||||
// HACK: Don't force position for players
|
||||
if (!isLocalPlayer) {
|
||||
(glm::vec3&)transform["Position"] += vectorInterpolation<glm::vec3>(currentPosition, nextPosition, sTransform.interpolationTime);
|
||||
}
|
||||
// Orientation
|
||||
// Don't force orientation for players
|
||||
if (!isLocalPlayer) {
|
||||
glm::quat nextOrientation = sTransform.Orientation;
|
||||
glm::quat currentOrientation = glm::quat(static_cast<glm::vec3>(transform["Orientation"]));
|
||||
(glm::vec3&)transform["Orientation"] = glm::eulerAngles(glm::slerp<float>(currentOrientation, nextOrientation, sTransform.interpolationTime / m_SnapshotInterval));
|
||||
}
|
||||
// Scale
|
||||
glm::vec3 nextScale = sTransform.Scale;
|
||||
glm::vec3 currentScale = static_cast<glm::vec3>(transform["Scale"]);
|
||||
(glm::vec3&)transform["Scale"] += vectorInterpolation<glm::vec3>(currentScale, nextScale, sTransform.interpolationTime);
|
||||
auto& iOrientation = kv.second;
|
||||
glm::vec3& orientation = iOrientation.Component[iOrientation.Field];
|
||||
|
||||
iOrientation.Alpha += dt / m_SnapshotInterval;
|
||||
iOrientation.Alpha = glm::min(iOrientation.Alpha, 1.0);
|
||||
orientation = glm::eulerAngles(glm::slerp(iOrientation.Start, iOrientation.Goal, (float)iOrientation.Alpha));
|
||||
}
|
||||
|
||||
// Velocity
|
||||
for (auto& kv : m_InterpolateVelocity) {
|
||||
EntityWrapper entity = kv.first;
|
||||
if (!entity.Valid()) {
|
||||
continue;
|
||||
}
|
||||
auto& iVelocity = kv.second;
|
||||
glm::vec3& position = iVelocity.Component[iVelocity.Field];
|
||||
|
||||
iVelocity.Alpha += dt;
|
||||
float alpha = glm::min(iVelocity.Alpha / m_SnapshotInterval, 1.0);
|
||||
position = iVelocity.Start + ((iVelocity.Goal - iVelocity.Start) * alpha);
|
||||
}
|
||||
}
|
||||
|
||||
bool InterpolationSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
|
||||
bool InterpolationSystem::OnInterpolate(Events::Interpolate& e)
|
||||
{
|
||||
m_LocalPlayer = e.Player;
|
||||
if (e.Component.Info.Name == "Transform") {
|
||||
auto cTransform = e.Entity["Transform"];
|
||||
|
||||
// Position
|
||||
Interpolation<glm::vec3> iPosition(
|
||||
cTransform,
|
||||
"Position",
|
||||
cTransform["Position"],
|
||||
e.Component["Position"]
|
||||
);
|
||||
m_InterpolatePosition.erase(e.Entity);
|
||||
m_InterpolatePosition.insert(std::make_pair(e.Entity, iPosition));
|
||||
|
||||
// Orientation
|
||||
Interpolation<glm::quat> iOrientation(
|
||||
cTransform,
|
||||
"Orientation",
|
||||
glm::quat((glm::vec3&)cTransform["Orientation"]),
|
||||
glm::quat((glm::vec3&)e.Component["Orientation"])
|
||||
);
|
||||
m_InterpolateOrientation.erase(e.Entity);
|
||||
m_InterpolateOrientation.insert(std::make_pair(e.Entity, iOrientation));
|
||||
} else if (e.Component.Info.Name == "Physics") {
|
||||
auto cPhysics = e.Entity["Physics"];
|
||||
if (!e.Entity.HasComponent("Player")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Velocity
|
||||
Interpolation<glm::vec3> iVelocity(
|
||||
cPhysics,
|
||||
"Velocity",
|
||||
cPhysics["Velocity"],
|
||||
e.Component["Velocity"]
|
||||
);
|
||||
m_InterpolateVelocity.erase(e.Entity);
|
||||
m_InterpolateVelocity.insert(std::make_pair(e.Entity, iVelocity));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InterpolationSystem::OnInterpolate(const Events::Interpolate & e)
|
||||
{
|
||||
Transform transform;
|
||||
int offset = 0;
|
||||
// Read the data
|
||||
memcpy(&transform.Position, e.DataArray.get() + offset, sizeof(glm::vec3));
|
||||
offset += sizeof(glm::vec3);
|
||||
glm::vec3 tempOrientation;
|
||||
memcpy(&tempOrientation, e.DataArray.get() + offset, sizeof(glm::vec3));
|
||||
transform.Orientation = glm::quat(tempOrientation);
|
||||
offset += sizeof(glm::vec3);
|
||||
memcpy(&transform.Scale, e.DataArray.get() + offset, sizeof(glm::vec3));
|
||||
transform.interpolationTime = 0.0f;
|
||||
|
||||
if (m_NextTransform.find(e.Entity) != m_NextTransform.end()) { // Did exist
|
||||
m_LastReceivedTransform[e.Entity] = transform;
|
||||
} else { // Did not
|
||||
m_NextTransform[e.Entity] = transform;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "Systems/PickupSpawnSystem.h"
|
||||
|
||||
PickupSpawnSystem::PickupSpawnSystem(World* m_World, EventBroker* eventBroker)
|
||||
: System(m_World, eventBroker)
|
||||
PickupSpawnSystem::PickupSpawnSystem(SystemParams params)
|
||||
: System(params)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_ETriggerTouch, &PickupSpawnSystem::OnTriggerTouch);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "Systems/PlayerDeathSystem.h"
|
||||
|
||||
PlayerDeathSystem::PlayerDeathSystem(World* m_World, EventBroker* eventBroker)
|
||||
: System(m_World, eventBroker)
|
||||
PlayerDeathSystem::PlayerDeathSystem(SystemParams params)
|
||||
: System(params)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_OnPlayerDeath, &PlayerDeathSystem::OnPlayerDeath);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,6 @@
|
||||
#include "Game/Systems/PlayerHUD.h"
|
||||
#include "Game/Systems/PlayerHUDSystem.h"
|
||||
|
||||
PlayerHUD::PlayerHUD(World* world, EventBroker* eventBrokerer)
|
||||
:System(world, eventBrokerer)
|
||||
, m_World(world)
|
||||
, m_EventBroker(eventBrokerer)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
PlayerHUD::~PlayerHUD()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
void PlayerHUD::Update(double dt)
|
||||
void PlayerHUDSystem::Update(double dt)
|
||||
{
|
||||
auto healthHUDs = m_World->GetComponents("HealthHUD");
|
||||
if (healthHUDs == nullptr) {
|
||||
@@ -1,8 +1,7 @@
|
||||
#include "Systems/PlayerMovementSystem.h"
|
||||
|
||||
PlayerMovementSystem::PlayerMovementSystem(World* world, EventBroker* eventBroker)
|
||||
: System(world, eventBroker)
|
||||
, PureSystem("Player")
|
||||
PlayerMovementSystem::PlayerMovementSystem(SystemParams params)
|
||||
: System(params)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &PlayerMovementSystem::OnPlayerSpawned);
|
||||
}
|
||||
@@ -15,6 +14,12 @@ PlayerMovementSystem::~PlayerMovementSystem()
|
||||
}
|
||||
|
||||
void PlayerMovementSystem::Update(double dt)
|
||||
{
|
||||
updateMovementControllers(dt);
|
||||
updateVelocity(dt);
|
||||
}
|
||||
|
||||
void PlayerMovementSystem::updateMovementControllers(double dt)
|
||||
{
|
||||
for (auto& kv : m_PlayerInputControllers) {
|
||||
EntityWrapper player = kv.first;
|
||||
@@ -24,12 +29,20 @@ void PlayerMovementSystem::Update(double dt)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Aim pitch
|
||||
EntityWrapper cameraEntity = player.FirstChildByName("Camera");
|
||||
if (cameraEntity.Valid()) {
|
||||
glm::vec3& cameraOrientation = cameraEntity["Transform"]["Orientation"];
|
||||
cameraOrientation.x += controller->Rotation().x;
|
||||
// Limit camera pitch so we don't break our necks
|
||||
cameraOrientation.x = glm::clamp(cameraOrientation.x, -glm::half_pi<float>(), glm::half_pi<float>());
|
||||
// Set third person model aim pitch
|
||||
EntityWrapper playerModel = player.FirstChildByName("PlayerModel");
|
||||
if (playerModel.Valid()) {
|
||||
ComponentWrapper cAnimationOffset = playerModel["AnimationOffset"];
|
||||
double time = (cameraOrientation.x + glm::half_pi<float>()) / glm::pi<float>();
|
||||
cAnimationOffset["Time"] = time;
|
||||
}
|
||||
}
|
||||
|
||||
ComponentWrapper& cTransform = player["Transform"];
|
||||
@@ -119,24 +132,74 @@ void PlayerMovementSystem::Update(double dt)
|
||||
EntityWrapper playerModel = player.FirstChildByName("PlayerModel");
|
||||
if (playerModel.Valid()) {
|
||||
ComponentWrapper cAnimation = playerModel["Animation"];
|
||||
std::string& animationName1 = cAnimation["AnimationName1"];
|
||||
std::string& animationName2 = cAnimation["AnimationName2"];
|
||||
double& animationTime1 = cAnimation["Time1"];
|
||||
double& animationTime2 = cAnimation["Time2"];
|
||||
double& animationSpeed1 = cAnimation["Speed1"];
|
||||
double& animationSpeed2 = cAnimation["Speed2"];
|
||||
double& animationWeight1 = cAnimation["Weight1"];
|
||||
double& animationWeight2 = cAnimation["Weight2"];
|
||||
|
||||
float movementLength = glm::length(groundVelocity);
|
||||
//TODO: add assault dash animation here
|
||||
if (glm::length(controller->Movement()) > 0.f) {
|
||||
if (controller->Crouching()) {
|
||||
cAnimation["AnimationName1"] = "Crouch Walk";
|
||||
(double&)cAnimation["Speed1"] = 1.f * -glm::sign(controller->Movement().z);
|
||||
double forwardMovement = controller->Movement().z;
|
||||
double strafeMovement = controller->Movement().x;
|
||||
|
||||
if (controller->Crouching() && animationName1 != "CrouchWalk") {
|
||||
animationName1 = "CrouchWalk";
|
||||
animationSpeed1 = 1.0 * -glm::sign(controller->Movement().z);
|
||||
} else {
|
||||
cAnimation["AnimationName1"] = "Run";
|
||||
(double&)cAnimation["Speed1"] = 2.f * -glm::sign(controller->Movement().z);
|
||||
if (glm::abs(forwardMovement) > 0) {
|
||||
if (animationName1 != "Run") {
|
||||
animationName1 = "Run";
|
||||
if (animationName2 == "StrafeLeft" || animationName2 == "StrafeRight") {
|
||||
animationTime1 = animationTime2;
|
||||
} else {
|
||||
animationTime1 = 0.0;
|
||||
}
|
||||
}
|
||||
animationSpeed1 = 2.f * -glm::sign(forwardMovement);
|
||||
}
|
||||
|
||||
if (glm::abs(strafeMovement) > 0) {
|
||||
if (animationName2 != "StrafeLeft" && animationName2 != "StrafeRight") {
|
||||
if (strafeMovement < 0) {
|
||||
animationName2 = "StrafeLeft";
|
||||
}
|
||||
if (strafeMovement > 0) {
|
||||
animationName2 = "StrafeRight";
|
||||
}
|
||||
if (animationName1 == "Run") {
|
||||
animationTime2 = animationTime1;
|
||||
} else {
|
||||
animationTime2 = 0.0;
|
||||
}
|
||||
}
|
||||
animationSpeed2 = 2.f * glm::abs(strafeMovement);
|
||||
}
|
||||
|
||||
double strafeWeight = glm::abs(strafeMovement) / (glm::abs(forwardMovement) + glm::abs(strafeMovement));
|
||||
animationWeight2 = strafeWeight;
|
||||
animationWeight1 = 1.0 - strafeWeight;
|
||||
}
|
||||
} else {
|
||||
if (controller->Crouching()) {
|
||||
cAnimation["AnimationName1"] = "Crouch";
|
||||
(double&)cAnimation["Speed"] = 1.f;
|
||||
animationName1 = "Crouch";
|
||||
animationName2 = "";
|
||||
animationSpeed1 = 1.0;
|
||||
animationSpeed2 = 0.0;
|
||||
animationWeight1 = 1.0;
|
||||
animationWeight2 = 0.0;
|
||||
} else {
|
||||
cAnimation["AnimationName1"] = "Hold Pos";
|
||||
(double&)cAnimation["Speed1"] = 1.f;
|
||||
animationName1 = "Idle";
|
||||
animationName2 = "";
|
||||
animationSpeed1 = 1.f;
|
||||
animationSpeed2 = 0.0;
|
||||
animationWeight1 = 1.0;
|
||||
animationWeight2 = 0.0;
|
||||
//cAnimation["AnimationName2"] = "Idle";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,14 +210,16 @@ void PlayerMovementSystem::Update(double dt)
|
||||
playerStep(dt);
|
||||
}
|
||||
|
||||
void PlayerMovementSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
|
||||
|
||||
void PlayerMovementSystem::updateVelocity(double dt)
|
||||
{
|
||||
ComponentWrapper& cTransform = entity["Transform"];
|
||||
if (!entity.HasComponent("Physics")) {
|
||||
// Only apply velocity to local player
|
||||
if (!LocalPlayer.Valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ComponentWrapper& cPhysics = entity["Physics"];
|
||||
ComponentWrapper& cTransform = LocalPlayer["Transform"];
|
||||
ComponentWrapper& cPhysics = LocalPlayer["Physics"];
|
||||
glm::vec3& velocity = cPhysics["Velocity"];
|
||||
bool isOnGround = (bool)cPhysics["IsOnGround"];
|
||||
|
||||
@@ -172,6 +237,7 @@ void PlayerMovementSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp
|
||||
velocity.z *= multiplier;
|
||||
}
|
||||
|
||||
// Gravity
|
||||
if (cPhysics["Gravity"]) {
|
||||
velocity.y -= 9.82f * (float)dt;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "Systems/PlayerSpawnSystem.h"
|
||||
|
||||
PlayerSpawnSystem::PlayerSpawnSystem(World* m_World, EventBroker* eventBroker)
|
||||
: System(m_World, eventBroker)
|
||||
PlayerSpawnSystem::PlayerSpawnSystem(SystemParams params)
|
||||
: System(params)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_OnInputCommand, &PlayerSpawnSystem::OnInputCommand);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_OnPlayerSpawnerd, &PlayerSpawnSystem::OnPlayerSpawned);
|
||||
@@ -71,6 +71,9 @@ bool PlayerSpawnSystem::OnInputCommand(const Events::InputCommand& e)
|
||||
bool PlayerSpawnSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
|
||||
{
|
||||
// When a player is actually spawned (since the actual spawning is handled on the server)
|
||||
if (!IsClient) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if a player already exists
|
||||
if (m_PlayerEntities.count(e.PlayerID) != 0) {
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
#include "Game/Systems/SoundSystem.h"
|
||||
|
||||
SoundSystem::SoundSystem(World* world, EventBroker* eventbroker)
|
||||
: System(world, eventbroker)
|
||||
SoundSystem::SoundSystem(SystemParams params)
|
||||
: System(params)
|
||||
, PureSystem("SoundEmitter")
|
||||
//, ImpureSystem()
|
||||
{
|
||||
ConfigFile* config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||
m_Announcer = ResourceManager::Load<ConfigFile>("Config.ini")->Get<std::string>("Sound.Announcer", "female");
|
||||
m_World = world;
|
||||
m_EventBroker = eventbroker;
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &SoundSystem::OnPlayerSpawned);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_InputCommand, &SoundSystem::OnInputCommand);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EDoubleJump, &SoundSystem::OnDoubleJump);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EDashAbility, &SoundSystem::OnDashAbility);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EShoot, &SoundSystem::OnShoot);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &SoundSystem::OnPlayerDamage);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_ECaptured, &SoundSystem::OnCaptured);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_ETriggerTouch, &SoundSystem::OnTriggerTouch);
|
||||
@@ -34,9 +30,8 @@ bool SoundSystem::OnPlayerSpawned(const Events::PlayerSpawned &e)
|
||||
{
|
||||
if (e.PlayerID == -1) { // Local player
|
||||
m_World->AttachComponent(e.Player.ID, "Listener");
|
||||
m_LocalPlayer = e.Player;
|
||||
Events::PlaySoundOnEntity go;
|
||||
go.EmitterID = m_LocalPlayer.ID;
|
||||
go.EmitterID = LocalPlayer.ID;
|
||||
go.FilePath = "Audio/announcer/" + m_Announcer + "/go.wav";
|
||||
m_EventBroker->Publish(go);
|
||||
// TEMP: starts bgm
|
||||
@@ -59,7 +54,7 @@ bool SoundSystem::OnInputCommand(const Events::InputCommand & e)
|
||||
}
|
||||
if (e.Command == "TakeDamage" && e.Value > 0) {
|
||||
Events::PlayerDamage ev;
|
||||
ev.Player = m_LocalPlayer;
|
||||
ev.Player = LocalPlayer;
|
||||
ev.Damage = 1.0;
|
||||
m_EventBroker->Publish(ev);
|
||||
}
|
||||
@@ -69,13 +64,14 @@ bool SoundSystem::OnInputCommand(const Events::InputCommand & e)
|
||||
|
||||
void SoundSystem::playerJumps()
|
||||
{
|
||||
if (!m_LocalPlayer.Valid()) {
|
||||
if (!LocalPlayer.Valid()) {
|
||||
return;
|
||||
}
|
||||
bool grounded = (bool)m_World->GetComponent(m_LocalPlayer.ID, "Physics")["IsOnGround"];
|
||||
|
||||
bool grounded = (bool)m_World->GetComponent(LocalPlayer.ID, "Physics")["IsOnGround"];
|
||||
if (grounded) {
|
||||
Events::PlaySoundOnEntity e;
|
||||
e.EmitterID = m_LocalPlayer.ID;
|
||||
e.EmitterID = LocalPlayer.ID;
|
||||
e.FilePath = "Audio/jump/jump1.wav";
|
||||
m_EventBroker->Publish(e);
|
||||
}
|
||||
@@ -92,26 +88,17 @@ bool SoundSystem::drumTimer(double dt)
|
||||
}
|
||||
}
|
||||
|
||||
bool SoundSystem::OnShoot(const Events::Shoot & e)
|
||||
{
|
||||
Events::PlaySoundOnEntity ev;
|
||||
ev.EmitterID = m_LocalPlayer.ID;
|
||||
ev.FilePath = "Audio/laser/laser1.wav";
|
||||
m_EventBroker->Publish(ev);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SoundSystem::OnCaptured(const Events::Captured & e)
|
||||
{
|
||||
int homeTeam = (int)m_World->GetComponent(e.CapturePointID, "Team")["Team"];
|
||||
int team = (int)m_World->GetComponent(m_LocalPlayer.ID, "Team")["Team"];
|
||||
int team = (int)m_World->GetComponent(LocalPlayer.ID, "Team")["Team"];
|
||||
Events::PlaySoundOnEntity ev;
|
||||
if (team == homeTeam) {
|
||||
ev.FilePath = "Audio/announcer/" + m_Announcer + "/objective_achieved.wav";
|
||||
} else {
|
||||
ev.FilePath = "Audio/announcer/" + m_Announcer + "/objective_failed.wav"; // have not been tested
|
||||
}
|
||||
ev.EmitterID = m_LocalPlayer.ID;
|
||||
ev.EmitterID = LocalPlayer.ID;
|
||||
m_EventBroker->Publish(ev);
|
||||
// Temp for play test.
|
||||
m_DrumsIsPlaying = false;
|
||||
@@ -133,7 +120,7 @@ bool SoundSystem::OnPlayerDamage(const Events::PlayerDamage & e)
|
||||
// paths.push_back("Audio/exhausted/breath.wav");
|
||||
// }
|
||||
Events::PlayQueueOnEntity ev;
|
||||
ev.Emitter = m_LocalPlayer;
|
||||
ev.Emitter = LocalPlayer;
|
||||
ev.FilePaths = paths;
|
||||
m_EventBroker->Publish(ev);
|
||||
return false;
|
||||
@@ -142,7 +129,7 @@ bool SoundSystem::OnPlayerDamage(const Events::PlayerDamage & e)
|
||||
bool SoundSystem::OnPlayerDeath(const Events::PlayerDeath & e)
|
||||
{
|
||||
Events::PlaySoundOnEntity ev;
|
||||
ev.EmitterID = m_LocalPlayer.ID;
|
||||
ev.EmitterID = LocalPlayer.ID;
|
||||
ev.FilePath = "Audio/die/die2.wav";
|
||||
m_EventBroker->Publish(ev);
|
||||
return false;
|
||||
@@ -151,7 +138,7 @@ bool SoundSystem::OnPlayerDeath(const Events::PlayerDeath & e)
|
||||
bool SoundSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup & e)
|
||||
{
|
||||
Events::PlaySoundOnEntity ev;
|
||||
ev.EmitterID = m_LocalPlayer.ID;
|
||||
ev.EmitterID = LocalPlayer.ID;
|
||||
ev.FilePath = "Audio/pickup/pickup2.wav";
|
||||
m_EventBroker->Publish(ev);
|
||||
return false;
|
||||
@@ -165,7 +152,7 @@ bool SoundSystem::OnTriggerTouch(const Events::TriggerTouch & e)
|
||||
}
|
||||
if (m_World->HasComponent(e.Trigger.ID, "CapturePoint")) {
|
||||
Events::PlaySoundOnEntity ev; // should be BGM
|
||||
ev.EmitterID = m_LocalPlayer.ID;
|
||||
ev.EmitterID = LocalPlayer.ID;
|
||||
ev.FilePath = "Audio/bgm/drumstest.wav";
|
||||
m_EventBroker->Publish(ev);
|
||||
// Temp for play test.
|
||||
@@ -177,7 +164,7 @@ bool SoundSystem::OnTriggerTouch(const Events::TriggerTouch & e)
|
||||
bool SoundSystem::OnDoubleJump(const Events::DoubleJump & e)
|
||||
{
|
||||
Events::PlaySoundOnEntity ev;
|
||||
ev.EmitterID = m_LocalPlayer.ID;
|
||||
ev.EmitterID = LocalPlayer.ID;
|
||||
ev.FilePath = "Audio/jump/jump2.wav";
|
||||
m_EventBroker->Publish(ev);
|
||||
return false;
|
||||
@@ -186,7 +173,7 @@ bool SoundSystem::OnDoubleJump(const Events::DoubleJump & e)
|
||||
bool SoundSystem::OnDashAbility(const Events::DashAbility &e)
|
||||
{
|
||||
Events::PlaySoundOnEntity ev;
|
||||
ev.EmitterID = m_LocalPlayer.ID;
|
||||
ev.EmitterID = LocalPlayer.ID;
|
||||
ev.FilePath = "Audio/jump/dash1.wav";
|
||||
m_EventBroker->Publish(ev);
|
||||
return false;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "Systems/SpawnerSystem.h"
|
||||
|
||||
SpawnerSystem::SpawnerSystem(World* world, EventBroker* eventBroker)
|
||||
: System(world, eventBroker)
|
||||
SpawnerSystem::SpawnerSystem(SystemParams params)
|
||||
: System(params)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_OnSpawnerSpawn, &SpawnerSystem::OnSpawnerSpawn);
|
||||
}
|
||||
@@ -51,7 +51,7 @@ EntityWrapper SpawnerSystem::Spawn(EntityWrapper spawner, EntityWrapper parent /
|
||||
// Set its position and orientation to that of the SpawnPoint
|
||||
spawnedEntity["Transform"]["Position"] = Transform::AbsolutePosition(spawnPoint.World, spawnPoint.ID);
|
||||
// TODO: Quaternions, bitch
|
||||
//spawnedEntity["Transform"]["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(spawnPoint.World, spawnPoint.ID));
|
||||
spawnedEntity["Transform"]["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(spawnPoint));
|
||||
|
||||
return spawnedEntity;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
#include "Systems/WeaponSystem.h"
|
||||
|
||||
WeaponSystem::WeaponSystem(World* world, EventBroker* eventBroker, IRenderer* renderer)
|
||||
: System(world, eventBroker)
|
||||
, ImpureSystem()
|
||||
WeaponSystem::WeaponSystem(SystemParams params, IRenderer* renderer, Octree<EntityAABB>* collisionOctree)
|
||||
: System(params)
|
||||
, PureSystem("Player")
|
||||
, m_SystemParams(params)
|
||||
, m_Renderer(renderer)
|
||||
, m_CollisionOctree(collisionOctree)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &WeaponSystem::OnPlayerSpawned);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &WeaponSystem::OnInputCommand);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EShoot, &WeaponSystem::OnShoot);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &WeaponSystem::OnPlayerSpawned);
|
||||
}
|
||||
|
||||
void WeaponSystem::Update(double dt)
|
||||
@@ -15,90 +17,84 @@ void WeaponSystem::Update(double dt)
|
||||
|
||||
}
|
||||
|
||||
bool WeaponSystem::OnPlayerSpawned(const Events::PlayerSpawned& e)
|
||||
void WeaponSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cPlayer, double dt)
|
||||
{
|
||||
// Update potential weapon behaviour for player
|
||||
auto it = m_ActiveWeapons.find(entity);
|
||||
if (it == m_ActiveWeapons.end()) {
|
||||
selectWeapon(entity, 1);
|
||||
}
|
||||
|
||||
m_ActiveWeapons.at(entity)->Update(dt);
|
||||
}
|
||||
|
||||
bool WeaponSystem::OnInputCommand(Events::InputCommand& e)
|
||||
{
|
||||
EntityWrapper player = e.Player;
|
||||
if (e.PlayerID == -1) {
|
||||
m_LocalPlayer = e.Player;
|
||||
player = LocalPlayer;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WeaponSystem::OnInputCommand(const Events::InputCommand& e)
|
||||
{
|
||||
// Only shoot client-side!
|
||||
if (e.PlayerID != -1) {
|
||||
// Make sure player is alive
|
||||
if (!player.Valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only shoot if the player is alive
|
||||
if (!m_LocalPlayer.Valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e.Command == "PrimaryFire" && e.Value > 0) {
|
||||
Events::Shoot eShoot;
|
||||
if (e.PlayerID == -1) {
|
||||
eShoot.Player = m_LocalPlayer;
|
||||
} else {
|
||||
eShoot.Player = e.Player;
|
||||
// Weapon selection
|
||||
if (e.Command == "SelectWeapon") {
|
||||
if (e.Value != 0) {
|
||||
//selectWeapon(player, static_cast<ComponentInfo::EnumType>(e.Value));
|
||||
}
|
||||
}
|
||||
|
||||
// Fire
|
||||
if (e.Command == "PrimaryFire") {
|
||||
if (m_ActiveWeapons.find(player) != m_ActiveWeapons.end()) {
|
||||
auto weapon = m_ActiveWeapons.at(player);
|
||||
if (e.Value > 0) {
|
||||
weapon->Fire();
|
||||
} else {
|
||||
weapon->CeaseFire();
|
||||
}
|
||||
}
|
||||
m_EventBroker->Publish(eShoot);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WeaponSystem::OnShoot(Events::Shoot& eShoot)
|
||||
void WeaponSystem::selectWeapon(EntityWrapper player, ComponentInfo::EnumType slot)
|
||||
{
|
||||
// Primary
|
||||
if (slot == 1) {
|
||||
// TODO: if class...
|
||||
if (m_ActiveWeapons.count(player) == 0) {
|
||||
m_ActiveWeapons.insert(std::make_pair(player, std::make_shared<AssaultWeaponBehaviour>(m_SystemParams, m_CollisionOctree, player)));
|
||||
} else {
|
||||
//m_ActiveWeapons.erase(player);
|
||||
}
|
||||
}
|
||||
|
||||
// Secondary
|
||||
if (slot == 2) {
|
||||
//m_ActiveWeapons[player] = std::make_shared<PistolWeaponBehaviour>();
|
||||
}
|
||||
}
|
||||
|
||||
bool WeaponSystem::OnPlayerSpawned(Events::PlayerSpawned& e)
|
||||
{
|
||||
// Select primary weapon on player spawn
|
||||
// TODO: Select the active one specified by player component
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WeaponSystem::OnShoot(Events::Shoot& eShoot)
|
||||
{
|
||||
if (!eShoot.Player.Valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Weapon firing effects here
|
||||
|
||||
auto rayRed = ResourceManager::Load<EntityFile>("Schema/Entities/RayRed.xml");
|
||||
auto rayBlue = ResourceManager::Load<EntityFile>("Schema/Entities/RayBlue.xml");
|
||||
|
||||
EntityWrapper weapon = eShoot.Player.FirstChildByName("WeaponMuzzle");
|
||||
if (weapon.Valid()) {
|
||||
EntityWrapper ray;
|
||||
if ((ComponentInfo::EnumType)eShoot.Player["Team"]["Team"] == eShoot.Player["Team"]["Team"].Enum("Red")) {
|
||||
EntityFileParser parser(rayRed);
|
||||
EntityID rayID = parser.MergeEntities(m_World);
|
||||
ray = EntityWrapper(m_World, rayID);
|
||||
} else {
|
||||
EntityFileParser parser(rayBlue);
|
||||
EntityID rayID = parser.MergeEntities(m_World);
|
||||
ray = EntityWrapper(m_World, rayID);
|
||||
}
|
||||
|
||||
glm::mat4 transformation = Transform::AbsoluteTransformation(weapon);
|
||||
glm::vec3 scale;
|
||||
glm::vec3 translation;
|
||||
glm::quat orientation;
|
||||
glm::vec3 skew;
|
||||
glm::vec4 perspective;
|
||||
glm::decompose(transformation, scale, orientation, translation, skew, perspective);
|
||||
|
||||
// Matrix to euler angles
|
||||
glm::vec3 euler;
|
||||
euler.y = glm::asin(-transformation[0][2]);
|
||||
if (cos(euler.y) != 0) {
|
||||
euler.x = atan2(transformation[1][2], transformation[2][2]);
|
||||
euler.z = atan2(transformation[0][1], transformation[0][0]);
|
||||
} else {
|
||||
euler.x = atan2(-transformation[2][0], transformation[1][1]);
|
||||
euler.z = 0;
|
||||
}
|
||||
|
||||
//LOG_DEBUG("rotation: %f %f %f", euler.x, euler.y, euler.z);
|
||||
(glm::vec3&)ray["Transform"]["Position"] = translation;
|
||||
(glm::vec3&)ray["Transform"]["Orientation"] = euler;
|
||||
//(glm::vec3&)ray["Transform"]["Orientation"] = Transform::AbsoluteOrientationEuler(weapon);
|
||||
}
|
||||
|
||||
// Only run further picking code client-side!
|
||||
if (eShoot.Player != m_LocalPlayer) {
|
||||
// Only run further picking code for the local player!
|
||||
if (eShoot.Player != LocalPlayer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -138,4 +134,4 @@ bool WeaponSystem::OnShoot(Events::Shoot& eShoot)
|
||||
m_EventBroker->Publish(ePlayerDamage);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user