Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions include/CommonLib/Components/DistributionComponent.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright (C) 2025 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "This Space Of Mine" project
// For conditions of distribution and use, see copyright notice in LICENSE

#pragma once

#ifndef TSOM_COMMONLIB_COMPONENTS_DISTRIBUTIONCOMPONENT_HPP
#define TSOM_COMMONLIB_COMPONENTS_DISTRIBUTIONCOMPONENT_HPP

#include <NazaraUtils/EnumArray.hpp>
#include <NazaraUtils/FixedVector.hpp>
#include <NazaraUtils/Signal.hpp>
#include <CommonLib/Export.hpp>
#include <entt/entt.hpp>
#include <span>

namespace tsom
{
enum class DistributionType
{
Electrical,

Max = Electrical
};

class TSOM_COMMONLIB_API DistributionComponent
{
friend class DistributionSystem;

public:
inline DistributionComponent(std::span<DistributionType> inputs, std::span<DistributionType> outputs);
DistributionComponent(const DistributionComponent&) = delete;
DistributionComponent(DistributionComponent&&) = delete;
~DistributionComponent() = default;

inline void ConnectInput(std::size_t inputIndex, entt::handle entity, std::size_t outputIndex);
inline void ConnectOutput(std::size_t outputIndex, entt::handle entity, std::size_t inputIndex);

inline Nz::UInt32 GetConsumptionValue(std::size_t inputIndex) const;

inline Nz::UInt64 GetDistributedValue(DistributionType type) const;

inline entt::handle GetInputConnectedEntity(std::size_t inputIndex) const;
inline std::size_t GetInputConnectedPort(std::size_t inputIndex) const;
inline std::size_t GetInputCount() const;
inline DistributionType GetInputType(std::size_t inputIndex) const;

inline entt::handle GetOutputConnectedEntity(std::size_t outputIndex) const;
inline std::size_t GetOutputConnectedPort(std::size_t outputIndex) const;
inline std::size_t GetOutputCount() const;
inline DistributionType GetOutputType(std::size_t outputIndex) const;

inline Nz::UInt32 GetProductionValue(std::size_t outputIndex) const;

inline bool IsInputConnected(std::size_t inputIndex) const;
inline bool IsOutputConnected(std::size_t outputIndex) const;

inline void UpdateConsumptionValue(std::size_t inputIndex, Nz::UInt32 consumption);
inline void UpdateProductionValue(std::size_t outputIndex, Nz::UInt32 production);

DistributionComponent& operator=(const DistributionComponent&) = delete;
DistributionComponent& operator=(DistributionComponent&&) = delete;

NazaraSignal(OnInputOutputChanged, DistributionComponent*);

private:
inline void ClearDistributedValues();
inline void IncrementDistributedValue(DistributionType type, Nz::UInt32 value);

struct Port
{
DistributionType type;
entt::handle connectedEntity;
std::size_t connectedPort;
};

struct InputPort : Port
{
Nz::UInt64 consumptionValue = 0;
};

struct OutputPort : Port
{
Nz::UInt64 productionValue = 0;
};

Nz::EnumArray<DistributionType, Nz::UInt64> m_distributedValues;
Nz::HybridVector<InputPort, 3> m_inputs;
Nz::HybridVector<OutputPort, 3> m_outputs;
};
}

#include <CommonLib/Components/DistributionComponent.inl>

#endif // TSOM_COMMONLIB_COMPONENTS_DISTRIBUTIONCOMPONENT_HPP
140 changes: 140 additions & 0 deletions include/CommonLib/Components/DistributionComponent.inl
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
// Copyright (C) 2025 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "This Space Of Mine" project
// For conditions of distribution and use, see copyright notice in LICENSE

#include <NazaraUtils/Assert.hpp>

