Multiplayer working
This commit is contained in:
parent
106d5ced0b
commit
2af77fa468
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@ -3,7 +3,7 @@
|
||||
"args": [
|
||||
"--single",
|
||||
"--port",
|
||||
"8080"
|
||||
"8080-"
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -14,4 +14,5 @@ namespace deerith
|
||||
float get_window_aspect_ratio();
|
||||
|
||||
int get_current_frame_id();
|
||||
bool is_windows_focused();
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include <deerith/engine.h>
|
||||
|
||||
namespace deerith
|
||||
{
|
||||
struct chunk_render_t
|
||||
{
|
||||
};
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
#include "deerith/graphics/shader.h"
|
||||
#include <deerith/engine.h>
|
||||
|
||||
#include <glad/gl.h>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
@ -6,6 +7,24 @@
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <filesystem>
|
||||
|
||||
std::filesystem::path get_executable_directory()
|
||||
{
|
||||
std::array<char, 4096> buffer{};
|
||||
|
||||
const auto length = readlink(
|
||||
"/proc/self/exe",
|
||||
buffer.data(),
|
||||
buffer.size() - 1);
|
||||
|
||||
if (length == -1)
|
||||
throw std::runtime_error("Failed to get executable path");
|
||||
|
||||
return std::filesystem::path(
|
||||
std::string(buffer.data(), length))
|
||||
.parent_path();
|
||||
}
|
||||
|
||||
deerith::Shader::Shader(const char *vertexPath, const char *fragmentPath)
|
||||
{
|
||||
@ -23,10 +42,11 @@ deerith::Shader::Shader(const char *vertexPath, const char *fragmentPath)
|
||||
std::ifstream::failbit |
|
||||
std::ifstream::badbit);
|
||||
|
||||
std::filesystem::path cwd = get_executable_directory();
|
||||
try
|
||||
{
|
||||
vertexFile.open(vertexPath);
|
||||
fragmentFile.open(fragmentPath);
|
||||
vertexFile.open(cwd / vertexPath);
|
||||
fragmentFile.open(cwd / fragmentPath);
|
||||
|
||||
std::stringstream vertexStream;
|
||||
std::stringstream fragmentStream;
|
||||
|
||||
@ -77,6 +77,11 @@ int deerith::init_window()
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool deerith::is_windows_focused()
|
||||
{
|
||||
return window && glfwGetWindowAttrib(window, GLFW_FOCUSED);
|
||||
}
|
||||
|
||||
bool deerith::begin_window_display()
|
||||
{
|
||||
glfwPollEvents();
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#include <deerith/engine.h>
|
||||
#include <deerith/graphics/input.h>
|
||||
#include <deerith/graphics/window.h>
|
||||
#include <deerith/network/router.h>
|
||||
#include <deerith/network/packets.h>
|
||||
#include <deerith/world/entity.h>
|
||||
@ -15,7 +16,13 @@ void deerith::process_player_input()
|
||||
{
|
||||
if (self_entity == entt::null)
|
||||
return;
|
||||
|
||||
glm::vec2 movment = get_joystick_axes(0, 0);
|
||||
if (!is_windows_focused())
|
||||
{
|
||||
movment = glm::vec2(0, 0);
|
||||
}
|
||||
|
||||
entity_sync_client_position_t &entity_sync_position = get_component<entity_sync_client_position_t>(self_entity);
|
||||
|
||||
entity_sync_position.move_input = movment;
|
||||
|
||||
@ -13,6 +13,7 @@ void deerith::setup_base_protocols()
|
||||
router_add_packet_processor<create_player_entity_packet_t>();
|
||||
router_add_packet_processor<create_entity_packet_t>();
|
||||
router_add_packet_processor<sync_entities_coordinates_packet_t>();
|
||||
router_add_packet_processor<destroy_entity_packet_t>();
|
||||
}
|
||||
|
||||
template <>
|
||||
@ -34,7 +35,17 @@ void deerith::process_packet(deerith::create_entity_packet_t &packet, client_t *
|
||||
{
|
||||
deerith_trace("creating entity with network id {}", packet.network_sync_id);
|
||||
|
||||
entity_t entity = create_entity();
|
||||
entity_t entity;
|
||||
if (packet.is_self_client)
|
||||
{
|
||||
deerith_trace("creating self entity");
|
||||
entity = self_entity;
|
||||
}
|
||||
else
|
||||
{
|
||||
entity = create_entity();
|
||||
}
|
||||
|
||||
entity_network_id_t &entity_network_id = add_entity_network_with_id(entity, packet.network_sync_id);
|
||||
|
||||
if (packet.add_entity_sync_coordinates)
|
||||
@ -60,3 +71,11 @@ void deerith::process_packet(deerith::sync_entities_coordinates_packet_t &packet
|
||||
packet.positions_to_update[i].recive(sync_coords.position);
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void deerith::process_packet(deerith::destroy_entity_packet_t &packet, client_t *client)
|
||||
{
|
||||
deerith_trace("destroying entity : {}", packet.network_sync_id);
|
||||
entity_t specific_entity = get_network_entity_with_id(packet.network_sync_id);
|
||||
get_entity_registry().destroy(specific_entity);
|
||||
}
|
||||
@ -7,7 +7,7 @@ void deerith::render_world()
|
||||
{
|
||||
define_primitive_viewspace(glm::vec2(-10, -10), glm::vec2(10, 10));
|
||||
|
||||
auto entities_view = get_entity_registry().view<entity_sync_coordinates_t>();
|
||||
auto entities_view = get_entity_registry().view<entity_sync_coordinates_t>(entt::exclude<entity_sync_client_position_t>);
|
||||
for (auto [entity, sync_coords] : entities_view.each())
|
||||
{
|
||||
glm::vec2 chords;
|
||||
@ -17,4 +17,12 @@ void deerith::render_world()
|
||||
draw_primitive_rectangle(chords - glm::vec2(0.5f, 0.5f), chords + glm::vec2(0.5f, 0.5f));
|
||||
}
|
||||
}
|
||||
|
||||
// we should expect only one registry
|
||||
auto self_view = get_entity_registry().view<entity_sync_coordinates_t, entity_sync_client_position_t>();
|
||||
for (auto [entity, sync_coords, client_sync_coords] : self_view.each())
|
||||
{
|
||||
define_primitive_color(glm::vec4(1, 0.5f, 0.6f, 1));
|
||||
draw_primitive_rectangle(client_sync_coords.position.read_value() - glm::vec2(0.5f, 0.5f), client_sync_coords.position.read_value() + glm::vec2(0.5f, 0.5f));
|
||||
}
|
||||
}
|
||||
@ -42,7 +42,7 @@ namespace cereal
|
||||
inline std::uint8_t is_little_endian()
|
||||
{
|
||||
static std::int32_t test = 1;
|
||||
return *reinterpret_cast<std::int8_t*>( &test ) == 1;
|
||||
return *reinterpret_cast<std::int8_t *>(&test) == 1;
|
||||
}
|
||||
|
||||
//! Swaps the order of bytes for some chunk of memory
|
||||
@ -50,10 +50,10 @@ namespace cereal
|
||||
@tparam DataSize The true size of the data
|
||||
@ingroup Internal */
|
||||
template <std::size_t DataSize>
|
||||
inline void swap_bytes( std::uint8_t * data )
|
||||
inline void swap_bytes(std::uint8_t *data)
|
||||
{
|
||||
for( std::size_t i = 0, end = DataSize / 2; i < end; ++i )
|
||||
std::swap( data[i], data[DataSize - i - 1] );
|
||||
for (std::size_t i = 0, end = DataSize / 2; i < end; ++i)
|
||||
std::swap(data[i], data[DataSize - i - 1]);
|
||||
}
|
||||
} // end namespace portable_binary_detail
|
||||
|
||||
@ -84,30 +84,36 @@ namespace cereal
|
||||
public:
|
||||
//! Represents desired endianness
|
||||
enum class Endianness : std::uint8_t
|
||||
{ big, little };
|
||||
{
|
||||
big,
|
||||
little
|
||||
};
|
||||
|
||||
//! Default options, preserve system endianness
|
||||
static Options Default(){ return Options(); }
|
||||
static Options Default() { return Options(); }
|
||||
|
||||
//! Save as little endian
|
||||
static Options LittleEndian(){ return Options( Endianness::little ); }
|
||||
static Options LittleEndian() { return Options(Endianness::little); }
|
||||
|
||||
//! Save as big endian
|
||||
static Options BigEndian(){ return Options( Endianness::big ); }
|
||||
static Options BigEndian() { return Options(Endianness::big); }
|
||||
|
||||
//! Specify specific options for the PortableBinaryOutputArchive
|
||||
/*! @param outputEndian The desired endianness of saved (output) data */
|
||||
explicit Options( Endianness outputEndian = getEndianness() ) :
|
||||
itsOutputEndianness( outputEndian ) { }
|
||||
explicit Options(Endianness outputEndian = getEndianness()) : itsOutputEndianness(outputEndian) {}
|
||||
|
||||
private:
|
||||
//! Gets the endianness of the system
|
||||
inline static Endianness getEndianness()
|
||||
{ return portable_binary_detail::is_little_endian() ? Endianness::little : Endianness::big; }
|
||||
{
|
||||
return portable_binary_detail::is_little_endian() ? Endianness::little : Endianness::big;
|
||||
}
|
||||
|
||||
//! Checks if Options is set for little endian
|
||||
inline std::uint8_t is_little_endian() const
|
||||
{ return itsOutputEndianness == Endianness::little; }
|
||||
{
|
||||
return itsOutputEndianness == Endianness::little;
|
||||
}
|
||||
|
||||
friend class PortableBinaryOutputArchive;
|
||||
Endianness itsOutputEndianness;
|
||||
@ -117,37 +123,36 @@ namespace cereal
|
||||
/*! @param stream The stream to output to. Should be opened with std::ios::binary flag.
|
||||
@param options The PortableBinary specific options to use. See the Options struct
|
||||
for the values of default parameters */
|
||||
PortableBinaryOutputArchive(std::ostream & stream, Options const & options = Options::Default()) :
|
||||
OutputArchive<PortableBinaryOutputArchive, AllowEmptyClassElision>(this),
|
||||
PortableBinaryOutputArchive(std::ostream &stream, Options const &options = Options::Default()) : OutputArchive<PortableBinaryOutputArchive, AllowEmptyClassElision>(this),
|
||||
itsStream(stream),
|
||||
itsConvertEndianness( portable_binary_detail::is_little_endian() ^ options.is_little_endian() )
|
||||
itsConvertEndianness(portable_binary_detail::is_little_endian() ^ options.is_little_endian())
|
||||
{
|
||||
this->operator()( options.is_little_endian() );
|
||||
this->operator()(options.is_little_endian());
|
||||
}
|
||||
|
||||
~PortableBinaryOutputArchive() CEREAL_NOEXCEPT = default;
|
||||
|
||||
//! Writes size bytes of data to the output stream
|
||||
template <std::streamsize DataSize> inline
|
||||
void saveBinary( const void * data, std::streamsize size )
|
||||
template <std::streamsize DataSize>
|
||||
inline void saveBinary(const void *data, std::streamsize size)
|
||||
{
|
||||
std::streamsize writtenSize = 0;
|
||||
|
||||
if( itsConvertEndianness )
|
||||
if (itsConvertEndianness)
|
||||
{
|
||||
for( std::streamsize i = 0; i < size; i += DataSize )
|
||||
for( std::streamsize j = 0; j < DataSize; ++j )
|
||||
writtenSize += itsStream.rdbuf()->sputn( reinterpret_cast<const char*>( data ) + DataSize - j - 1 + i, 1 );
|
||||
for (std::streamsize i = 0; i < size; i += DataSize)
|
||||
for (std::streamsize j = 0; j < DataSize; ++j)
|
||||
writtenSize += itsStream.rdbuf()->sputn(reinterpret_cast<const char *>(data) + DataSize - j - 1 + i, 1);
|
||||
}
|
||||
else
|
||||
writtenSize = itsStream.rdbuf()->sputn( reinterpret_cast<const char*>( data ), size );
|
||||
writtenSize = itsStream.rdbuf()->sputn(reinterpret_cast<const char *>(data), size);
|
||||
|
||||
if(writtenSize != size)
|
||||
if (writtenSize != size)
|
||||
throw Exception("Failed to write " + std::to_string(size) + " bytes to output stream! Wrote " + std::to_string(writtenSize));
|
||||
}
|
||||
|
||||
private:
|
||||
std::ostream & itsStream;
|
||||
std::ostream &itsStream;
|
||||
const uint8_t itsConvertEndianness; //!< If set to true, we will need to swap bytes upon saving
|
||||
};
|
||||
|
||||
@ -186,30 +191,36 @@ namespace cereal
|
||||
public:
|
||||
//! Represents desired endianness
|
||||
enum class Endianness : std::uint8_t
|
||||
{ big, little };
|
||||
{
|
||||
big,
|
||||
little
|
||||
};
|
||||
|
||||
//! Default options, preserve system endianness
|
||||
static Options Default(){ return Options(); }
|
||||
static Options Default() { return Options(); }
|
||||
|
||||
//! Load into little endian
|
||||
static Options LittleEndian(){ return Options( Endianness::little ); }
|
||||
static Options LittleEndian() { return Options(Endianness::little); }
|
||||
|
||||
//! Load into big endian
|
||||
static Options BigEndian(){ return Options( Endianness::big ); }
|
||||
static Options BigEndian() { return Options(Endianness::big); }
|
||||
|
||||
//! Specify specific options for the PortableBinaryInputArchive
|
||||
/*! @param inputEndian The desired endianness of loaded (input) data */
|
||||
explicit Options( Endianness inputEndian = getEndianness() ) :
|
||||
itsInputEndianness( inputEndian ) { }
|
||||
explicit Options(Endianness inputEndian = getEndianness()) : itsInputEndianness(inputEndian) {}
|
||||
|
||||
private:
|
||||
//! Gets the endianness of the system
|
||||
inline static Endianness getEndianness()
|
||||
{ return portable_binary_detail::is_little_endian() ? Endianness::little : Endianness::big; }
|
||||
{
|
||||
return portable_binary_detail::is_little_endian() ? Endianness::little : Endianness::big;
|
||||
}
|
||||
|
||||
//! Checks if Options is set for little endian
|
||||
inline std::uint8_t is_little_endian() const
|
||||
{ return itsInputEndianness == Endianness::little; }
|
||||
{
|
||||
return itsInputEndianness == Endianness::little;
|
||||
}
|
||||
|
||||
friend class PortableBinaryInputArchive;
|
||||
Endianness itsInputEndianness;
|
||||
@ -219,13 +230,12 @@ namespace cereal
|
||||
/*! @param stream The stream to read from. Should be opened with std::ios::binary flag.
|
||||
@param options The PortableBinary specific options to use. See the Options struct
|
||||
for the values of default parameters */
|
||||
PortableBinaryInputArchive(std::istream & stream, Options const & options = Options::Default()) :
|
||||
InputArchive<PortableBinaryInputArchive, AllowEmptyClassElision>(this),
|
||||
PortableBinaryInputArchive(std::istream &stream, Options const &options = Options::Default()) : InputArchive<PortableBinaryInputArchive, AllowEmptyClassElision>(this),
|
||||
itsStream(stream),
|
||||
itsConvertEndianness( false )
|
||||
itsConvertEndianness(false)
|
||||
{
|
||||
uint8_t streamLittleEndian;
|
||||
this->operator()( streamLittleEndian );
|
||||
this->operator()(streamLittleEndian);
|
||||
itsConvertEndianness = options.is_little_endian() ^ streamLittleEndian;
|
||||
}
|
||||
|
||||
@ -235,26 +245,26 @@ namespace cereal
|
||||
/*! @param data The data to save
|
||||
@param size The number of bytes in the data
|
||||
@tparam DataSize T The size of the actual type of the data elements being loaded */
|
||||
template <std::streamsize DataSize> inline
|
||||
void loadBinary( void * const data, std::streamsize size )
|
||||
template <std::streamsize DataSize>
|
||||
inline void loadBinary(void *const data, std::streamsize size)
|
||||
{
|
||||
// load data
|
||||
auto const readSize = itsStream.rdbuf()->sgetn( reinterpret_cast<char*>( data ), size );
|
||||
auto const readSize = itsStream.rdbuf()->sgetn(reinterpret_cast<char *>(data), size);
|
||||
|
||||
if(readSize != size)
|
||||
if (readSize != size)
|
||||
throw Exception("Failed to read " + std::to_string(size) + " bytes from input stream! Read " + std::to_string(readSize));
|
||||
|
||||
// flip bits if needed
|
||||
if( itsConvertEndianness )
|
||||
if (itsConvertEndianness)
|
||||
{
|
||||
std::uint8_t * ptr = reinterpret_cast<std::uint8_t*>( data );
|
||||
for( std::streamsize i = 0; i < size; i += DataSize )
|
||||
portable_binary_detail::swap_bytes<DataSize>( ptr + i );
|
||||
std::uint8_t *ptr = reinterpret_cast<std::uint8_t *>(data);
|
||||
for (std::streamsize i = 0; i < size; i += DataSize)
|
||||
portable_binary_detail::swap_bytes<DataSize>(ptr + i);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::istream & itsStream;
|
||||
std::istream &itsStream;
|
||||
uint8_t itsConvertEndianness; //!< If set to true, we will need to swap bytes upon loading
|
||||
};
|
||||
|
||||
@ -262,65 +272,67 @@ namespace cereal
|
||||
// Common BinaryArchive serialization functions
|
||||
|
||||
//! Saving for POD types to portable binary
|
||||
template<class T> inline
|
||||
template <class T>
|
||||
inline
|
||||
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
|
||||
CEREAL_SAVE_FUNCTION_NAME(PortableBinaryOutputArchive & ar, T const & t)
|
||||
CEREAL_SAVE_FUNCTION_NAME(PortableBinaryOutputArchive &ar, T const &t)
|
||||
{
|
||||
static_assert( !std::is_floating_point<T>::value ||
|
||||
static_assert(!std::is_floating_point<T>::value ||
|
||||
(std::is_floating_point<T>::value && std::numeric_limits<T>::is_iec559),
|
||||
"Portable binary only supports IEEE 754 standardized floating point" );
|
||||
"Portable binary only supports IEEE 754 standardized floating point");
|
||||
ar.template saveBinary<sizeof(T)>(std::addressof(t), sizeof(t));
|
||||
}
|
||||
|
||||
//! Loading for POD types from portable binary
|
||||
template<class T> inline
|
||||
template <class T>
|
||||
inline
|
||||
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME(PortableBinaryInputArchive & ar, T & t)
|
||||
CEREAL_LOAD_FUNCTION_NAME(PortableBinaryInputArchive &ar, T &t)
|
||||
{
|
||||
static_assert( !std::is_floating_point<T>::value ||
|
||||
static_assert(!std::is_floating_point<T>::value ||
|
||||
(std::is_floating_point<T>::value && std::numeric_limits<T>::is_iec559),
|
||||
"Portable binary only supports IEEE 754 standardized floating point" );
|
||||
"Portable binary only supports IEEE 754 standardized floating point");
|
||||
ar.template loadBinary<sizeof(T)>(std::addressof(t), sizeof(t));
|
||||
}
|
||||
|
||||
//! Serializing NVP types to portable binary
|
||||
template <class Archive, class T> inline
|
||||
CEREAL_ARCHIVE_RESTRICT(PortableBinaryInputArchive, PortableBinaryOutputArchive)
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, NameValuePair<T> & t )
|
||||
template <class Archive, class T>
|
||||
inline CEREAL_ARCHIVE_RESTRICT(PortableBinaryInputArchive, PortableBinaryOutputArchive)
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME(Archive &ar, NameValuePair<T> &t)
|
||||
{
|
||||
ar( t.value );
|
||||
ar(t.value);
|
||||
}
|
||||
|
||||
//! Serializing SizeTags to portable binary
|
||||
template <class Archive, class T> inline
|
||||
CEREAL_ARCHIVE_RESTRICT(PortableBinaryInputArchive, PortableBinaryOutputArchive)
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, SizeTag<T> & t )
|
||||
template <class Archive, class T>
|
||||
inline CEREAL_ARCHIVE_RESTRICT(PortableBinaryInputArchive, PortableBinaryOutputArchive)
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME(Archive &ar, SizeTag<T> &t)
|
||||
{
|
||||
ar( t.size );
|
||||
ar(t.size);
|
||||
}
|
||||
|
||||
//! Saving binary data to portable binary
|
||||
template <class T> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME(PortableBinaryOutputArchive & ar, BinaryData<T> const & bd)
|
||||
template <class T>
|
||||
inline void CEREAL_SAVE_FUNCTION_NAME(PortableBinaryOutputArchive &ar, BinaryData<T> const &bd)
|
||||
{
|
||||
typedef typename std::remove_pointer<T>::type TT;
|
||||
static_assert( !std::is_floating_point<TT>::value ||
|
||||
static_assert(!std::is_floating_point<TT>::value ||
|
||||
(std::is_floating_point<TT>::value && std::numeric_limits<TT>::is_iec559),
|
||||
"Portable binary only supports IEEE 754 standardized floating point" );
|
||||
"Portable binary only supports IEEE 754 standardized floating point");
|
||||
|
||||
ar.template saveBinary<sizeof(TT)>( bd.data, static_cast<std::streamsize>( bd.size ) );
|
||||
ar.template saveBinary<sizeof(TT)>(bd.data, static_cast<std::streamsize>(bd.size));
|
||||
}
|
||||
|
||||
//! Loading binary data from portable binary
|
||||
template <class T> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME(PortableBinaryInputArchive & ar, BinaryData<T> & bd)
|
||||
template <class T>
|
||||
inline void CEREAL_LOAD_FUNCTION_NAME(PortableBinaryInputArchive &ar, BinaryData<T> &bd)
|
||||
{
|
||||
typedef typename std::remove_pointer<T>::type TT;
|
||||
static_assert( !std::is_floating_point<TT>::value ||
|
||||
static_assert(!std::is_floating_point<TT>::value ||
|
||||
(std::is_floating_point<TT>::value && std::numeric_limits<TT>::is_iec559),
|
||||
"Portable binary only supports IEEE 754 standardized floating point" );
|
||||
"Portable binary only supports IEEE 754 standardized floating point");
|
||||
|
||||
ar.template loadBinary<sizeof(TT)>( bd.data, static_cast<std::streamsize>( bd.size ) );
|
||||
ar.template loadBinary<sizeof(TT)>(bd.data, static_cast<std::streamsize>(bd.size));
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
|
||||
@ -47,14 +47,16 @@ namespace deerith
|
||||
static constexpr uint16_t packet_id = 4;
|
||||
static constexpr bool reliable = true;
|
||||
|
||||
id_t network_sync_id;
|
||||
bool add_entity_sync_coordinates;
|
||||
id_t network_sync_id = 0;
|
||||
bool add_entity_sync_coordinates = false;
|
||||
bool is_self_client = false;
|
||||
|
||||
template <typename Archive>
|
||||
void serialize(Archive &archive)
|
||||
{
|
||||
archive(network_sync_id);
|
||||
archive(add_entity_sync_coordinates);
|
||||
archive(is_self_client);
|
||||
}
|
||||
};
|
||||
|
||||
@ -73,4 +75,18 @@ namespace deerith
|
||||
archive(positions_to_update);
|
||||
}
|
||||
};
|
||||
|
||||
struct destroy_entity_packet_t
|
||||
{
|
||||
static constexpr uint16_t packet_id = 6;
|
||||
static constexpr bool reliable = true;
|
||||
|
||||
id_t network_sync_id = 0;
|
||||
|
||||
template <typename Archive>
|
||||
void serialize(Archive &archive)
|
||||
{
|
||||
archive(network_sync_id);
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
#include "network/network_internals.h"
|
||||
#include <deerith/network/router.h>
|
||||
|
||||
#include <deerith/network/packets.h>
|
||||
|
||||
void deerith::load_base_protocols()
|
||||
{
|
||||
router_add_packet_processor<sync_entity_player_position_packet_t>();
|
||||
}
|
||||
@ -21,6 +21,21 @@ namespace deerith
|
||||
std::vector<std::unique_ptr<client_t>> clients;
|
||||
|
||||
void create_client(ENetPeer *peer);
|
||||
void delete_client(client_t *client);
|
||||
}
|
||||
|
||||
void deerith::delete_client(client_t *client)
|
||||
{
|
||||
auto it = std::find_if(
|
||||
clients.begin(),
|
||||
clients.end(),
|
||||
[client](const std::unique_ptr<client_t> &ptr)
|
||||
{ return ptr.get() == client; });
|
||||
|
||||
if (it != clients.end())
|
||||
{
|
||||
clients.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
bool deerith::init_server(int port)
|
||||
@ -71,6 +86,8 @@ void deerith::flush_network_events()
|
||||
break;
|
||||
|
||||
case ENET_EVENT_TYPE_DISCONNECT:
|
||||
client_disconnects((client_t *)event.peer->data);
|
||||
delete_client((client_t *)event.peer->data);
|
||||
event.peer->data = NULL;
|
||||
break;
|
||||
|
||||
|
||||
@ -12,6 +12,10 @@ namespace deerith
|
||||
{
|
||||
|
||||
}
|
||||
void deerith::load_base_protocols()
|
||||
{
|
||||
router_add_packet_processor<sync_entity_player_position_packet_t>();
|
||||
}
|
||||
|
||||
template <>
|
||||
void deerith::process_packet(sync_entity_player_position_packet_t &packet, client_t *client)
|
||||
@ -32,37 +36,85 @@ void deerith::client_connects(client_t *client)
|
||||
|
||||
// create entity player entity
|
||||
entity_t entity = create_entity();
|
||||
entity_link_to_client_t &link = add_component<entity_link_to_client_t>(entity);
|
||||
entity_sync_client_position_t &position_sync = add_component<entity_sync_client_position_t>(entity);
|
||||
|
||||
create_player_entity_packet_t create_player_entity;
|
||||
router_send_packet(create_player_entity, client);
|
||||
|
||||
link.client = client;
|
||||
client->entity_id = entity;
|
||||
|
||||
// create the server representation of the entity
|
||||
add_entity_network_id(entity);
|
||||
add_component<entity_sync_coordinates_t>(entity);
|
||||
|
||||
send_create_entity_to_all_clients(entity);
|
||||
|
||||
// we do this the last to avoid send_create_entity_to_all_clients send_create_actual_entities_to_client create the same entity for the player
|
||||
entity_link_to_client_t &link = add_component<entity_link_to_client_t>(entity);
|
||||
client->entity_id = entity;
|
||||
link.client = client;
|
||||
|
||||
send_create_actual_entities_to_client(client);
|
||||
}
|
||||
|
||||
void deerith::send_create_entity_to_all_clients(deerith::entity_t ent)
|
||||
{
|
||||
auto view = get_entity_registry().view<entity_link_to_client_t>();
|
||||
for (auto [entity, link_to_client] : view.each())
|
||||
{
|
||||
send_create_entity_to_client(ent, link_to_client.client);
|
||||
}
|
||||
}
|
||||
|
||||
void deerith::send_create_entity_to_client(entity_t ent, client_t *client)
|
||||
{
|
||||
entity_network_id_t &entity_network_id = get_component<entity_network_id_t>(ent);
|
||||
|
||||
create_entity_packet_t create_entity;
|
||||
create_entity.network_sync_id = entity_network_id.network_id;
|
||||
|
||||
// in case its the self entity we let it know to the client
|
||||
if (has_component<entity_link_to_client_t>(ent))
|
||||
{
|
||||
entity_link_to_client_t &link = get_component<entity_link_to_client_t>(ent);
|
||||
create_entity.is_self_client = link.client == client;
|
||||
deerith_trace("entity could be self {}", create_entity.is_self_client);
|
||||
}
|
||||
|
||||
if (has_component<entity_sync_coordinates_t>(ent))
|
||||
{
|
||||
create_entity.add_entity_sync_coordinates = true;
|
||||
}
|
||||
|
||||
router_send_packet(create_entity, client);
|
||||
}
|
||||
|
||||
void deerith::client_disconnects(client_t *client)
|
||||
{
|
||||
entity_t client_entity = client->entity_id;
|
||||
send_delete_entity_to_all_clients(client_entity);
|
||||
|
||||
get_entity_registry().destroy(client_entity);
|
||||
}
|
||||
|
||||
void deerith::send_delete_entity_to_all_clients(entity_t ent)
|
||||
{
|
||||
destroy_entity_packet_t destroy_entity;
|
||||
entity_network_id_t &network_id = get_component<entity_network_id_t>(ent);
|
||||
|
||||
destroy_entity.network_sync_id = network_id.network_id;
|
||||
|
||||
auto view = get_entity_registry().view<entity_link_to_client_t>();
|
||||
for (auto [entity, link_to_client] : view.each())
|
||||
{
|
||||
router_send_packet(create_entity, link_to_client.client);
|
||||
router_send_packet(destroy_entity, link_to_client.client);
|
||||
}
|
||||
}
|
||||
|
||||
void deerith::send_create_actual_entities_to_client(client_t *client)
|
||||
{
|
||||
auto entities_view = get_entity_registry().view<entity_network_id_t>();
|
||||
|
||||
for (auto [ent, network_id] : entities_view.each())
|
||||
{
|
||||
send_create_entity_to_client(ent, client);
|
||||
}
|
||||
}
|
||||
@ -6,8 +6,13 @@ namespace deerith
|
||||
{
|
||||
void update_players_characters();
|
||||
void client_connects(client_t *client);
|
||||
void client_disconnects(client_t *client);
|
||||
|
||||
void send_entity_data();
|
||||
|
||||
void send_create_entity_to_all_clients(entity_t ent);
|
||||
void send_create_entity_to_client(entity_t ent, client_t *client);
|
||||
void send_create_actual_entities_to_client(client_t *client);
|
||||
|
||||
void send_delete_entity_to_all_clients(entity_t ent);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user