namespace tsom
{
inline DistributionComponent::DistributionComponent(std::span<DistributionType> inputs, std::span<DistributionType> outputs)
{
m_inputs.reserve(inputs.size());
for (DistributionType distributionType : inputs)
{
auto& port = m_inputs.emplace_back();
port.type = distributionType;
}

m_outputs.reserve(inputs.size());
for (DistributionType distributionType : outputs)
{
auto& port = m_outputs.emplace_back();
port.type = distributionType;
}
}

inline void DistributionComponent::ConnectInput(std::size_t inputIndex, entt::handle entity, std::size_t outputIndex)
{
NazaraAssert(inputIndex < m_inputs.size());
m_inputs[inputIndex].connectedEntity = entity;
m_inputs[inputIndex].connectedPort = outputIndex;

OnInputOutputChanged(this);
}

inline void DistributionComponent::ConnectOutput(std::size_t outputIndex, entt::handle entity, std::size_t inputIndex)
{
NazaraAssert(outputIndex < m_outputs.size());
m_outputs[outputIndex].connectedEntity = entity;
m_outputs[outputIndex].connectedPort = inputIndex;

OnInputOutputChanged(this);
}

inline Nz::UInt32 DistributionComponent::GetConsumptionValue(std::size_t inputIndex) const
{
NazaraAssert(inputIndex < m_inputs.size());
return m_inputs[inputIndex].consumptionValue;
}

inline Nz::UInt64 DistributionComponent::GetDistributedValue(DistributionType type) const
{
return m_distributedValues[type];
}

inline entt::handle DistributionComponent::GetInputConnectedEntity(std::size_t inputIndex) const
{
NazaraAssert(inputIndex < m_inputs.size());
return m_inputs[inputIndex].connectedEntity;
}

inline std::size_t DistributionComponent::GetInputConnectedPort(std::size_t inputIndex) const
{
NazaraAssert(inputIndex < m_inputs.size());
return m_inputs[inputIndex].connectedPort;
}

inline std::size_t DistributionComponent::GetInputCount() const
{
return m_inputs.size();
}

inline DistributionType DistributionComponent::GetInputType(std::size_t inputIndex) const
{
NazaraAssert(inputIndex < m_inputs.size());
return m_inputs[inputIndex].type;
}

inline entt::handle DistributionComponent::GetOutputConnectedEntity(std::size_t outputIndex) const
{
NazaraAssert(outputIndex < m_outputs.size());
return m_outputs[outputIndex].connectedEntity;
}

inline std::size_t DistributionComponent::GetOutputConnectedPort(std::size_t outputIndex) const
{
NazaraAssert(outputIndex < m_outputs.size());
return m_outputs[outputIndex].connectedPort;
}

inline std::size_t DistributionComponent::GetOutputCount() const
{
return m_outputs.size();
}

inline DistributionType DistributionComponent::GetOutputType(std::size_t outputIndex) const
{
NazaraAssert(outputIndex < m_outputs.size());
return m_outputs[outputIndex].type;
}

inline Nz::UInt32 DistributionComponent::GetProductionValue(std::size_t outputIndex) const
{
NazaraAssert(outputIndex < m_outputs.size());
return m_outputs[outputIndex].productionValue;
}

inline bool DistributionComponent::IsInputConnected(std::size_t inputIndex) const
{
NazaraAssert(inputIndex < m_inputs.size());
return m_inputs[inputIndex].connectedEntity.valid();
}

inline bool DistributionComponent::IsOutputConnected(std::size_t outputIndex) const
{
NazaraAssert(outputIndex < m_outputs.size());
return m_outputs[outputIndex].connectedEntity.valid();
}

inline void DistributionComponent::UpdateConsumptionValue(std::size_t inputIndex, Nz::UInt32 consumption)
{
NazaraAssert(inputIndex < m_inputs.size());
m_inputs[inputIndex].consumptionValue = consumption;
}

inline void DistributionComponent::UpdateProductionValue(std::size_t outputIndex, Nz::UInt32 production)
{
NazaraAssert(outputIndex < m_outputs.size());
m_outputs[outputIndex].productionValue = production;
}

inline void DistributionComponent::ClearDistributedValues()
{
m_distributedValues.fill(0);
}

inline void DistributionComponent::IncrementDistributedValue(DistributionType type, Nz::UInt32 value)
{
m_distributedValues[type] += value;
}
}
56 changes: 56 additions & 0 deletions include/ServerLib/Systems/DistributionSystem.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright (C) 2025 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "This Space Of Mine" project
// For conditions of distribution and use, see copyright notice in LICENSE

#pragma once

#ifndef TSOM_SERVERLIB_SYSTEMS_DISTRIBUTIONSYSTEM_HPP
#define TSOM_SERVERLIB_SYSTEMS_DISTRIBUTIONSYSTEM_HPP

#include <ServerLib/Export.hpp>
#include <CommonLib/Components/DistributionComponent.hpp>
#include <Nazara/Core/Time.hpp>
#include <NazaraUtils/TypeList.hpp>
#include <entt/entt.hpp>
#include <tsl/hopscotch_map.h>
#include <tsl/hopscotch_set.h>

namespace tsom
{
class TSOM_SERVERLIB_API DistributionSystem
{
public:
static constexpr bool AllowConcurrent = false;
static constexpr Nz::Int64 ExecutionOrder = -2; //< execute before TickSystem
using Components = Nz::TypeList<DistributionComponent>;

DistributionSystem(entt::registry& registry);
DistributionSystem(const DistributionSystem&) = delete;
DistributionSystem(DistributionSystem&&) = delete;
~DistributionSystem();

void Update(Nz::Time elapsedTime);

DistributionSystem& operator=(const DistributionSystem&) = delete;
DistributionSystem& operator=(DistributionSystem&&) = delete;

private:
void OnDistributionDestroy(entt::entity entity);
void HandleDistributionEntity(entt::entity entity, DistributionComponent& distribution);

struct EntityData
{
NazaraSlot(DistributionComponent, OnInputOutputChanged, onInputOutputChangedSlot);
};

tsl::hopscotch_map<entt::entity, EntityData> m_distributionEntities;
tsl::hopscotch_set<entt::entity> m_producers;
entt::observer m_distributionConstructObserver;
entt::scoped_connection m_distributionDestroyConnection;
entt::registry& m_registry;
};
}

#include <ServerLib/Systems/DistributionSystem.inl>

#endif // TSOM_SERVERLIB_SYSTEMS_DISTRIBUTIONSYSTEM_HPP
7 changes: 7 additions & 0 deletions include/ServerLib/Systems/DistributionSystem.inl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Copyright (C) 2025 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "This Space Of Mine" project
// For conditions of distribution and use, see copyright notice in LICENSE

namespace tsom
{
}
14 changes: 14 additions & 0 deletions scripts/assets/light.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
local primitive = Primitive.Box(Vec3f(0.5, 0.5, 0.5))

local mesh = Mesh.CreateStatic()
mesh:BuildSubMesh(primitive)
mesh:SetMaterialCount(1)

local model = Model.BuildFromMesh(mesh)

local lightMat = MaterialInstance.Instantiate(MaterialType.PhysicallyBased)
lightMat:SetTextureProperty("BaseColorMap", Texture.Load("assets/dev/grey.png"))

model:SetMaterial(0, lightMat)

AssetLibrary.RegisterModel("light", model)
15 changes: 15 additions & 0 deletions scripts/assets/solar_panel.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
local primitive = Primitive.Box(Vec3f(2.0, 0.1, 2.0))

local mesh = Mesh.CreateStatic()
mesh:BuildSubMesh(primitive)
mesh:SetMaterialCount(1)

local model = Model.BuildFromMesh(mesh)

local solarPanelMat = MaterialInstance.Instantiate(MaterialType.PhysicallyBased)
solarPanelMat:SetTextureProperty("BaseColorMap", Texture.Load("assets/dev/grey.png"))
solarPanelMat:SetValueProperty("BaseColor", Color(0.2, 0.2, 1.0))

model:SetMaterial(0, solarPanelMat)

AssetLibrary.RegisterModel("solar_panel", model)
30 changes: 30 additions & 0 deletions scripts/commands/spawn_solar_panel.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
return function ()
local env = CurrentPlayer:GetEnvironment()
local physWorld = env:GetPhysWorld()

local controller = CurrentPlayer:GetController()

local eyePos = controller:GetEyePosition()
local cameraRot = controller:GetCameraRotation()

local result = physWorld:RaycastQueryFirst(eyePos, eyePos + cameraRot * Vec3f(0, 0, -10), { IgnorePlayers = true })

if not result.hitEntity or not result.hitChunk then
print("no chunk hit")
return
end

local solarPanel = env:CreateEntity("solar_panel", {
position = result.hitPosition + result.hitNormal + Vec3f(-2, 0, 0)
})

local light = env:CreateEntity("light", {
position = result.hitPosition + result.hitNormal + Vec3f(2, 0, 0)
})

local solarPanelDis = solarPanel:GetComponent("distribution")
local solarPanelLight = light:GetComponent("distribution")

solarPanelDis:ConnectOutput(0, light, 0)
solarPanelLight:ConnectInput(0, solarPanel, 0)
end
Loading
Loading