Network compatibility changes
This commit is contained in:
parent
90db1e0fba
commit
37f3178d33
231
.github/workflows/build.yml
vendored
Normal file
231
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,231 @@
|
||||
name: Build
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- "*"
|
||||
|
||||
jobs:
|
||||
build_windows:
|
||||
name: Build OpenStarbound Windows x64
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: Install CMake & Ninja
|
||||
uses: lukka/get-cmake@latest
|
||||
with:
|
||||
cmakeVersion: 3.29.2
|
||||
|
||||
- name: sccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
variant: sccache
|
||||
key: ${{ github.job }}-${{ runner.os }}
|
||||
max-size: 1000M
|
||||
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
|
||||
- name: vcpkg
|
||||
uses: lukka/run-vcpkg@v11
|
||||
id: runvcpkg
|
||||
with:
|
||||
vcpkgJsonGlob: '**/source/vcpkg.json'
|
||||
vcpkgConfigurationJsonGlob: '**/source/vcpkg-configuration.json'
|
||||
|
||||
- name: Run CMake
|
||||
uses: lukka/run-cmake@v10
|
||||
with:
|
||||
cmakeListsTxtPath: '${{ github.workspace }}/source/CMakeLists.txt'
|
||||
configurePreset: 'windows-release'
|
||||
buildPreset: 'windows-release'
|
||||
testPreset: 'windows-release'
|
||||
|
||||
- name: Run Post-Build Task
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: scripts\ci\windows\post_build.bat
|
||||
|
||||
- name: Assemble Files
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: scripts\ci\windows\assemble.bat
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: OpenStarbound-Windows-All-DevOnly
|
||||
path: dist/*
|
||||
|
||||
- name: Upload Client
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: OpenStarbound-Windows-Client
|
||||
path: client_distribution/*
|
||||
|
||||
- name: Upload Server
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: OpenStarbound-Windows-Server
|
||||
path: server_distribution/*
|
||||
|
||||
- name: Create Installer
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
& "C:\Program Files (x86)\Inno Setup 6\iscc.exe" /Oinstaller scripts\inno\setup.iss
|
||||
|
||||
- name: Upload Installer
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: OpenStarbound-Windows-Installer
|
||||
path: installer/*
|
||||
|
||||
build_linux:
|
||||
name: Build OpenStarbound Linux x86_64
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- name: Install Packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y pkg-config libxmu-dev libxi-dev libgl-dev libglu1-mesa-dev libsdl2-dev
|
||||
|
||||
- name: Install CMake & Ninja
|
||||
uses: lukka/get-cmake@latest
|
||||
with:
|
||||
cmakeVersion: 3.29.2
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: sccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
variant: sccache
|
||||
key: ${{ github.job }}-${{ runner.os }}
|
||||
max-size: 250M
|
||||
|
||||
- name: vcpkg
|
||||
uses: lukka/run-vcpkg@v11
|
||||
id: runvcpkg
|
||||
with:
|
||||
vcpkgJsonGlob: '**/source/vcpkg.json'
|
||||
vcpkgConfigurationJsonGlob: '**/source/vcpkg-configuration.json'
|
||||
|
||||
- name: Run CMake
|
||||
uses: lukka/run-cmake@v10
|
||||
with:
|
||||
cmakeListsTxtPath: '${{ github.workspace }}/source/CMakeLists.txt'
|
||||
configurePreset: 'linux-release'
|
||||
buildPreset: 'linux-release'
|
||||
testPreset: 'linux-release'
|
||||
|
||||
- name: Assemble Files
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: scripts/ci/linux/assemble.sh
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: OpenStarbound-Linux
|
||||
path: dist.tar
|
||||
|
||||
- name: Upload Client Files
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: OpenStarbound-Linux-Client
|
||||
path: client.tar
|
||||
|
||||
- name: Upload Server Files
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: OpenStarbound-Linux-Server
|
||||
path: server.tar
|
||||
|
||||
build-mac-intel:
|
||||
name: Build OpenStarbound macOS x86_64
|
||||
runs-on: macos-13
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: Install CMake & Ninja
|
||||
uses: lukka/get-cmake@latest
|
||||
with:
|
||||
cmakeVersion: 3.29.0
|
||||
|
||||
- name: sccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
variant: sccache
|
||||
key: ${{ github.job }}-Intel-${{ runner.os }}
|
||||
max-size: 250M
|
||||
|
||||
- name: vcpkg
|
||||
uses: lukka/run-vcpkg@v11
|
||||
id: runvcpkg
|
||||
with:
|
||||
vcpkgJsonGlob: '**/source/vcpkg.json'
|
||||
vcpkgConfigurationJsonGlob: '**/source/vcpkg-configuration.json'
|
||||
|
||||
- name: Run CMake
|
||||
uses: lukka/run-cmake@v10
|
||||
with:
|
||||
cmakeListsTxtPath: '${{ github.workspace }}/source/CMakeLists.txt'
|
||||
configurePreset: 'macos-release'
|
||||
buildPreset: 'macos-release'
|
||||
testPreset: 'macos-release'
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: OpenStarbound-macOS-Intel
|
||||
path: dist/*
|
||||
|
||||
build-mac-arm:
|
||||
name: Build OpenStarbound macOS arm64
|
||||
runs-on: macos-14
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: Install CMake & Ninja
|
||||
uses: lukka/get-cmake@latest
|
||||
with:
|
||||
cmakeVersion: 3.29.2
|
||||
|
||||
- name: sccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
variant: sccache
|
||||
key: ${{ github.job }}-ARM-${{ runner.os }}
|
||||
max-size: 250M
|
||||
|
||||
- name: vcpkg
|
||||
uses: lukka/run-vcpkg@v11
|
||||
id: runvcpkg
|
||||
with:
|
||||
vcpkgJsonGlob: '**/source/vcpkg.json'
|
||||
vcpkgConfigurationJsonGlob: '**/source/vcpkg-configuration.json'
|
||||
|
||||
- name: Run CMake
|
||||
uses: lukka/run-cmake@v10
|
||||
with:
|
||||
cmakeListsTxtPath: '${{ github.workspace }}/source/CMakeLists.txt'
|
||||
configurePreset: 'macos-arm-release'
|
||||
buildPreset: 'macos-arm-release'
|
||||
testPreset: 'macos-arm-release'
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: OpenStarbound-macOS-Silicon
|
||||
path: dist/*
|
76
.github/workflows/build_linux.yml
vendored
76
.github/workflows/build_linux.yml
vendored
@ -1,76 +0,0 @@
|
||||
name: Ubuntu Linux
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "*"
|
||||
tags:
|
||||
- "*"
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- "*"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: OpenStarbound Linux x86_64
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- name: Install Packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y pkg-config libxmu-dev libxi-dev libgl-dev libglu1-mesa-dev libsdl2-dev
|
||||
|
||||
- name: Install CMake & Ninja
|
||||
uses: lukka/get-cmake@latest
|
||||
with:
|
||||
cmakeVersion: 3.29.2
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: sccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
variant: sccache
|
||||
key: ${{ github.job }}-${{ runner.os }}
|
||||
max-size: 250M
|
||||
|
||||
- name: vcpkg
|
||||
uses: lukka/run-vcpkg@v11
|
||||
id: runvcpkg
|
||||
with:
|
||||
vcpkgJsonGlob: '**/source/vcpkg.json'
|
||||
vcpkgConfigurationJsonGlob: '**/source/vcpkg-configuration.json'
|
||||
|
||||
- name: Run CMake
|
||||
uses: lukka/run-cmake@v10
|
||||
with:
|
||||
cmakeListsTxtPath: '${{ github.workspace }}/source/CMakeLists.txt'
|
||||
configurePreset: 'linux-release'
|
||||
buildPreset: 'linux-release'
|
||||
testPreset: 'linux-release'
|
||||
|
||||
- name: Assemble Files
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: scripts/ci/linux/assemble.sh
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: OpenStarbound-Linux
|
||||
path: dist.tar
|
||||
|
||||
- name: Upload Client Files
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: OpenStarbound-Linux-Client
|
||||
path: client.tar
|
||||
|
||||
- name: Upload Server Files
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: OpenStarbound-Linux-Server
|
||||
path: server.tar
|
97
.github/workflows/build_macos.yml
vendored
97
.github/workflows/build_macos.yml
vendored
@ -1,97 +0,0 @@
|
||||
name: macOS
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "*"
|
||||
tags:
|
||||
- "*"
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- "*"
|
||||
|
||||
jobs:
|
||||
build-intel:
|
||||
name: OpenStarbound macOS x86_64
|
||||
runs-on: macos-13
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: Install CMake & Ninja
|
||||
uses: lukka/get-cmake@latest
|
||||
with:
|
||||
cmakeVersion: 3.29.0
|
||||
|
||||
- name: sccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
variant: sccache
|
||||
key: ${{ github.job }}-Intel-${{ runner.os }}
|
||||
max-size: 250M
|
||||
|
||||
- name: vcpkg
|
||||
uses: lukka/run-vcpkg@v11
|
||||
id: runvcpkg
|
||||
with:
|
||||
vcpkgJsonGlob: '**/source/vcpkg.json'
|
||||
vcpkgConfigurationJsonGlob: '**/source/vcpkg-configuration.json'
|
||||
|
||||
- name: Run CMake
|
||||
uses: lukka/run-cmake@v10
|
||||
with:
|
||||
cmakeListsTxtPath: '${{ github.workspace }}/source/CMakeLists.txt'
|
||||
configurePreset: 'macos-release'
|
||||
buildPreset: 'macos-release'
|
||||
testPreset: 'macos-release'
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: OpenStarbound-macOS-Intel
|
||||
path: dist/*
|
||||
|
||||
build-arm:
|
||||
name: OpenStarbound macOS arm64
|
||||
runs-on: macos-14
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: Install CMake & Ninja
|
||||
uses: lukka/get-cmake@latest
|
||||
with:
|
||||
cmakeVersion: 3.29.2
|
||||
|
||||
- name: sccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
variant: sccache
|
||||
key: ${{ github.job }}-ARM-${{ runner.os }}
|
||||
max-size: 250M
|
||||
|
||||
- name: vcpkg
|
||||
uses: lukka/run-vcpkg@v11
|
||||
id: runvcpkg
|
||||
with:
|
||||
vcpkgJsonGlob: '**/source/vcpkg.json'
|
||||
vcpkgConfigurationJsonGlob: '**/source/vcpkg-configuration.json'
|
||||
|
||||
- name: Run CMake
|
||||
uses: lukka/run-cmake@v10
|
||||
with:
|
||||
cmakeListsTxtPath: '${{ github.workspace }}/source/CMakeLists.txt'
|
||||
configurePreset: 'macos-arm-release'
|
||||
buildPreset: 'macos-arm-release'
|
||||
testPreset: 'macos-arm-release'
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: OpenStarbound-macOS-Silicon
|
||||
path: dist/*
|
89
.github/workflows/build_windows.yml
vendored
89
.github/workflows/build_windows.yml
vendored
@ -1,89 +0,0 @@
|
||||
name: Windows
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "*"
|
||||
tags:
|
||||
- "*"
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- "*"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build OpenStarbound Windows x64
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: Install CMake & Ninja
|
||||
uses: lukka/get-cmake@latest
|
||||
with:
|
||||
cmakeVersion: 3.29.2
|
||||
|
||||
- name: sccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
variant: sccache
|
||||
key: ${{ github.job }}-${{ runner.os }}
|
||||
max-size: 1000M
|
||||
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
|
||||
- name: vcpkg
|
||||
uses: lukka/run-vcpkg@v11
|
||||
id: runvcpkg
|
||||
with:
|
||||
vcpkgJsonGlob: '**/source/vcpkg.json'
|
||||
vcpkgConfigurationJsonGlob: '**/source/vcpkg-configuration.json'
|
||||
|
||||
- name: Run CMake
|
||||
uses: lukka/run-cmake@v10
|
||||
with:
|
||||
cmakeListsTxtPath: '${{ github.workspace }}/source/CMakeLists.txt'
|
||||
configurePreset: 'windows-release'
|
||||
buildPreset: 'windows-release'
|
||||
testPreset: 'windows-release'
|
||||
|
||||
- name: Run Post-Build Task
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: scripts\ci\windows\post_build.bat
|
||||
|
||||
- name: Assemble Files
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: scripts\ci\windows\assemble.bat
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: OpenStarbound-Windows-All-DevOnly
|
||||
path: dist/*
|
||||
|
||||
- name: Upload Client
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: OpenStarbound-Windows-Client
|
||||
path: client_distribution/*
|
||||
|
||||
- name: Upload Server
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: OpenStarbound-Windows-Server
|
||||
path: server_distribution/*
|
||||
|
||||
- name: Create Installer
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
& "C:\Program Files (x86)\Inno Setup 6\iscc.exe" /Oinstaller scripts\inno\setup.iss
|
||||
|
||||
- name: Upload Installer
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: OpenStarbound-Windows-Installer
|
||||
path: installer/*
|
@ -68,7 +68,7 @@ static void validatePath(AssetPath const& components, bool canContainSubPath, bo
|
||||
throw AssetException::format("Path '{}' cannot contain directives", components);
|
||||
}
|
||||
|
||||
static void validatePath(StringView const& path, bool canContainSubPath, bool canContainDirectives) {
|
||||
static void validatePath(StringView path, bool canContainSubPath, bool canContainDirectives) {
|
||||
std::string_view const& str = path.utf8();
|
||||
|
||||
size_t end = str.find_first_of(":?");
|
||||
|
@ -70,10 +70,12 @@ SET (star_core_HEADERS
|
||||
StarMultiArray.hpp
|
||||
StarMultiArrayInterpolator.hpp
|
||||
StarMultiTable.hpp
|
||||
StarNetCompatibility.hpp
|
||||
StarNetElement.hpp
|
||||
StarNetElementBasicFields.hpp
|
||||
StarNetElementContainers.hpp
|
||||
StarNetElementDynamicGroup.hpp
|
||||
StarNetElementExt.hpp
|
||||
StarNetElementFloatFields.hpp
|
||||
StarNetElementGroup.hpp
|
||||
StarNetElementSignal.hpp
|
||||
|
@ -35,6 +35,13 @@ void DataStream::setStreamCompatibilityVersion(unsigned streamCompatibilityVersi
|
||||
m_streamCompatibilityVersion = streamCompatibilityVersion;
|
||||
}
|
||||
|
||||
void DataStream::setStreamCompatibilityVersion(NetCompatibilityRules const& rules) {
|
||||
if (rules.isLegacy)
|
||||
m_streamCompatibilityVersion = 1;
|
||||
else
|
||||
m_streamCompatibilityVersion = CurrentStreamVersion;
|
||||
}
|
||||
|
||||
ByteArray DataStream::readBytes(size_t len) {
|
||||
ByteArray ba;
|
||||
ba.resize(len);
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "StarString.hpp"
|
||||
#include "StarNetCompatibility.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
@ -12,7 +13,7 @@ public:
|
||||
DataStream();
|
||||
virtual ~DataStream() = default;
|
||||
|
||||
static unsigned const CurrentStreamVersion = 1;
|
||||
static unsigned const CurrentStreamVersion = 2;
|
||||
|
||||
// DataStream defaults to big-endian order for all primitive types
|
||||
ByteOrder byteOrder() const;
|
||||
@ -27,7 +28,7 @@ public:
|
||||
// changed for compatibility with older versions of DataStream serialization.
|
||||
unsigned streamCompatibilityVersion() const;
|
||||
void setStreamCompatibilityVersion(unsigned streamCompatibilityVersion);
|
||||
|
||||
void setStreamCompatibilityVersion(NetCompatibilityRules const& rules);
|
||||
// Do direct reads and writes
|
||||
virtual void readData(char* data, size_t len) = 0;
|
||||
virtual void writeData(char const* data, size_t len) = 0;
|
||||
|
@ -126,8 +126,8 @@ private:
|
||||
class DataStreamExternalBuffer : public DataStream {
|
||||
public:
|
||||
DataStreamExternalBuffer();
|
||||
explicit DataStreamExternalBuffer(ByteArray const& byteArray);
|
||||
explicit DataStreamExternalBuffer(DataStreamBuffer const& buffer);
|
||||
DataStreamExternalBuffer(ByteArray const& byteArray);
|
||||
DataStreamExternalBuffer(DataStreamBuffer const& buffer);
|
||||
|
||||
DataStreamExternalBuffer(DataStreamExternalBuffer const& buffer) = default;
|
||||
DataStreamExternalBuffer(char const* externalData, size_t len);
|
||||
|
41
source/core/StarNetCompatibility.hpp
Normal file
41
source/core/StarNetCompatibility.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
#include "StarDataStream.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
|
||||
enum class NetCompatibilityFilter {
|
||||
None = 0,
|
||||
Old = 1,
|
||||
New = 2
|
||||
};
|
||||
|
||||
struct NetCompatibilityRules {
|
||||
NetCompatibilityRules() = default;
|
||||
NetCompatibilityRules(uint64_t) = delete;
|
||||
NetCompatibilityRules(bool legacy);
|
||||
|
||||
bool checkFilter(NetCompatibilityFilter const& filter) const;
|
||||
|
||||
bool isLegacy = false;
|
||||
};
|
||||
|
||||
inline NetCompatibilityRules::NetCompatibilityRules(bool legacy) : isLegacy(legacy) {}
|
||||
|
||||
inline bool NetCompatibilityRules::checkFilter(NetCompatibilityFilter const& filter) const {
|
||||
if (filter == NetCompatibilityFilter::None)
|
||||
return true;
|
||||
else if (isLegacy)
|
||||
return filter == NetCompatibilityFilter::Old;
|
||||
else
|
||||
return filter == NetCompatibilityFilter::New;
|
||||
}
|
||||
|
||||
template <>
|
||||
struct hash<NetCompatibilityRules> {
|
||||
size_t operator()(NetCompatibilityRules const& s) const {
|
||||
return s.isLegacy;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
@ -7,8 +7,8 @@ uint64_t NetElementVersion::current() const {
|
||||
return m_version;
|
||||
}
|
||||
|
||||
void NetElementVersion::increment() {
|
||||
++m_version;
|
||||
uint64_t NetElementVersion::increment() {
|
||||
return ++m_version;
|
||||
}
|
||||
|
||||
void NetElement::enableNetInterpolation(float) {}
|
||||
|
@ -9,7 +9,7 @@ namespace Star {
|
||||
class NetElementVersion {
|
||||
public:
|
||||
uint64_t current() const;
|
||||
void increment();
|
||||
uint64_t increment();
|
||||
|
||||
private:
|
||||
uint64_t m_version = 0;
|
||||
@ -20,15 +20,15 @@ class NetElement {
|
||||
public:
|
||||
virtual ~NetElement() = default;
|
||||
|
||||
// A network of NetElements will have a shared monotinically increasing
|
||||
// A network of NetElements will have a shared monotonically increasing
|
||||
// NetElementVersion. When elements are updated, they will mark the version
|
||||
// number at the time they are updated so that a delta can be constructed
|
||||
// that contains only changes since any past version.
|
||||
virtual void initNetVersion(NetElementVersion const* version = nullptr) = 0;
|
||||
|
||||
// Full store / load of the entire element.
|
||||
virtual void netStore(DataStream& ds) const = 0;
|
||||
virtual void netLoad(DataStream& ds) = 0;
|
||||
virtual void netStore(DataStream& ds, NetCompatibilityRules rules) const = 0;
|
||||
virtual void netLoad(DataStream& ds, NetCompatibilityRules rules) = 0;
|
||||
|
||||
// Enables interpolation mode. If interpolation mode is enabled, then
|
||||
// NetElements will delay presenting incoming delta data for the
|
||||
@ -46,14 +46,32 @@ public:
|
||||
// the version at the time of the *last* call to writeDelta, + 1. If
|
||||
// fromVersion is 0, this will always write the full state. Should return
|
||||
// true if a delta was needed and was written to DataStream, false otherwise.
|
||||
virtual bool writeNetDelta(DataStream& ds, uint64_t fromVersion) const = 0;
|
||||
virtual bool writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) const = 0;
|
||||
// Read a delta written by writeNetDelta. 'interpolationTime' is the time in
|
||||
// the future that data from this delta should be delayed and smoothed into,
|
||||
// if interpolation is enabled.
|
||||
virtual void readNetDelta(DataStream& ds, float interpolationTime = 0.0) = 0;
|
||||
virtual void readNetDelta(DataStream& ds, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) = 0;
|
||||
// When extrapolating, it is important to notify when a delta WOULD have been
|
||||
// received even if no deltas are produced, so no extrapolation takes place.
|
||||
virtual void blankNetDelta(float interpolationTime);
|
||||
|
||||
NetCompatibilityFilter netCompatibilityFilter() const;
|
||||
void setNetCompatibilityFilter(NetCompatibilityFilter netFilter);
|
||||
bool checkWithRules(NetCompatibilityRules const& rules) const;
|
||||
private:
|
||||
NetCompatibilityFilter m_netCompatibilityFilter = NetCompatibilityFilter::None;
|
||||
};
|
||||
|
||||
inline NetCompatibilityFilter NetElement::netCompatibilityFilter() const {
|
||||
return m_netCompatibilityFilter;
|
||||
}
|
||||
|
||||
inline void NetElement::setNetCompatibilityFilter(NetCompatibilityFilter netFilter) {
|
||||
m_netCompatibilityFilter = netFilter;
|
||||
}
|
||||
|
||||
inline bool NetElement::checkWithRules(NetCompatibilityRules const& rules) const {
|
||||
return rules.checkFilter(m_netCompatibilityFilter);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -49,8 +49,8 @@ void NetElementEvent::setIgnoreOccurrencesOnNetLoad(bool ignoreOccurrencesOnNetL
|
||||
m_ignoreOccurrencesOnNetLoad = ignoreOccurrencesOnNetLoad;
|
||||
}
|
||||
|
||||
void NetElementEvent::netLoad(DataStream& ds) {
|
||||
NetElementUInt::netLoad(ds);
|
||||
void NetElementEvent::netLoad(DataStream& ds, NetCompatibilityRules rules) {
|
||||
NetElementUInt::netLoad(ds, rules);
|
||||
if (m_ignoreOccurrencesOnNetLoad)
|
||||
ignoreOccurrences();
|
||||
}
|
||||
|
@ -38,11 +38,11 @@ public:
|
||||
void disableNetInterpolation() override;
|
||||
void tickNetInterpolation(float dt) override;
|
||||
|
||||
void netStore(DataStream& ds) const override;
|
||||
void netLoad(DataStream& ds) override;
|
||||
void netStore(DataStream& ds, NetCompatibilityRules rules = {}) const override;
|
||||
void netLoad(DataStream& ds, NetCompatibilityRules rules) override;
|
||||
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromVersion) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0f) override;
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules = {}) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override;
|
||||
|
||||
protected:
|
||||
virtual void readData(DataStream& ds, T& t) const = 0;
|
||||
@ -107,7 +107,7 @@ public:
|
||||
void ignoreOccurrences();
|
||||
void setIgnoreOccurrencesOnNetLoad(bool ignoreOccurrencesOnNetLoad);
|
||||
|
||||
void netLoad(DataStream& ds) override;
|
||||
void netLoad(DataStream& ds, NetCompatibilityRules rules) override;
|
||||
|
||||
protected:
|
||||
void updated() override;
|
||||
@ -211,7 +211,8 @@ void NetElementBasicField<T>::tickNetInterpolation(float dt) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void NetElementBasicField<T>::netStore(DataStream& ds) const {
|
||||
void NetElementBasicField<T>::netStore(DataStream& ds, NetCompatibilityRules rules) const {
|
||||
if (!checkWithRules(rules)) return;
|
||||
if (m_pendingInterpolatedValues && !m_pendingInterpolatedValues->empty())
|
||||
writeData(ds, m_pendingInterpolatedValues->last().second);
|
||||
else
|
||||
@ -219,7 +220,8 @@ void NetElementBasicField<T>::netStore(DataStream& ds) const {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void NetElementBasicField<T>::netLoad(DataStream& ds) {
|
||||
void NetElementBasicField<T>::netLoad(DataStream& ds, NetCompatibilityRules rules) {
|
||||
if (!checkWithRules(rules)) return;
|
||||
readData(ds, m_value);
|
||||
m_latestUpdateVersion = m_netVersion ? m_netVersion->current() : 0;
|
||||
updated();
|
||||
@ -228,7 +230,8 @@ void NetElementBasicField<T>::netLoad(DataStream& ds) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool NetElementBasicField<T>::writeNetDelta(DataStream& ds, uint64_t fromVersion) const {
|
||||
bool NetElementBasicField<T>::writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) const {
|
||||
if (!checkWithRules(rules)) return false;
|
||||
if (m_latestUpdateVersion < fromVersion)
|
||||
return false;
|
||||
|
||||
@ -236,11 +239,13 @@ bool NetElementBasicField<T>::writeNetDelta(DataStream& ds, uint64_t fromVersion
|
||||
writeData(ds, m_pendingInterpolatedValues->last().second);
|
||||
else
|
||||
writeData(ds, m_value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void NetElementBasicField<T>::readNetDelta(DataStream& ds, float interpolationTime) {
|
||||
void NetElementBasicField<T>::readNetDelta(DataStream& ds, float interpolationTime, NetCompatibilityRules rules) {
|
||||
if (!checkWithRules(rules)) return;
|
||||
T t;
|
||||
readData(ds, t);
|
||||
m_latestUpdateVersion = m_netVersion ? m_netVersion->current() : 0;
|
||||
|
@ -26,11 +26,12 @@ public:
|
||||
void disableNetInterpolation() override;
|
||||
void tickNetInterpolation(float dt) override;
|
||||
|
||||
void netStore(DataStream& ds) const override;
|
||||
void netLoad(DataStream& ds) override;
|
||||
void netStore(DataStream& ds, NetCompatibilityRules rules = {}) const override;
|
||||
void netLoad(DataStream& ds, NetCompatibilityRules rules) override;
|
||||
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromVersion) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0f) override;
|
||||
bool shouldWriteNetDelta(uint64_t fromVersion, NetCompatibilityRules rules = {}) const;
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules = {}) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override;
|
||||
|
||||
mapped_type const& get(key_type const& key) const;
|
||||
mapped_type const* ptr(key_type const& key) const;
|
||||
@ -77,6 +78,8 @@ public:
|
||||
template <typename MapType>
|
||||
void setContents(MapType const& values);
|
||||
|
||||
uint64_t changeDataLastVersion() const;
|
||||
|
||||
private:
|
||||
// If a delta is written from further back than this many steps, the delta
|
||||
// will fall back to a full serialization of the entire state.
|
||||
@ -152,7 +155,8 @@ void NetElementMapWrapper<BaseMap>::tickNetInterpolation(float dt) {
|
||||
}
|
||||
|
||||
template <typename BaseMap>
|
||||
void NetElementMapWrapper<BaseMap>::netStore(DataStream& ds) const {
|
||||
void NetElementMapWrapper<BaseMap>::netStore(DataStream& ds, NetCompatibilityRules rules) const {
|
||||
if (!checkWithRules(rules)) return;
|
||||
ds.writeVlqU(BaseMap::size() + m_pendingChangeData.size());
|
||||
for (auto const& pair : *this)
|
||||
writeChange(ds, SetChange{pair.first, pair.second});
|
||||
@ -162,7 +166,8 @@ void NetElementMapWrapper<BaseMap>::netStore(DataStream& ds) const {
|
||||
}
|
||||
|
||||
template <typename BaseMap>
|
||||
void NetElementMapWrapper<BaseMap>::netLoad(DataStream& ds) {
|
||||
void NetElementMapWrapper<BaseMap>::netLoad(DataStream& ds, NetCompatibilityRules rules) {
|
||||
if (!checkWithRules(rules)) return;
|
||||
m_changeData.clear();
|
||||
m_changeDataLastVersion = m_netVersion ? m_netVersion->current() : 0;
|
||||
m_pendingChangeData.clear();
|
||||
@ -181,13 +186,27 @@ void NetElementMapWrapper<BaseMap>::netLoad(DataStream& ds) {
|
||||
}
|
||||
|
||||
template <typename BaseMap>
|
||||
bool NetElementMapWrapper<BaseMap>::writeNetDelta(DataStream& ds, uint64_t fromVersion) const {
|
||||
bool NetElementMapWrapper<BaseMap>::shouldWriteNetDelta(uint64_t fromVersion, NetCompatibilityRules rules) const {
|
||||
if (!checkWithRules(rules)) return false;
|
||||
if (fromVersion < m_changeDataLastVersion)
|
||||
return true;
|
||||
|
||||
for (auto const& p : m_changeData)
|
||||
if (p.first >= fromVersion)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename BaseMap>
|
||||
bool NetElementMapWrapper<BaseMap>::writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) const {
|
||||
if (!checkWithRules(rules)) return false;
|
||||
bool deltaWritten = false;
|
||||
|
||||
if (fromVersion < m_changeDataLastVersion) {
|
||||
deltaWritten = true;
|
||||
ds.writeVlqU(1);
|
||||
netStore(ds);
|
||||
netStore(ds, rules);
|
||||
|
||||
} else {
|
||||
for (auto const& p : m_changeData) {
|
||||
@ -206,13 +225,14 @@ bool NetElementMapWrapper<BaseMap>::writeNetDelta(DataStream& ds, uint64_t fromV
|
||||
}
|
||||
|
||||
template <typename BaseMap>
|
||||
void NetElementMapWrapper<BaseMap>::readNetDelta(DataStream& ds, float interpolationTime) {
|
||||
void NetElementMapWrapper<BaseMap>::readNetDelta(DataStream& ds, float interpolationTime, NetCompatibilityRules rules) {
|
||||
if (!checkWithRules(rules)) return;
|
||||
while (true) {
|
||||
uint64_t code = ds.readVlqU();
|
||||
if (code == 0) {
|
||||
break;
|
||||
} else if (code == 1) {
|
||||
netLoad(ds);
|
||||
netLoad(ds, rules);
|
||||
} else if (code == 2) {
|
||||
auto change = readChange(ds);
|
||||
addChangeData(change);
|
||||
@ -381,6 +401,11 @@ void NetElementMapWrapper<BaseMap>::setContents(MapType const& values) {
|
||||
reset(BaseMap::from(values));
|
||||
}
|
||||
|
||||
template <typename BaseMap>
|
||||
uint64_t NetElementMapWrapper<BaseMap>::changeDataLastVersion() const {
|
||||
return m_changeDataLastVersion;
|
||||
}
|
||||
|
||||
template <typename BaseMap>
|
||||
void NetElementMapWrapper<BaseMap>::writeChange(DataStream& ds, ElementChange const& change) {
|
||||
if (auto sc = change.template ptr<SetChange>()) {
|
||||
|
@ -45,11 +45,11 @@ public:
|
||||
void disableNetInterpolation() override;
|
||||
void tickNetInterpolation(float dt) override;
|
||||
|
||||
void netStore(DataStream& ds) const override;
|
||||
void netLoad(DataStream& ds) override;
|
||||
void netStore(DataStream& ds, NetCompatibilityRules rules = {}) const override;
|
||||
void netLoad(DataStream& ds, NetCompatibilityRules rules) override;
|
||||
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromVersion) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0f) override;
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules = {}) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override;
|
||||
void blankNetDelta(float interpolationTime = 0.0f) override;
|
||||
|
||||
private:
|
||||
@ -89,7 +89,7 @@ template <typename Element>
|
||||
auto NetElementDynamicGroup<Element>::addNetElement(ElementPtr element) -> ElementId {
|
||||
readyElement(element);
|
||||
DataStreamBuffer storeBuffer;
|
||||
element->netStore(storeBuffer);
|
||||
element->netStore(storeBuffer, {});
|
||||
auto id = m_idMap.add(std::move(element));
|
||||
|
||||
addChangeData(ElementAddition(id, storeBuffer.takeData()));
|
||||
@ -134,7 +134,7 @@ void NetElementDynamicGroup<Element>::initNetVersion(NetElementVersion const* ve
|
||||
for (auto& pair : m_idMap) {
|
||||
pair.second->initNetVersion(m_netVersion);
|
||||
DataStreamBuffer storeBuffer;
|
||||
pair.second->netStore(storeBuffer);
|
||||
pair.second->netStore(storeBuffer, {});
|
||||
addChangeData(ElementAddition(pair.first, storeBuffer.takeData()));
|
||||
}
|
||||
}
|
||||
@ -162,19 +162,22 @@ void NetElementDynamicGroup<Element>::tickNetInterpolation(float dt) {
|
||||
}
|
||||
|
||||
template <typename Element>
|
||||
void NetElementDynamicGroup<Element>::netStore(DataStream& ds) const {
|
||||
void NetElementDynamicGroup<Element>::netStore(DataStream& ds, NetCompatibilityRules rules) const {
|
||||
if (!checkWithRules(rules)) return;
|
||||
ds.writeVlqU(m_idMap.size());
|
||||
|
||||
m_buffer.setStreamCompatibilityVersion(rules);
|
||||
for (auto& pair : m_idMap) {
|
||||
ds.writeVlqU(pair.first);
|
||||
pair.second->netStore(m_buffer);
|
||||
pair.second->netStore(m_buffer, rules);
|
||||
ds.write(m_buffer.data());
|
||||
m_buffer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Element>
|
||||
void NetElementDynamicGroup<Element>::netLoad(DataStream& ds) {
|
||||
void NetElementDynamicGroup<Element>::netLoad(DataStream& ds, NetCompatibilityRules rules) {
|
||||
if (!checkWithRules(rules)) return;
|
||||
m_changeData.clear();
|
||||
m_changeDataLastVersion = m_netVersion ? m_netVersion->current() : 0;
|
||||
m_idMap.clear();
|
||||
@ -188,7 +191,7 @@ void NetElementDynamicGroup<Element>::netLoad(DataStream& ds) {
|
||||
DataStreamBuffer storeBuffer(ds.read<ByteArray>());
|
||||
|
||||
ElementPtr element = make_shared<Element>();
|
||||
element->netLoad(storeBuffer);
|
||||
element->netLoad(storeBuffer, rules);
|
||||
readyElement(element);
|
||||
|
||||
m_idMap.add(id, std::move(element));
|
||||
@ -197,10 +200,11 @@ void NetElementDynamicGroup<Element>::netLoad(DataStream& ds) {
|
||||
}
|
||||
|
||||
template <typename Element>
|
||||
bool NetElementDynamicGroup<Element>::writeNetDelta(DataStream& ds, uint64_t fromVersion) const {
|
||||
bool NetElementDynamicGroup<Element>::writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) const {
|
||||
if (!checkWithRules(rules)) return false;
|
||||
if (fromVersion < m_changeDataLastVersion) {
|
||||
ds.write<bool>(true);
|
||||
netStore(ds);
|
||||
netStore(ds, rules);
|
||||
return true;
|
||||
|
||||
} else {
|
||||
@ -220,8 +224,9 @@ bool NetElementDynamicGroup<Element>::writeNetDelta(DataStream& ds, uint64_t fro
|
||||
}
|
||||
}
|
||||
|
||||
m_buffer.setStreamCompatibilityVersion(rules);
|
||||
for (auto& p : m_idMap) {
|
||||
if (p.second->writeNetDelta(m_buffer, fromVersion)) {
|
||||
if (p.second->writeNetDelta(m_buffer, fromVersion, rules)) {
|
||||
willWrite();
|
||||
ds.writeVlqU(p.first + 1);
|
||||
ds.writeBytes(m_buffer.data());
|
||||
@ -237,10 +242,11 @@ bool NetElementDynamicGroup<Element>::writeNetDelta(DataStream& ds, uint64_t fro
|
||||
}
|
||||
|
||||
template <typename Element>
|
||||
void NetElementDynamicGroup<Element>::readNetDelta(DataStream& ds, float interpolationTime) {
|
||||
void NetElementDynamicGroup<Element>::readNetDelta(DataStream& ds, float interpolationTime, NetCompatibilityRules rules) {
|
||||
if (!checkWithRules(rules)) return;
|
||||
bool isFull = ds.read<bool>();
|
||||
if (isFull) {
|
||||
netLoad(ds);
|
||||
netLoad(ds, rules);
|
||||
} else {
|
||||
while (true) {
|
||||
uint64_t code = ds.readVlqU();
|
||||
@ -256,7 +262,7 @@ void NetElementDynamicGroup<Element>::readNetDelta(DataStream& ds, float interpo
|
||||
} else if (auto addition = changeUpdate.template ptr<ElementAddition>()) {
|
||||
ElementPtr element = make_shared<Element>();
|
||||
DataStreamBuffer storeBuffer(std::move(get<1>(*addition)));
|
||||
element->netLoad(storeBuffer);
|
||||
element->netLoad(storeBuffer, rules);
|
||||
readyElement(element);
|
||||
m_idMap.add(get<0>(*addition), std::move(element));
|
||||
} else if (auto removal = changeUpdate.template ptr<ElementRemoval>()) {
|
||||
@ -265,7 +271,7 @@ void NetElementDynamicGroup<Element>::readNetDelta(DataStream& ds, float interpo
|
||||
} else {
|
||||
ElementId elementId = code - 1;
|
||||
auto const& element = m_idMap.get(elementId);
|
||||
element->readNetDelta(ds, interpolationTime);
|
||||
element->readNetDelta(ds, interpolationTime, rules);
|
||||
if (m_interpolationEnabled)
|
||||
m_receivedDeltaIds.add(elementId);
|
||||
}
|
||||
|
85
source/core/StarNetElementExt.hpp
Normal file
85
source/core/StarNetElementExt.hpp
Normal file
@ -0,0 +1,85 @@
|
||||
#pragma once
|
||||
|
||||
#include "StarNetElement.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
template <typename BaseNetElement>
|
||||
class NetElementOverride : public BaseNetElement {
|
||||
public:
|
||||
void netStore(DataStream& ds, NetCompatibilityRules rules = {}) const override;
|
||||
void netLoad(DataStream& ds, NetCompatibilityRules rules) override;
|
||||
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules = {}) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override;
|
||||
|
||||
typedef std::function<void(DataStream&, NetCompatibilityRules)> NetStorer;
|
||||
typedef std::function<void(DataStream&, NetCompatibilityRules)> NetLoader;
|
||||
typedef std::function<bool(DataStream&, uint64_t, NetCompatibilityRules)> NetDeltaWriter;
|
||||
typedef std::function<void(DataStream&, float, NetCompatibilityRules)> NetDeltaReader;
|
||||
|
||||
void setNetStorer(NetStorer);
|
||||
void setNetLoader(NetLoader);
|
||||
void setNetDeltaWriter(NetDeltaWriter);
|
||||
void setNetDeltaReader(NetDeltaReader);
|
||||
void setOverrides(NetStorer netStorer, NetLoader netLoader,
|
||||
NetDeltaWriter netDeltaWriter, NetDeltaReader netDeltaReader);
|
||||
|
||||
private:
|
||||
NetStorer m_netStorer;
|
||||
NetLoader m_netLoader;
|
||||
|
||||
NetDeltaWriter m_netDeltaWriter;
|
||||
NetDeltaReader m_netDeltaReader;
|
||||
};
|
||||
|
||||
template <typename BaseNetElement>
|
||||
void NetElementOverride<BaseNetElement>::netStore(DataStream& ds, NetCompatibilityRules rules) const {
|
||||
if (m_netStorer)
|
||||
m_netStorer(ds, rules);
|
||||
else
|
||||
BaseNetElement::netStore(ds, rules);
|
||||
}
|
||||
|
||||
template <typename BaseNetElement>
|
||||
void NetElementOverride<BaseNetElement>::netLoad(DataStream& ds, NetCompatibilityRules rules) {
|
||||
if (m_netLoader)
|
||||
m_netLoader(ds, rules);
|
||||
else
|
||||
BaseNetElement::netLoad(ds, rules);
|
||||
}
|
||||
|
||||
template <typename BaseNetElement>
|
||||
bool NetElementOverride<BaseNetElement>::writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) const {
|
||||
if (m_netDeltaWriter)
|
||||
return m_netDeltaWriter(ds, fromVersion, rules);
|
||||
else
|
||||
return BaseNetElement::writeNetDelta(ds, fromVersion, rules);
|
||||
}
|
||||
|
||||
template <typename BaseNetElement>
|
||||
void NetElementOverride<BaseNetElement>::readNetDelta(DataStream& ds, float interpolationTime, NetCompatibilityRules rules) {
|
||||
if (m_netDeltaReader)
|
||||
m_netDeltaReader(ds, interpolationTime, rules);
|
||||
else
|
||||
BaseNetElement::readNetDelta(ds, interpolationTime, rules);
|
||||
}
|
||||
|
||||
template <typename BaseNetElement>
|
||||
inline void NetElementOverride<BaseNetElement>::setNetStorer(NetStorer f) { m_netStorer = std::move(f); }
|
||||
template <typename BaseNetElement>
|
||||
inline void NetElementOverride<BaseNetElement>::setNetLoader(NetLoader f) { m_netLoader = std::move(f); }
|
||||
template <typename BaseNetElement>
|
||||
inline void NetElementOverride<BaseNetElement>::setNetDeltaWriter(NetDeltaWriter f) { m_netDeltaWriter = std::move(f); }
|
||||
template <typename BaseNetElement>
|
||||
inline void NetElementOverride<BaseNetElement>::setNetDeltaReader(NetDeltaReader f) { m_netDeltaReader = std::move(f); }
|
||||
|
||||
template <typename BaseNetElement>
|
||||
inline void NetElementOverride<BaseNetElement>::setOverrides(NetStorer netStorer, NetLoader netLoader, NetDeltaWriter netDeltaWriter, NetDeltaReader netDeltaReader) {
|
||||
m_netStorer = std::move(netStorer);
|
||||
m_netLoader = std::move(netLoader);
|
||||
m_netDeltaWriter = std::move(netDeltaWriter);
|
||||
m_netDeltaReader = std::move(netDeltaReader);
|
||||
}
|
||||
|
||||
}
|
@ -36,11 +36,11 @@ public:
|
||||
void disableNetInterpolation() override;
|
||||
void tickNetInterpolation(float dt) override;
|
||||
|
||||
void netStore(DataStream& ds) const override;
|
||||
void netLoad(DataStream& ds) override;
|
||||
void netStore(DataStream& ds, NetCompatibilityRules rules = {}) const override;
|
||||
void netLoad(DataStream& ds, NetCompatibilityRules rules) override;
|
||||
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromVersion) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0f) override;
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules = {}) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override;
|
||||
void blankNetDelta(float interpolationTime = 0.0f) override;
|
||||
|
||||
private:
|
||||
@ -131,7 +131,8 @@ void NetElementFloating<T>::tickNetInterpolation(float dt) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void NetElementFloating<T>::netStore(DataStream& ds) const {
|
||||
void NetElementFloating<T>::netStore(DataStream& ds, NetCompatibilityRules rules) const {
|
||||
if (!checkWithRules(rules)) return;
|
||||
if (m_interpolationDataPoints)
|
||||
writeValue(ds, m_interpolationDataPoints->last().second);
|
||||
else
|
||||
@ -139,7 +140,8 @@ void NetElementFloating<T>::netStore(DataStream& ds) const {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void NetElementFloating<T>::netLoad(DataStream& ds) {
|
||||
void NetElementFloating<T>::netLoad(DataStream& ds, NetCompatibilityRules rules) {
|
||||
if (!checkWithRules(rules)) return;
|
||||
m_value = readValue(ds);
|
||||
m_latestUpdateVersion = m_netVersion ? m_netVersion->current() : 0;
|
||||
if (m_interpolationDataPoints) {
|
||||
@ -149,7 +151,8 @@ void NetElementFloating<T>::netLoad(DataStream& ds) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool NetElementFloating<T>::writeNetDelta(DataStream& ds, uint64_t fromVersion) const {
|
||||
bool NetElementFloating<T>::writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) const {
|
||||
if (!checkWithRules(rules)) return false;
|
||||
if (m_latestUpdateVersion < fromVersion)
|
||||
return false;
|
||||
|
||||
@ -162,7 +165,7 @@ bool NetElementFloating<T>::writeNetDelta(DataStream& ds, uint64_t fromVersion)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void NetElementFloating<T>::readNetDelta(DataStream& ds, float interpolationTime) {
|
||||
void NetElementFloating<T>::readNetDelta(DataStream& ds, float interpolationTime, NetCompatibilityRules rules) {
|
||||
T t = readValue(ds);
|
||||
|
||||
m_latestUpdateVersion = m_netVersion ? m_netVersion->current() : 0;
|
||||
|
@ -21,14 +21,18 @@ void NetElementGroup::initNetVersion(NetElementVersion const* version) {
|
||||
p.first->initNetVersion(m_version);
|
||||
}
|
||||
|
||||
void NetElementGroup::netStore(DataStream& ds) const {
|
||||
void NetElementGroup::netStore(DataStream& ds, NetCompatibilityRules rules) const {
|
||||
if (!checkWithRules(rules)) return;
|
||||
for (auto& p : m_elements)
|
||||
p.first->netStore(ds);
|
||||
if (p.first->checkWithRules(rules))
|
||||
p.first->netStore(ds, rules);
|
||||
}
|
||||
|
||||
void NetElementGroup::netLoad(DataStream& ds) {
|
||||
void NetElementGroup::netLoad(DataStream& ds, NetCompatibilityRules rules) {
|
||||
if (!checkWithRules(rules)) return;
|
||||
for (auto& p : m_elements)
|
||||
p.first->netLoad(ds);
|
||||
if (p.first->checkWithRules(rules))
|
||||
p.first->netLoad(ds, rules);
|
||||
}
|
||||
|
||||
void NetElementGroup::enableNetInterpolation(float extrapolationHint) {
|
||||
@ -56,17 +60,23 @@ void NetElementGroup::tickNetInterpolation(float dt) {
|
||||
}
|
||||
}
|
||||
|
||||
bool NetElementGroup::writeNetDelta(DataStream& ds, uint64_t fromStep) const {
|
||||
bool NetElementGroup::writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) const {
|
||||
if (!checkWithRules(rules)) return false;
|
||||
if (m_elements.size() == 0) {
|
||||
return false;
|
||||
} else if (m_elements.size() == 1) {
|
||||
return m_elements[0].first->writeNetDelta(ds, fromStep);
|
||||
return m_elements[0].first->writeNetDelta(ds, fromVersion, rules);
|
||||
} else {
|
||||
bool deltaWritten = false;
|
||||
for (uint64_t i = 0; i < m_elements.size(); ++i) {
|
||||
if (m_elements[i].first->writeNetDelta(m_buffer, fromStep)) {
|
||||
uint64_t i = 0;
|
||||
m_buffer.setStreamCompatibilityVersion(rules);
|
||||
for (auto& element : m_elements) {
|
||||
if (!element.first->checkWithRules(rules))
|
||||
continue;
|
||||
++i;
|
||||
if (element.first->writeNetDelta(m_buffer, fromVersion, rules)) {
|
||||
deltaWritten = true;
|
||||
ds.writeVlqU(i + 1);
|
||||
ds.writeVlqU(i);
|
||||
ds.writeBytes(m_buffer.data());
|
||||
m_buffer.clear();
|
||||
}
|
||||
@ -77,23 +87,28 @@ bool NetElementGroup::writeNetDelta(DataStream& ds, uint64_t fromStep) const {
|
||||
}
|
||||
}
|
||||
|
||||
void NetElementGroup::readNetDelta(DataStream& ds, float interpolationTime) {
|
||||
void NetElementGroup::readNetDelta(DataStream& ds, float interpolationTime, NetCompatibilityRules rules) {
|
||||
if (!checkWithRules(rules)) return;
|
||||
if (m_elements.size() == 0) {
|
||||
throw IOException("readNetDelta called on empty NetElementGroup");
|
||||
} else if (m_elements.size() == 1) {
|
||||
m_elements[0].first->readNetDelta(ds, interpolationTime);
|
||||
m_elements[0].first->readNetDelta(ds, interpolationTime, rules);
|
||||
} else {
|
||||
uint64_t readIndex = ds.readVlqU();
|
||||
for (uint64_t i = 0; i < m_elements.size(); ++i) {
|
||||
uint64_t i = 0;
|
||||
for (auto& element : m_elements) {
|
||||
if (!element.first->checkWithRules(rules))
|
||||
continue;
|
||||
if (readIndex == 0 || readIndex - 1 > i) {
|
||||
if (m_interpolationEnabled)
|
||||
m_elements[i].first->blankNetDelta(interpolationTime);
|
||||
} else if (readIndex - 1 == i) {
|
||||
m_elements[i].first->readNetDelta(ds, interpolationTime);
|
||||
m_elements[i].first->readNetDelta(ds, interpolationTime, rules);
|
||||
readIndex = ds.readVlqU();
|
||||
} else {
|
||||
throw IOException("group indexes out of order in NetElementGroup::readNetDelta");
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,15 +24,15 @@ public:
|
||||
|
||||
void initNetVersion(NetElementVersion const* version = nullptr) override;
|
||||
|
||||
void netStore(DataStream& ds) const override;
|
||||
void netLoad(DataStream& ds) override;
|
||||
void netStore(DataStream& ds, NetCompatibilityRules rules = {}) const override;
|
||||
void netLoad(DataStream& ds, NetCompatibilityRules rules) override;
|
||||
|
||||
void enableNetInterpolation(float extrapolationHint = 0.0f) override;
|
||||
void disableNetInterpolation() override;
|
||||
void tickNetInterpolation(float dt) override;
|
||||
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromVersion) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0f) override;
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules = {}) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override;
|
||||
void blankNetDelta(float interpolationTime) override;
|
||||
|
||||
NetElementVersion const* netVersion() const;
|
||||
|
@ -16,15 +16,15 @@ public:
|
||||
|
||||
void initNetVersion(NetElementVersion const* version = nullptr) override;
|
||||
|
||||
void netStore(DataStream& ds) const override;
|
||||
void netLoad(DataStream& ds) override;
|
||||
void netStore(DataStream& ds, NetCompatibilityRules rules = {}) const override;
|
||||
void netLoad(DataStream& ds, NetCompatibilityRules rules) override;
|
||||
|
||||
void enableNetInterpolation(float extrapolationHint = 0.0f) override;
|
||||
void disableNetInterpolation() override;
|
||||
void tickNetInterpolation(float dt) override;
|
||||
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromVersion) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0) override;
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules = {}) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override;
|
||||
|
||||
void send(Signal signal);
|
||||
List<Signal> receive();
|
||||
@ -55,10 +55,10 @@ void NetElementSignal<Signal>::initNetVersion(NetElementVersion const* version)
|
||||
}
|
||||
|
||||
template <typename Signal>
|
||||
void NetElementSignal<Signal>::netStore(DataStream&) const {}
|
||||
void NetElementSignal<Signal>::netStore(DataStream&, NetCompatibilityRules) const {}
|
||||
|
||||
template <typename Signal>
|
||||
void NetElementSignal<Signal>::netLoad(DataStream&) {
|
||||
void NetElementSignal<Signal>::netLoad(DataStream&, NetCompatibilityRules) {
|
||||
}
|
||||
|
||||
template <typename Signal>
|
||||
@ -83,7 +83,8 @@ void NetElementSignal<Signal>::tickNetInterpolation(float dt) {
|
||||
}
|
||||
|
||||
template <typename Signal>
|
||||
bool NetElementSignal<Signal>::writeNetDelta(DataStream& ds, uint64_t fromVersion) const {
|
||||
bool NetElementSignal<Signal>::writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) const {
|
||||
if (!checkWithRules(rules)) return false;
|
||||
size_t numToWrite = 0;
|
||||
for (auto const& p : m_signals) {
|
||||
if (p.version >= fromVersion)
|
||||
@ -103,7 +104,8 @@ bool NetElementSignal<Signal>::writeNetDelta(DataStream& ds, uint64_t fromVersio
|
||||
}
|
||||
|
||||
template <typename Signal>
|
||||
void NetElementSignal<Signal>::readNetDelta(DataStream& ds, float interpolationTime) {
|
||||
void NetElementSignal<Signal>::readNetDelta(DataStream& ds, float interpolationTime, NetCompatibilityRules rules) {
|
||||
if (!checkWithRules(rules)) return;
|
||||
size_t numToRead = ds.readVlqU();
|
||||
for (size_t i = 0; i < numToRead; ++i) {
|
||||
Signal s;
|
||||
|
@ -26,23 +26,27 @@ void NetElementSyncGroup::tickNetInterpolation(float dt) {
|
||||
}
|
||||
}
|
||||
|
||||
void NetElementSyncGroup::netStore(DataStream& ds) const {
|
||||
void NetElementSyncGroup::netStore(DataStream& ds, NetCompatibilityRules rules) const {
|
||||
if (!checkWithRules(rules)) return;
|
||||
const_cast<NetElementSyncGroup*>(this)->netElementsNeedStore();
|
||||
return NetElementGroup::netStore(ds);
|
||||
return NetElementGroup::netStore(ds, rules);
|
||||
}
|
||||
|
||||
void NetElementSyncGroup::netLoad(DataStream& ds) {
|
||||
NetElementGroup::netLoad(ds);
|
||||
void NetElementSyncGroup::netLoad(DataStream& ds, NetCompatibilityRules rules) {
|
||||
if (!checkWithRules(rules)) return;
|
||||
NetElementGroup::netLoad(ds, rules);
|
||||
netElementsNeedLoad(true);
|
||||
}
|
||||
|
||||
bool NetElementSyncGroup::writeNetDelta(DataStream& ds, uint64_t fromVersion) const {
|
||||
bool NetElementSyncGroup::writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) const {
|
||||
if (!checkWithRules(rules)) return false;
|
||||
const_cast<NetElementSyncGroup*>(this)->netElementsNeedStore();
|
||||
return NetElementGroup::writeNetDelta(ds, fromVersion);
|
||||
return NetElementGroup::writeNetDelta(ds, fromVersion, rules);
|
||||
}
|
||||
|
||||
void NetElementSyncGroup::readNetDelta(DataStream& ds, float interpolationTime) {
|
||||
NetElementGroup::readNetDelta(ds, interpolationTime);
|
||||
void NetElementSyncGroup::readNetDelta(DataStream& ds, float interpolationTime, NetCompatibilityRules rules) {
|
||||
if (!checkWithRules(rules)) return;
|
||||
NetElementGroup::readNetDelta(ds, interpolationTime, rules);
|
||||
|
||||
m_hasRecentChanges = true;
|
||||
m_recentDeltaTime = interpolationTime;
|
||||
|
@ -13,11 +13,11 @@ public:
|
||||
void disableNetInterpolation() override;
|
||||
void tickNetInterpolation(float dt) override;
|
||||
|
||||
void netStore(DataStream& ds) const override;
|
||||
void netLoad(DataStream& ds) override;
|
||||
void netStore(DataStream& ds, NetCompatibilityRules rules = {}) const override;
|
||||
void netLoad(DataStream& ds, NetCompatibilityRules rules) override;
|
||||
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromStep) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0f) override;
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules = {}) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override;
|
||||
void blankNetDelta(float interpolationTime = 0.0f) override;
|
||||
|
||||
protected:
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef STAR_NET_ELEMENT_TOP_HPP
|
||||
#define STAR_NET_ELEMENT_TOP_HPP
|
||||
#pragma once
|
||||
|
||||
#include "StarNetElement.hpp"
|
||||
|
||||
@ -12,10 +11,11 @@ class NetElementTop : public BaseNetElement {
|
||||
public:
|
||||
NetElementTop();
|
||||
|
||||
// Returns the state update, combined with the version code that should be
|
||||
// passed to the next call to writeState. If 'fromVersion' is 0, then this
|
||||
// is a full write for an initial read of a slave NetElementTop.
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0);
|
||||
// Writes the state update to the given DataStream then returns the version
|
||||
// code that should be passed to the next call to writeState. If
|
||||
// 'fromVersion' is 0, then this is a full write for an initial read of a
|
||||
// slave NetElementTop.
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0, NetCompatibilityRules rules = {});
|
||||
// Reads a state produced by a call to writeState, optionally with the
|
||||
// interpolation delay time for the data contained in this state update. If
|
||||
// the state is a full update rather than a delta, the interoplation delay
|
||||
@ -23,7 +23,7 @@ public:
|
||||
// readState, *unless* extrapolation is enabled. If extrapolation is
|
||||
// enabled, reading a blank update calls 'blankNetDelta' which is necessary
|
||||
// to not improperly extrapolate past the end of incoming deltas.
|
||||
void readNetState(ByteArray data, float interpolationTime = 0.0);
|
||||
void readNetState(ByteArray data, float interpolationTime = 0.0f, NetCompatibilityRules rules = {});
|
||||
|
||||
private:
|
||||
using BaseNetElement::initNetVersion;
|
||||
@ -32,6 +32,7 @@ private:
|
||||
using BaseNetElement::writeNetDelta;
|
||||
using BaseNetElement::readNetDelta;
|
||||
using BaseNetElement::blankNetDelta;
|
||||
using BaseNetElement::checkWithRules;
|
||||
|
||||
NetElementVersion m_netVersion;
|
||||
};
|
||||
@ -42,41 +43,34 @@ NetElementTop<BaseNetElement>::NetElementTop() {
|
||||
}
|
||||
|
||||
template <typename BaseNetElement>
|
||||
pair<ByteArray, uint64_t> NetElementTop<BaseNetElement>::writeNetState(uint64_t fromVersion) {
|
||||
pair<ByteArray, uint64_t> NetElementTop<BaseNetElement>::writeNetState(uint64_t fromVersion, NetCompatibilityRules rules) {
|
||||
DataStreamBuffer ds;
|
||||
ds.setStreamCompatibilityVersion(rules);
|
||||
if (fromVersion == 0) {
|
||||
DataStreamBuffer ds;
|
||||
ds.write<bool>(true);
|
||||
BaseNetElement::netStore(ds);
|
||||
m_netVersion.increment();
|
||||
return {ds.takeData(), m_netVersion.current()};
|
||||
|
||||
BaseNetElement::netStore(ds, rules);
|
||||
return {ds.takeData(), m_netVersion.increment()};
|
||||
} else {
|
||||
DataStreamBuffer ds;
|
||||
ds.write<bool>(false);
|
||||
if (!BaseNetElement::writeNetDelta(ds, fromVersion)) {
|
||||
if (!BaseNetElement::writeNetDelta(ds, fromVersion, rules))
|
||||
return {ByteArray(), m_netVersion.current()};
|
||||
} else {
|
||||
m_netVersion.increment();
|
||||
return {ds.takeData(), m_netVersion.current()};
|
||||
}
|
||||
else
|
||||
return {ds.takeData(), m_netVersion.increment()};
|
||||
}
|
||||
}
|
||||
|
||||
template <typename BaseNetElement>
|
||||
void NetElementTop<BaseNetElement>::readNetState(ByteArray data, float interpolationTime) {
|
||||
void NetElementTop<BaseNetElement>::readNetState(ByteArray data, float interpolationTime, NetCompatibilityRules rules) {
|
||||
if (data.empty()) {
|
||||
BaseNetElement::blankNetDelta(interpolationTime);
|
||||
|
||||
} else {
|
||||
DataStreamBuffer ds(std::move(data));
|
||||
|
||||
ds.setStreamCompatibilityVersion(rules);
|
||||
if (ds.read<bool>())
|
||||
BaseNetElement::netLoad(ds);
|
||||
BaseNetElement::netLoad(ds, rules);
|
||||
else
|
||||
BaseNetElement::readNetDelta(ds, interpolationTime);
|
||||
BaseNetElement::readNetDelta(ds, interpolationTime, rules);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
#ifndef STAR_TEAMBAR_HPP
|
||||
#define STAR_TEAMBAR_HPP
|
||||
#pragma once
|
||||
|
||||
#include "StarPane.hpp"
|
||||
#include "StarUuid.hpp"
|
||||
@ -113,6 +112,4 @@ private:
|
||||
friend class TeamMemberMenu;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
@ -77,11 +77,12 @@ ShipUpgrades ClientContext::shipUpgrades() const {
|
||||
return m_shipUpgrades.get();
|
||||
}
|
||||
|
||||
void ClientContext::readUpdate(ByteArray data) {
|
||||
void ClientContext::readUpdate(ByteArray data, NetCompatibilityRules rules) {
|
||||
if (data.empty())
|
||||
return;
|
||||
|
||||
DataStreamBuffer ds(std::move(data));
|
||||
ds.setStreamCompatibilityVersion(rules);
|
||||
|
||||
m_rpc->receive(ds.read<ByteArray>());
|
||||
|
||||
@ -89,10 +90,10 @@ void ClientContext::readUpdate(ByteArray data) {
|
||||
if (!shipUpdates.empty())
|
||||
m_newShipUpdates.merge(DataStreamBuffer::deserialize<WorldChunks>(std::move(shipUpdates)), true);
|
||||
|
||||
m_netGroup.readNetState(ds.read<ByteArray>());
|
||||
m_netGroup.readNetState(ds.read<ByteArray>(), 0.0f, rules);
|
||||
}
|
||||
|
||||
ByteArray ClientContext::writeUpdate() {
|
||||
ByteArray ClientContext::writeUpdate(NetCompatibilityRules rules) {
|
||||
return m_rpc->send();
|
||||
}
|
||||
|
||||
@ -104,4 +105,12 @@ ConnectionId ClientContext::connectionId() const {
|
||||
return m_connectionId;
|
||||
}
|
||||
|
||||
void ClientContext::setNetCompatibilityRules(NetCompatibilityRules netCompatibilityRules) {
|
||||
m_netCompatibilityRules = netCompatibilityRules;
|
||||
}
|
||||
|
||||
NetCompatibilityRules ClientContext::netCompatibilityRules() const {
|
||||
return m_netCompatibilityRules;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -40,16 +40,20 @@ public:
|
||||
WorldChunks newShipUpdates();
|
||||
ShipUpgrades shipUpgrades() const;
|
||||
|
||||
void readUpdate(ByteArray data);
|
||||
ByteArray writeUpdate();
|
||||
void readUpdate(ByteArray data, NetCompatibilityRules rules);
|
||||
ByteArray writeUpdate(NetCompatibilityRules rules);
|
||||
|
||||
void setConnectionId(ConnectionId connectionId);
|
||||
ConnectionId connectionId() const;
|
||||
|
||||
void setNetCompatibilityRules(NetCompatibilityRules netCompatibilityRules);
|
||||
NetCompatibilityRules netCompatibilityRules() const;
|
||||
|
||||
private:
|
||||
Uuid m_serverUuid;
|
||||
Uuid m_playerUuid;
|
||||
ConnectionId m_connectionId = 0;
|
||||
NetCompatibilityRules m_netCompatibilityRules;
|
||||
|
||||
JsonRpcPtr m_rpc;
|
||||
|
||||
|
@ -40,57 +40,57 @@ EntityFactory::EntityFactory() {
|
||||
m_versioningDatabase = root.versioningDatabase();
|
||||
}
|
||||
|
||||
ByteArray EntityFactory::netStoreEntity(EntityPtr const& entity) const {
|
||||
ByteArray EntityFactory::netStoreEntity(EntityPtr const& entity, NetCompatibilityRules rules) const {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
|
||||
if (auto player = as<Player>(entity)) {
|
||||
return player->netStore();
|
||||
return player->netStore(rules);
|
||||
} else if (auto monster = as<Monster>(entity)) {
|
||||
return monster->netStore();
|
||||
return monster->netStore(rules);
|
||||
} else if (auto object = as<Object>(entity)) {
|
||||
return object->netStore();
|
||||
return object->netStore(rules);
|
||||
} else if (auto plant = as<Plant>(entity)) {
|
||||
return plant->netStore();
|
||||
return plant->netStore(rules);
|
||||
} else if (auto plantDrop = as<PlantDrop>(entity)) {
|
||||
return plantDrop->netStore();
|
||||
return plantDrop->netStore(rules);
|
||||
} else if (auto projectile = as<Projectile>(entity)) {
|
||||
return projectile->netStore();
|
||||
return projectile->netStore(rules);
|
||||
} else if (auto itemDrop = as<ItemDrop>(entity)) {
|
||||
return itemDrop->netStore();
|
||||
return itemDrop->netStore(rules);
|
||||
} else if (auto npc = as<Npc>(entity)) {
|
||||
return npc->netStore();
|
||||
return npc->netStore(rules);
|
||||
} else if (auto stagehand = as<Stagehand>(entity)) {
|
||||
return stagehand->netStore();
|
||||
return stagehand->netStore(rules);
|
||||
} else if (auto vehicle = as<Vehicle>(entity)) {
|
||||
return m_vehicleDatabase->netStore(vehicle);
|
||||
return m_vehicleDatabase->netStore(vehicle, rules);
|
||||
} else {
|
||||
throw EntityFactoryException::format("Don't know how to make net store for entity type '{}'", EntityTypeNames.getRight(entity->entityType()));
|
||||
}
|
||||
}
|
||||
|
||||
EntityPtr EntityFactory::netLoadEntity(EntityType type, ByteArray const& netStore) const {
|
||||
EntityPtr EntityFactory::netLoadEntity(EntityType type, ByteArray const& netStore, NetCompatibilityRules rules) const {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
|
||||
if (type == EntityType::Player) {
|
||||
return m_playerFactory->netLoadPlayer(netStore);
|
||||
return m_playerFactory->netLoadPlayer(netStore, rules);
|
||||
} else if (type == EntityType::Monster) {
|
||||
return m_monsterDatabase->netLoadMonster(netStore);
|
||||
return m_monsterDatabase->netLoadMonster(netStore, rules);
|
||||
} else if (type == EntityType::Object) {
|
||||
return m_objectDatabase->netLoadObject(netStore);
|
||||
return m_objectDatabase->netLoadObject(netStore, rules);
|
||||
} else if (type == EntityType::Plant) {
|
||||
return make_shared<Plant>(netStore);
|
||||
return make_shared<Plant>(netStore, rules);
|
||||
} else if (type == EntityType::PlantDrop) {
|
||||
return make_shared<PlantDrop>(netStore);
|
||||
return make_shared<PlantDrop>(netStore, rules);
|
||||
} else if (type == EntityType::Projectile) {
|
||||
return m_projectileDatabase->netLoadProjectile(netStore);
|
||||
return m_projectileDatabase->netLoadProjectile(netStore, rules);
|
||||
} else if (type == EntityType::ItemDrop) {
|
||||
return make_shared<ItemDrop>(netStore);
|
||||
return make_shared<ItemDrop>(netStore, rules);
|
||||
} else if (type == EntityType::Npc) {
|
||||
return m_npcDatabase->netLoadNpc(netStore);
|
||||
return m_npcDatabase->netLoadNpc(netStore, rules);
|
||||
} else if (type == EntityType::Stagehand) {
|
||||
return make_shared<Stagehand>(netStore);
|
||||
return make_shared<Stagehand>(netStore, rules);
|
||||
} else if (type == EntityType::Vehicle) {
|
||||
return m_vehicleDatabase->netLoad(netStore);
|
||||
return m_vehicleDatabase->netLoad(netStore, rules);
|
||||
} else {
|
||||
throw EntityFactoryException::format("Don't know how to create entity type '{}' from net store", EntityTypeNames.getRight(type));
|
||||
}
|
||||
|
@ -20,8 +20,8 @@ class EntityFactory {
|
||||
public:
|
||||
EntityFactory();
|
||||
|
||||
ByteArray netStoreEntity(EntityPtr const& entity) const;
|
||||
EntityPtr netLoadEntity(EntityType type, ByteArray const& netStore) const;
|
||||
ByteArray netStoreEntity(EntityPtr const& entity, NetCompatibilityRules rules = {}) const;
|
||||
EntityPtr netLoadEntity(EntityType type, ByteArray const& netStore, NetCompatibilityRules rules = {}) const;
|
||||
|
||||
Json diskStoreEntity(EntityPtr const& entity) const;
|
||||
EntityPtr diskLoadEntity(EntityType type, Json const& diskStore) const;
|
||||
|
@ -243,6 +243,49 @@ EnumMap<Humanoid::State> const Humanoid::StateNames{
|
||||
};
|
||||
|
||||
Humanoid::Humanoid(Json const& config) {
|
||||
loadConfig(config);
|
||||
|
||||
m_twoHanded = false;
|
||||
m_primaryHand.holdingItem = false;
|
||||
m_altHand.holdingItem = false;
|
||||
|
||||
m_movingBackwards = false;
|
||||
m_altHand.angle = 0;
|
||||
m_facingDirection = Direction::Left;
|
||||
m_rotation = 0;
|
||||
m_scale = Vec2F::filled(1.f);
|
||||
m_drawVaporTrail = false;
|
||||
m_state = State::Idle;
|
||||
m_emoteState = HumanoidEmote::Idle;
|
||||
m_dance = {};
|
||||
|
||||
m_primaryHand.angle = 0;
|
||||
m_animationTimer = m_emoteAnimationTimer = m_danceTimer = 0.0f;
|
||||
}
|
||||
|
||||
Humanoid::Humanoid(HumanoidIdentity const& identity)
|
||||
: Humanoid(Root::singleton().speciesDatabase()->species(identity.species)->humanoidConfig()) {
|
||||
setIdentity(identity);
|
||||
}
|
||||
|
||||
void Humanoid::setIdentity(HumanoidIdentity const& identity) {
|
||||
m_identity = identity;
|
||||
m_headFrameset = getHeadFromIdentity();
|
||||
m_bodyFrameset = getBodyFromIdentity();
|
||||
m_emoteFrameset = getFacialEmotesFromIdentity();
|
||||
m_hairFrameset = getHairFromIdentity();
|
||||
m_facialHairFrameset = getFacialHairFromIdentity();
|
||||
m_facialMaskFrameset = getFacialMaskFromIdentity();
|
||||
m_backArmFrameset = getBackArmFromIdentity();
|
||||
m_frontArmFrameset = getFrontArmFromIdentity();
|
||||
m_vaporTrailFrameset = getVaporTrailFrameset();
|
||||
}
|
||||
|
||||
HumanoidIdentity const& Humanoid::identity() const {
|
||||
return m_identity;
|
||||
}
|
||||
|
||||
void Humanoid::loadConfig(Json const& config) {
|
||||
m_timing = HumanoidTiming(config.getObject("humanoidTiming"));
|
||||
|
||||
m_globalOffset = jsonToVec2F(config.get("globalOffset")) / TilePixels;
|
||||
@ -271,10 +314,13 @@ Humanoid::Humanoid(Json const& config) {
|
||||
m_armWalkSeq = jsonToIntList(config.get("armWalkSeq"));
|
||||
m_armRunSeq = jsonToIntList(config.get("armRunSeq"));
|
||||
|
||||
m_walkBob.clear();
|
||||
for (auto const& v : config.get("walkBob").toArray())
|
||||
m_walkBob.append(v.toDouble() / TilePixels);
|
||||
m_runBob.clear();
|
||||
for (auto const& v : config.get("runBob").toArray())
|
||||
m_runBob.append(v.toDouble() / TilePixels);
|
||||
m_swimBob.clear();
|
||||
for (auto const& v : config.get("swimBob").toArray())
|
||||
m_swimBob.append(v.toDouble() / TilePixels);
|
||||
|
||||
@ -290,46 +336,6 @@ Humanoid::Humanoid(Json const& config) {
|
||||
m_particleEmitters = config.get("particleEmitters");
|
||||
|
||||
m_defaultMovementParameters = config.get("movementParameters");
|
||||
|
||||
m_twoHanded = false;
|
||||
m_primaryHand.holdingItem = false;
|
||||
m_altHand.holdingItem = false;
|
||||
|
||||
m_movingBackwards = false;
|
||||
m_altHand.angle = 0;
|
||||
m_facingDirection = Direction::Left;
|
||||
m_rotation = 0;
|
||||
m_scale = Vec2F::filled(1.f);
|
||||
m_drawVaporTrail = false;
|
||||
m_state = State::Idle;
|
||||
m_emoteState = HumanoidEmote::Idle;
|
||||
m_dance = {};
|
||||
m_emoteAnimationTimer = 0;
|
||||
|
||||
m_primaryHand.angle = 0;
|
||||
m_animationTimer = 0.0f;
|
||||
}
|
||||
|
||||
Humanoid::Humanoid(HumanoidIdentity const& identity)
|
||||
: Humanoid(Root::singleton().speciesDatabase()->species(identity.species)->humanoidConfig()) {
|
||||
setIdentity(identity);
|
||||
}
|
||||
|
||||
void Humanoid::setIdentity(HumanoidIdentity const& identity) {
|
||||
m_identity = identity;
|
||||
m_headFrameset = getHeadFromIdentity();
|
||||
m_bodyFrameset = getBodyFromIdentity();
|
||||
m_emoteFrameset = getFacialEmotesFromIdentity();
|
||||
m_hairFrameset = getHairFromIdentity();
|
||||
m_facialHairFrameset = getFacialHairFromIdentity();
|
||||
m_facialMaskFrameset = getFacialMaskFromIdentity();
|
||||
m_backArmFrameset = getBackArmFromIdentity();
|
||||
m_frontArmFrameset = getFrontArmFromIdentity();
|
||||
m_vaporTrailFrameset = getVaporTrailFrameset();
|
||||
}
|
||||
|
||||
HumanoidIdentity const& Humanoid::identity() const {
|
||||
return m_identity;
|
||||
}
|
||||
|
||||
void Humanoid::setHeadArmorDirectives(Directives directives) {
|
||||
|
@ -125,6 +125,8 @@ public:
|
||||
void setIdentity(HumanoidIdentity const& identity);
|
||||
HumanoidIdentity const& identity() const;
|
||||
|
||||
void loadConfig(Json const& config);
|
||||
|
||||
// All of the image identifiers here are meant to be image *base* names, with
|
||||
// a collection of frames specific to each piece. If an image is set to
|
||||
// empty string, it is disabled.
|
||||
|
@ -92,9 +92,9 @@ ItemDrop::ItemDrop(Json const& diskStore)
|
||||
m_itemDescriptor.set(m_item->descriptor());
|
||||
}
|
||||
|
||||
ItemDrop::ItemDrop(ByteArray store)
|
||||
: ItemDrop() {
|
||||
ItemDrop::ItemDrop(ByteArray store, NetCompatibilityRules rules) : ItemDrop() {
|
||||
DataStreamBuffer ds(std::move(store));
|
||||
ds.setStreamCompatibilityVersion(rules);
|
||||
|
||||
Root::singleton().itemDatabase()->loadItem(ds.read<ItemDescriptor>(), m_item);
|
||||
ds.read(m_eternal);
|
||||
@ -116,8 +116,9 @@ Json ItemDrop::diskStore() const {
|
||||
};
|
||||
}
|
||||
|
||||
ByteArray ItemDrop::netStore() const {
|
||||
ByteArray ItemDrop::netStore(NetCompatibilityRules rules) const {
|
||||
DataStreamBuffer ds;
|
||||
ds.setStreamCompatibilityVersion(rules);
|
||||
|
||||
ds.write(itemSafeDescriptor(m_item));
|
||||
ds.write(m_eternal);
|
||||
@ -146,12 +147,12 @@ String ItemDrop::description() const {
|
||||
return m_item->description();
|
||||
}
|
||||
|
||||
pair<ByteArray, uint64_t> ItemDrop::writeNetState(uint64_t fromVersion) {
|
||||
return m_netGroup.writeNetState(fromVersion);
|
||||
pair<ByteArray, uint64_t> ItemDrop::writeNetState(uint64_t fromVersion, NetCompatibilityRules rules) {
|
||||
return m_netGroup.writeNetState(fromVersion, rules);
|
||||
}
|
||||
|
||||
void ItemDrop::readNetState(ByteArray data, float interpolationTime) {
|
||||
m_netGroup.readNetState(std::move(data), interpolationTime);
|
||||
void ItemDrop::readNetState(ByteArray data, float interpolationTime, NetCompatibilityRules rules) {
|
||||
m_netGroup.readNetState(data, interpolationTime, rules);
|
||||
}
|
||||
|
||||
void ItemDrop::enableInterpolation(float extrapolationHint) {
|
||||
|
@ -27,10 +27,10 @@ public:
|
||||
|
||||
ItemDrop(ItemPtr item);
|
||||
ItemDrop(Json const& diskStore);
|
||||
ItemDrop(ByteArray netStore);
|
||||
ItemDrop(ByteArray netStore, NetCompatibilityRules rules = {});
|
||||
|
||||
Json diskStore() const;
|
||||
ByteArray netStore() const;
|
||||
ByteArray netStore(NetCompatibilityRules rules = {}) const;
|
||||
|
||||
EntityType entityType() const override;
|
||||
|
||||
@ -39,8 +39,8 @@ public:
|
||||
|
||||
String description() const override;
|
||||
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0) override;
|
||||
void readNetState(ByteArray data, float interpolationTime = 0.0f) override;
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0, NetCompatibilityRules rules = {}) override;
|
||||
void readNetState(ByteArray data, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override;
|
||||
|
||||
void enableInterpolation(float extrapolationHint = 0.0f) override;
|
||||
void disableInterpolation() override;
|
||||
|
@ -110,8 +110,8 @@ Json Monster::diskStore() const {
|
||||
};
|
||||
}
|
||||
|
||||
ByteArray Monster::netStore() {
|
||||
return Root::singleton().monsterDatabase()->writeMonsterVariant(m_monsterVariant);
|
||||
ByteArray Monster::netStore(NetCompatibilityRules rules) {
|
||||
return Root::singleton().monsterDatabase()->writeMonsterVariant(m_monsterVariant, rules);
|
||||
}
|
||||
|
||||
EntityType Monster::entityType() const {
|
||||
@ -210,12 +210,12 @@ Vec2F Monster::velocity() const {
|
||||
return m_movementController->velocity();
|
||||
}
|
||||
|
||||
pair<ByteArray, uint64_t> Monster::writeNetState(uint64_t fromVersion) {
|
||||
return m_netGroup.writeNetState(fromVersion);
|
||||
pair<ByteArray, uint64_t> Monster::writeNetState(uint64_t fromVersion, NetCompatibilityRules rules) {
|
||||
return m_netGroup.writeNetState(fromVersion, rules);
|
||||
}
|
||||
|
||||
void Monster::readNetState(ByteArray data, float interpolationTime) {
|
||||
m_netGroup.readNetState(std::move(data), interpolationTime);
|
||||
void Monster::readNetState(ByteArray data, float interpolationTime, NetCompatibilityRules rules) {
|
||||
m_netGroup.readNetState(data, interpolationTime, rules);
|
||||
}
|
||||
|
||||
void Monster::enableInterpolation(float extrapolationHint) {
|
||||
|
@ -42,7 +42,7 @@ public:
|
||||
Monster(Json const& diskStore);
|
||||
|
||||
Json diskStore() const;
|
||||
ByteArray netStore();
|
||||
ByteArray netStore(NetCompatibilityRules rules = {});
|
||||
|
||||
EntityType entityType() const override;
|
||||
ClientEntityMode clientEntityMode() const override;
|
||||
@ -60,8 +60,8 @@ public:
|
||||
|
||||
RectF collisionArea() const override;
|
||||
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0) override;
|
||||
void readNetState(ByteArray data, float interpolationTime = 0.0f) override;
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0, NetCompatibilityRules rules = {}) override;
|
||||
void readNetState(ByteArray data, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override;
|
||||
|
||||
void enableInterpolation(float extrapolationHint) override;
|
||||
void disableInterpolation() override;
|
||||
|
@ -170,8 +170,9 @@ MonsterVariant MonsterDatabase::monsterVariant(String const& typeName, uint64_t
|
||||
});
|
||||
}
|
||||
|
||||
ByteArray MonsterDatabase::writeMonsterVariant(MonsterVariant const& variant) const {
|
||||
ByteArray MonsterDatabase::writeMonsterVariant(MonsterVariant const& variant, NetCompatibilityRules rules) const {
|
||||
DataStreamBuffer ds;
|
||||
ds.setStreamCompatibilityVersion(rules);
|
||||
|
||||
ds.write(variant.type);
|
||||
ds.write(variant.seed);
|
||||
@ -180,8 +181,9 @@ ByteArray MonsterDatabase::writeMonsterVariant(MonsterVariant const& variant) co
|
||||
return ds.data();
|
||||
}
|
||||
|
||||
MonsterVariant MonsterDatabase::readMonsterVariant(ByteArray const& data) const {
|
||||
MonsterVariant MonsterDatabase::readMonsterVariant(ByteArray const& data, NetCompatibilityRules rules) const {
|
||||
DataStreamBuffer ds(data);
|
||||
ds.setStreamCompatibilityVersion(rules);
|
||||
|
||||
String type = ds.read<String>();
|
||||
uint64_t seed = ds.read<uint64_t>();
|
||||
@ -216,8 +218,8 @@ MonsterPtr MonsterDatabase::diskLoadMonster(Json const& diskStore) const {
|
||||
return make_shared<Monster>(diskStore);
|
||||
}
|
||||
|
||||
MonsterPtr MonsterDatabase::netLoadMonster(ByteArray const& netStore) const {
|
||||
return make_shared<Monster>(readMonsterVariant(netStore));
|
||||
MonsterPtr MonsterDatabase::netLoadMonster(ByteArray const& netStore, NetCompatibilityRules rules) const {
|
||||
return make_shared<Monster>(readMonsterVariant(netStore, rules));
|
||||
}
|
||||
|
||||
List<Drawable> MonsterDatabase::monsterPortrait(MonsterVariant const& variant) const {
|
||||
|
@ -96,8 +96,8 @@ public:
|
||||
MonsterVariant randomMonster(String const& typeName, Json const& uniqueParameters = JsonObject()) const;
|
||||
MonsterVariant monsterVariant(String const& typeName, uint64_t seed, Json const& uniqueParameters = JsonObject()) const;
|
||||
|
||||
ByteArray writeMonsterVariant(MonsterVariant const& variant) const;
|
||||
MonsterVariant readMonsterVariant(ByteArray const& data) const;
|
||||
ByteArray writeMonsterVariant(MonsterVariant const& variant, NetCompatibilityRules rules = {}) const;
|
||||
MonsterVariant readMonsterVariant(ByteArray const& data, NetCompatibilityRules rules = {}) const;
|
||||
|
||||
Json writeMonsterVariantToJson(MonsterVariant const& mVar) const;
|
||||
MonsterVariant readMonsterVariantFromJson(Json const& variant) const;
|
||||
@ -106,7 +106,7 @@ public:
|
||||
// whatever world they're spawned in.
|
||||
MonsterPtr createMonster(MonsterVariant monsterVariant, Maybe<float> level = {}, Json uniqueParameters = {}) const;
|
||||
MonsterPtr diskLoadMonster(Json const& diskStore) const;
|
||||
MonsterPtr netLoadMonster(ByteArray const& netStore) const;
|
||||
MonsterPtr netLoadMonster(ByteArray const& netStore, NetCompatibilityRules rules = {}) const;
|
||||
|
||||
List<Drawable> monsterPortrait(MonsterVariant const& variant) const;
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
namespace Star {
|
||||
|
||||
VersionNumber const StarProtocolVersion = 747;
|
||||
VersionNumber const OpenProtocolVersion = 1;
|
||||
|
||||
EnumMap<PacketType> const PacketTypeNames{
|
||||
{PacketType::ProtocolRequest, "ProtocolRequest"},
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "StarWiring.hpp"
|
||||
#include "StarClientContext.hpp"
|
||||
#include "StarSystemWorld.hpp"
|
||||
#include "StarNetCompatibility.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
@ -22,6 +23,7 @@ STAR_STRUCT(Packet);
|
||||
STAR_EXCEPTION(StarPacketException, IOException);
|
||||
|
||||
extern VersionNumber const StarProtocolVersion;
|
||||
extern VersionNumber const OpenProtocolVersion;
|
||||
|
||||
// Packet types sent between the client and server over a NetSocket. Does not
|
||||
// correspond to actual packets, simply logical portions of NetSocket data.
|
||||
|
@ -152,8 +152,8 @@ Json Npc::diskStore() const {
|
||||
};
|
||||
}
|
||||
|
||||
ByteArray Npc::netStore() {
|
||||
return Root::singleton().npcDatabase()->writeNpcVariant(m_npcVariant);
|
||||
ByteArray Npc::netStore(NetCompatibilityRules rules) {
|
||||
return Root::singleton().npcDatabase()->writeNpcVariant(m_npcVariant, rules);
|
||||
}
|
||||
|
||||
EntityType Npc::entityType() const {
|
||||
@ -252,7 +252,7 @@ RectF Npc::collisionArea() const {
|
||||
return m_movementController->collisionPoly().boundBox();
|
||||
}
|
||||
|
||||
pair<ByteArray, uint64_t> Npc::writeNetState(uint64_t fromVersion) {
|
||||
pair<ByteArray, uint64_t> Npc::writeNetState(uint64_t fromVersion, NetCompatibilityRules rules) {
|
||||
// client-side npcs error nearby vanilla NPC scripts because callScriptedEntity
|
||||
// for now, scrungle the collision poly to avoid their queries. hacky :(
|
||||
if (m_npcVariant.overrides && m_npcVariant.overrides.getBool("overrideNetPoly", false)) {
|
||||
@ -260,18 +260,18 @@ pair<ByteArray, uint64_t> Npc::writeNetState(uint64_t fromVersion) {
|
||||
if (*mode == EntityMode::Master && connectionForEntity(entityId()) != ServerConnectionId) {
|
||||
PolyF poly = m_movementController->collisionPoly();
|
||||
m_movementController->setCollisionPoly({ { 0.0f, -3.402823466e+38F }});
|
||||
auto result = m_netGroup.writeNetState(fromVersion);
|
||||
auto result = m_netGroup.writeNetState(fromVersion, rules);
|
||||
m_movementController->setCollisionPoly(poly);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m_netGroup.writeNetState(fromVersion);
|
||||
return m_netGroup.writeNetState(fromVersion, rules);
|
||||
}
|
||||
|
||||
void Npc::readNetState(ByteArray data, float interpolationTime) {
|
||||
m_netGroup.readNetState(std::move(data), interpolationTime);
|
||||
void Npc::readNetState(ByteArray data, float interpolationTime, NetCompatibilityRules rules) {
|
||||
m_netGroup.readNetState(data, interpolationTime, rules);
|
||||
}
|
||||
|
||||
String Npc::description() const {
|
||||
|
@ -42,11 +42,12 @@ class Npc
|
||||
public virtual PhysicsEntity,
|
||||
public virtual EmoteEntity {
|
||||
public:
|
||||
Npc(ByteArray const& netStore, NetCompatibilityRules rules = {});
|
||||
Npc(NpcVariant const& npcVariant);
|
||||
Npc(NpcVariant const& npcVariant, Json const& initialState);
|
||||
|
||||
Json diskStore() const;
|
||||
ByteArray netStore();
|
||||
ByteArray netStore(NetCompatibilityRules rules = {});
|
||||
|
||||
EntityType entityType() const override;
|
||||
ClientEntityMode clientEntityMode() const override;
|
||||
@ -66,8 +67,8 @@ public:
|
||||
|
||||
RectF collisionArea() const override;
|
||||
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0) override;
|
||||
void readNetState(ByteArray data, float interpolationTime = 0.0f) override;
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0, NetCompatibilityRules rules = {}) override;
|
||||
void readNetState(ByteArray data, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override;
|
||||
|
||||
void enableInterpolation(float extrapolationHint = 0.0f) override;
|
||||
void disableInterpolation() override;
|
||||
|
@ -157,8 +157,9 @@ NpcVariant NpcDatabase::generateNpcVariant(
|
||||
return variant;
|
||||
}
|
||||
|
||||
ByteArray NpcDatabase::writeNpcVariant(NpcVariant const& variant) const {
|
||||
ByteArray NpcDatabase::writeNpcVariant(NpcVariant const& variant, NetCompatibilityRules rules) const {
|
||||
DataStreamBuffer ds;
|
||||
ds.setStreamCompatibilityVersion(rules);
|
||||
|
||||
ds.write(variant.species);
|
||||
ds.write(variant.typeName);
|
||||
@ -179,8 +180,9 @@ ByteArray NpcDatabase::writeNpcVariant(NpcVariant const& variant) const {
|
||||
return ds.data();
|
||||
}
|
||||
|
||||
NpcVariant NpcDatabase::readNpcVariant(ByteArray const& data) const {
|
||||
NpcVariant NpcDatabase::readNpcVariant(ByteArray const& data, NetCompatibilityRules rules) const {
|
||||
DataStreamBuffer ds(data);
|
||||
ds.setStreamCompatibilityVersion(rules);
|
||||
|
||||
NpcVariant variant;
|
||||
|
||||
@ -325,8 +327,8 @@ NpcPtr NpcDatabase::diskLoadNpc(Json const& diskStore) const {
|
||||
return make_shared<Npc>(npcVariant, diskStore);
|
||||
}
|
||||
|
||||
NpcPtr NpcDatabase::netLoadNpc(ByteArray const& netStore) const {
|
||||
return make_shared<Npc>(readNpcVariant(netStore));
|
||||
NpcPtr NpcDatabase::netLoadNpc(ByteArray const& netStore, NetCompatibilityRules rules) const {
|
||||
return make_shared<Npc>(readNpcVariant(netStore, rules));
|
||||
}
|
||||
|
||||
List<Drawable> NpcDatabase::npcPortrait(NpcVariant const& npcVariant, PortraitMode mode) const {
|
||||
|
@ -58,15 +58,15 @@ public:
|
||||
NpcVariant generateNpcVariant(String const& species, String const& typeName, float level) const;
|
||||
NpcVariant generateNpcVariant(String const& species, String const& typeName, float level, uint64_t seed, Json const& overrides) const;
|
||||
|
||||
ByteArray writeNpcVariant(NpcVariant const& variant) const;
|
||||
NpcVariant readNpcVariant(ByteArray const& data) const;
|
||||
ByteArray writeNpcVariant(NpcVariant const& variant, NetCompatibilityRules rules = {}) const;
|
||||
NpcVariant readNpcVariant(ByteArray const& data, NetCompatibilityRules rules = {}) const;
|
||||
|
||||
Json writeNpcVariantToJson(NpcVariant const& variant) const;
|
||||
NpcVariant readNpcVariantFromJson(Json const& data) const;
|
||||
|
||||
NpcPtr createNpc(NpcVariant const& npcVariant) const;
|
||||
NpcPtr diskLoadNpc(Json const& diskStoree) const;
|
||||
NpcPtr netLoadNpc(ByteArray const& netStore) const;
|
||||
NpcPtr diskLoadNpc(Json const& diskStore) const;
|
||||
NpcPtr netLoadNpc(ByteArray const& netStore, NetCompatibilityRules rules = {}) const;
|
||||
|
||||
List<Drawable> npcPortrait(NpcVariant const& npcVariant, PortraitMode mode) const;
|
||||
|
||||
|
@ -118,8 +118,9 @@ Json Object::diskStore() const {
|
||||
return writeStoredData().setAll({{"name", m_config->name}, {"parameters", m_parameters.baseMap()}});
|
||||
}
|
||||
|
||||
ByteArray Object::netStore() {
|
||||
ByteArray Object::netStore(NetCompatibilityRules rules) {
|
||||
DataStreamBuffer ds;
|
||||
ds.setStreamCompatibilityVersion(rules);
|
||||
ds.write(m_config->name);
|
||||
ds.write<Json>(m_parameters.baseMap());
|
||||
return ds.takeData();
|
||||
@ -297,13 +298,12 @@ RectF Object::metaBoundBox() const {
|
||||
}
|
||||
}
|
||||
|
||||
pair<ByteArray, uint64_t> Object::writeNetState(uint64_t fromVersion) {
|
||||
DataStreamBuffer ds;
|
||||
return m_netGroup.writeNetState(fromVersion);
|
||||
pair<ByteArray, uint64_t> Object::writeNetState(uint64_t fromVersion, NetCompatibilityRules rules) {
|
||||
return m_netGroup.writeNetState(fromVersion, rules);
|
||||
}
|
||||
|
||||
void Object::readNetState(ByteArray delta, float interpolationTime) {
|
||||
m_netGroup.readNetState(std::move(delta), interpolationTime);
|
||||
void Object::readNetState(ByteArray data, float interpolationTime, NetCompatibilityRules rules) {
|
||||
m_netGroup.readNetState(data, interpolationTime, rules);
|
||||
}
|
||||
|
||||
Vec2I Object::tilePosition() const {
|
||||
|
@ -37,7 +37,7 @@ public:
|
||||
Object(ObjectConfigConstPtr config, Json const& parameters = JsonObject());
|
||||
|
||||
Json diskStore() const;
|
||||
ByteArray netStore();
|
||||
ByteArray netStore(NetCompatibilityRules rules = {});
|
||||
|
||||
virtual EntityType entityType() const override;
|
||||
virtual ClientEntityMode clientEntityMode() const override;
|
||||
@ -48,8 +48,8 @@ public:
|
||||
virtual Vec2F position() const override;
|
||||
virtual RectF metaBoundBox() const override;
|
||||
|
||||
virtual pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0) override;
|
||||
virtual void readNetState(ByteArray data, float interpolationTime = 0.0f) override;
|
||||
virtual pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0, NetCompatibilityRules rules = {}) override;
|
||||
virtual void readNetState(ByteArray data, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override;
|
||||
|
||||
virtual String description() const override;
|
||||
|
||||
|
@ -380,8 +380,9 @@ ObjectPtr ObjectDatabase::diskLoadObject(Json const& diskStore) const {
|
||||
return object;
|
||||
}
|
||||
|
||||
ObjectPtr ObjectDatabase::netLoadObject(ByteArray const& netStore) const {
|
||||
ObjectPtr ObjectDatabase::netLoadObject(ByteArray const& netStore, NetCompatibilityRules rules) const {
|
||||
DataStreamBuffer ds(netStore);
|
||||
ds.setStreamCompatibilityVersion(rules);
|
||||
String name = ds.read<String>();
|
||||
Json parameters = ds.read<Json>();
|
||||
return createObject(name, parameters);
|
||||
|
@ -198,7 +198,7 @@ public:
|
||||
|
||||
ObjectPtr createObject(String const& objectName, Json const& objectParameters = JsonObject()) const;
|
||||
ObjectPtr diskLoadObject(Json const& diskStore) const;
|
||||
ObjectPtr netLoadObject(ByteArray const& netStore) const;
|
||||
ObjectPtr netLoadObject(ByteArray const& netStore, NetCompatibilityRules rules = {}) const;
|
||||
|
||||
bool canPlaceObject(World const* world, Vec2I const& position, String const& objectName) const;
|
||||
// If the object is placeable in the given position, creates the given object
|
||||
|
@ -411,8 +411,9 @@ Json Plant::diskStore() const {
|
||||
};
|
||||
}
|
||||
|
||||
ByteArray Plant::netStore() const {
|
||||
ByteArray Plant::netStore(NetCompatibilityRules rules) const {
|
||||
DataStreamBuffer ds;
|
||||
ds.setStreamCompatibilityVersion(rules);
|
||||
ds.viwrite(m_tilePosition[0]);
|
||||
ds.viwrite(m_tilePosition[1]);
|
||||
ds.write(m_ceiling);
|
||||
@ -423,7 +424,7 @@ ByteArray Plant::netStore() const {
|
||||
ds.write(m_ephemeral);
|
||||
ds.write(m_tileDamageParameters);
|
||||
ds.write(m_fallsWhenDead);
|
||||
m_tileDamageStatus.netStore(ds);
|
||||
m_tileDamageStatus.netStore(ds, rules);
|
||||
ds.write(writePieces());
|
||||
|
||||
return ds.takeData();
|
||||
@ -534,7 +535,7 @@ Plant::Plant(Json const& diskStore) : Plant() {
|
||||
setupNetStates();
|
||||
}
|
||||
|
||||
Plant::Plant(ByteArray const& netStore) : Plant() {
|
||||
Plant::Plant(ByteArray const& netStore, NetCompatibilityRules rules) : Plant() {
|
||||
m_broken = false;
|
||||
m_tilePosition = Vec2I();
|
||||
m_ceiling = false;
|
||||
@ -545,6 +546,7 @@ Plant::Plant(ByteArray const& netStore) : Plant() {
|
||||
m_piecesUpdated = true;
|
||||
|
||||
DataStreamBuffer ds(netStore);
|
||||
ds.setStreamCompatibilityVersion(rules);
|
||||
ds.viread(m_tilePosition[0]);
|
||||
ds.viread(m_tilePosition[1]);
|
||||
ds.read(m_ceiling);
|
||||
@ -555,7 +557,7 @@ Plant::Plant(ByteArray const& netStore) : Plant() {
|
||||
ds.read(m_ephemeral);
|
||||
ds.read(m_tileDamageParameters);
|
||||
ds.read(m_fallsWhenDead);
|
||||
m_tileDamageStatus.netLoad(ds);
|
||||
m_tileDamageStatus.netLoad(ds, rules);
|
||||
readPieces(ds.read<ByteArray>());
|
||||
|
||||
setupNetStates();
|
||||
@ -586,12 +588,12 @@ void Plant::init(World* world, EntityId entityId, EntityMode mode) {
|
||||
m_tilePosition = world->geometry().xwrap(m_tilePosition);
|
||||
}
|
||||
|
||||
pair<ByteArray, uint64_t> Plant::writeNetState(uint64_t fromVersion) {
|
||||
return m_netGroup.writeNetState(fromVersion);
|
||||
pair<ByteArray, uint64_t> Plant::writeNetState(uint64_t fromVersion, NetCompatibilityRules rules) {
|
||||
return m_netGroup.writeNetState(fromVersion, rules);
|
||||
}
|
||||
|
||||
void Plant::readNetState(ByteArray data, float interpolationTime) {
|
||||
m_netGroup.readNetState(std::move(data), interpolationTime);
|
||||
void Plant::readNetState(ByteArray data, float interpolationTime, NetCompatibilityRules rules) {
|
||||
m_netGroup.readNetState(data, interpolationTime, rules);
|
||||
}
|
||||
|
||||
void Plant::enableInterpolation(float extrapolationHint) {
|
||||
|
@ -57,10 +57,10 @@ public:
|
||||
Plant(GrassVariant const& config, uint64_t seed);
|
||||
Plant(BushVariant const& config, uint64_t seed);
|
||||
Plant(Json const& diskStore);
|
||||
Plant(ByteArray const& netStore);
|
||||
Plant(ByteArray const& netStore, NetCompatibilityRules rules = {});
|
||||
|
||||
Json diskStore() const;
|
||||
ByteArray netStore() const;
|
||||
ByteArray netStore(NetCompatibilityRules rules = {}) const;
|
||||
|
||||
EntityType entityType() const override;
|
||||
|
||||
@ -68,8 +68,8 @@ public:
|
||||
|
||||
virtual String description() const override;
|
||||
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0) override;
|
||||
void readNetState(ByteArray data, float interpolationTime = 0.0f) override;
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0, NetCompatibilityRules rules = {}) override;
|
||||
void readNetState(ByteArray data, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override;
|
||||
|
||||
void enableInterpolation(float extrapolationHint) override;
|
||||
void disableInterpolation() override;
|
||||
|
@ -86,11 +86,12 @@ PlantDrop::PlantDrop(List<Plant::PlantPiece> pieces, Vec2F const& position, Vec2
|
||||
m_collisionRect = fullBounds;
|
||||
}
|
||||
|
||||
PlantDrop::PlantDrop(ByteArray const& netStore) {
|
||||
PlantDrop::PlantDrop(ByteArray const& netStore, NetCompatibilityRules rules) {
|
||||
m_netGroup.addNetElement(&m_movementController);
|
||||
m_netGroup.addNetElement(&m_spawnedDrops);
|
||||
|
||||
DataStreamBuffer ds(netStore);
|
||||
ds.setStreamCompatibilityVersion(rules);
|
||||
ds >> m_time;
|
||||
ds >> m_master;
|
||||
ds >> m_description;
|
||||
@ -113,7 +114,7 @@ PlantDrop::PlantDrop(ByteArray const& netStore) {
|
||||
m_spawnedDropEffects = true;
|
||||
}
|
||||
|
||||
ByteArray PlantDrop::netStore() {
|
||||
ByteArray PlantDrop::netStore(NetCompatibilityRules rules) {
|
||||
DataStreamBuffer ds;
|
||||
ds << m_time;
|
||||
ds << m_master;
|
||||
@ -358,12 +359,12 @@ void PlantDrop::render(RenderCallback* renderCallback) {
|
||||
}
|
||||
}
|
||||
|
||||
pair<ByteArray, uint64_t> PlantDrop::writeNetState(uint64_t fromVersion) {
|
||||
return m_netGroup.writeNetState(fromVersion);
|
||||
pair<ByteArray, uint64_t> PlantDrop::writeNetState(uint64_t fromVersion, NetCompatibilityRules rules) {
|
||||
return m_netGroup.writeNetState(fromVersion, rules);
|
||||
}
|
||||
|
||||
void PlantDrop::readNetState(ByteArray data, float interpolationTime) {
|
||||
m_netGroup.readNetState(std::move(data), interpolationTime);
|
||||
void PlantDrop::readNetState(ByteArray data, float interpolationTime, NetCompatibilityRules rules) {
|
||||
m_netGroup.readNetState(data, interpolationTime, rules);
|
||||
}
|
||||
|
||||
void PlantDrop::enableInterpolation(float extrapolationHint) {
|
||||
|
@ -15,9 +15,9 @@ public:
|
||||
PlantDrop(List<Plant::PlantPiece> pieces, Vec2F const& position, Vec2F const& strikeVector, String const& description,
|
||||
bool upsideDown, Json stemConfig, Json foliageConfig, Json saplingConfig,
|
||||
bool master, float random);
|
||||
PlantDrop(ByteArray const& netStore);
|
||||
PlantDrop(ByteArray const& netStore, NetCompatibilityRules rules = {});
|
||||
|
||||
ByteArray netStore();
|
||||
ByteArray netStore(NetCompatibilityRules rules = {});
|
||||
|
||||
EntityType entityType() const override;
|
||||
|
||||
@ -26,8 +26,8 @@ public:
|
||||
|
||||
String description() const override;
|
||||
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0) override;
|
||||
void readNetState(ByteArray data, float interpolationTime = 0.0f) override;
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0, NetCompatibilityRules rules = {}) override;
|
||||
void readNetState(ByteArray data, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override;
|
||||
|
||||
void enableInterpolation(float extrapolationHint = 0.0f) override;
|
||||
void disableInterpolation() override;
|
||||
|
@ -187,8 +187,9 @@ Player::Player(PlayerConfigPtr config, Uuid uuid) {
|
||||
m_netGroup.setNeedsStoreCallback(bind(&Player::setNetStates, this));
|
||||
}
|
||||
|
||||
Player::Player(PlayerConfigPtr config, ByteArray const& netStore) : Player(config) {
|
||||
Player::Player(PlayerConfigPtr config, ByteArray const& netStore, NetCompatibilityRules rules) : Player(config) {
|
||||
DataStreamBuffer ds(netStore);
|
||||
ds.setStreamCompatibilityVersion(rules);
|
||||
|
||||
setUniqueId(ds.read<String>());
|
||||
|
||||
@ -1618,12 +1619,12 @@ Direction Player::facingDirection() const {
|
||||
return m_movementController->facingDirection();
|
||||
}
|
||||
|
||||
pair<ByteArray, uint64_t> Player::writeNetState(uint64_t fromVersion) {
|
||||
return m_netGroup.writeNetState(fromVersion);
|
||||
pair<ByteArray, uint64_t> Player::writeNetState(uint64_t fromVersion, NetCompatibilityRules rules) {
|
||||
return m_netGroup.writeNetState(fromVersion, rules);
|
||||
}
|
||||
|
||||
void Player::readNetState(ByteArray data, float interpolationTime) {
|
||||
m_netGroup.readNetState(std::move(data), interpolationTime);
|
||||
void Player::readNetState(ByteArray data, float interpolationTime, NetCompatibilityRules rules) {
|
||||
m_netGroup.readNetState(data, interpolationTime, rules);
|
||||
}
|
||||
|
||||
void Player::enableInterpolation(float) {
|
||||
@ -2319,8 +2320,9 @@ Json Player::diskStore() {
|
||||
};
|
||||
}
|
||||
|
||||
ByteArray Player::netStore() {
|
||||
ByteArray Player::netStore(NetCompatibilityRules rules) {
|
||||
DataStreamBuffer ds;
|
||||
ds.setStreamCompatibilityVersion(rules);
|
||||
|
||||
ds.write(*uniqueId());
|
||||
ds.write(m_description);
|
||||
|
@ -76,7 +76,7 @@ public:
|
||||
static EnumMap<State> const StateNames;
|
||||
|
||||
Player(PlayerConfigPtr config, Uuid uuid = Uuid());
|
||||
Player(PlayerConfigPtr config, ByteArray const& netStore);
|
||||
Player(PlayerConfigPtr config, ByteArray const& netStore, NetCompatibilityRules rules = {});
|
||||
Player(PlayerConfigPtr config, Json const& diskStore);
|
||||
|
||||
void diskLoad(Json const& diskStore);
|
||||
@ -92,7 +92,7 @@ public:
|
||||
QuestManagerPtr questManager() const;
|
||||
|
||||
Json diskStore();
|
||||
ByteArray netStore();
|
||||
ByteArray netStore(NetCompatibilityRules rules = {});
|
||||
|
||||
EntityType entityType() const override;
|
||||
ClientEntityMode clientEntityMode() const override;
|
||||
@ -118,8 +118,8 @@ public:
|
||||
// relative to current position
|
||||
RectF collisionArea() const override;
|
||||
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromStep = 0) override;
|
||||
void readNetState(ByteArray data, float interpolationStep = 0.0f) override;
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0, NetCompatibilityRules rules = {}) override;
|
||||
void readNetState(ByteArray data, float interpolationStep = 0.0f, NetCompatibilityRules rules = {}) override;
|
||||
|
||||
void enableInterpolation(float extrapolationHint = 0.0f) override;
|
||||
void disableInterpolation() override;
|
||||
|
@ -60,8 +60,8 @@ PlayerPtr PlayerFactory::diskLoadPlayer(Json const& diskStore) const {
|
||||
return make_shared<Player>(m_config, diskStore);
|
||||
}
|
||||
|
||||
PlayerPtr PlayerFactory::netLoadPlayer(ByteArray const& netStore) const {
|
||||
return make_shared<Player>(m_config, netStore);
|
||||
PlayerPtr PlayerFactory::netLoadPlayer(ByteArray const& netStore, NetCompatibilityRules rules) const {
|
||||
return make_shared<Player>(m_config, netStore, rules);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ public:
|
||||
|
||||
PlayerPtr create() const;
|
||||
PlayerPtr diskLoadPlayer(Json const& diskStore) const;
|
||||
PlayerPtr netLoadPlayer(ByteArray const& netStore) const;
|
||||
PlayerPtr netLoadPlayer(ByteArray const& netStore, NetCompatibilityRules rules = {}) const;
|
||||
|
||||
private:
|
||||
PlayerConfigPtr m_config;
|
||||
|
@ -27,7 +27,7 @@ Projectile::Projectile(ProjectileConfigPtr const& config, Json const& parameters
|
||||
setup();
|
||||
}
|
||||
|
||||
Projectile::Projectile(ProjectileConfigPtr const& config, DataStreamBuffer& data) {
|
||||
Projectile::Projectile(ProjectileConfigPtr const& config, DataStreamBuffer& data, NetCompatibilityRules rules) {
|
||||
m_config = config;
|
||||
data.read(m_parameters);
|
||||
setup();
|
||||
@ -41,8 +41,9 @@ Projectile::Projectile(ProjectileConfigPtr const& config, DataStreamBuffer& data
|
||||
setTeam(data.read<EntityDamageTeam>());
|
||||
}
|
||||
|
||||
ByteArray Projectile::netStore() const {
|
||||
ByteArray Projectile::netStore(NetCompatibilityRules rules) const {
|
||||
DataStreamBuffer ds;
|
||||
ds.setStreamCompatibilityVersion(rules);
|
||||
|
||||
ds.write(m_config->typeName);
|
||||
ds.write(m_parameters);
|
||||
@ -141,12 +142,12 @@ Vec2F Projectile::velocity() const {
|
||||
return m_movementController->velocity();
|
||||
}
|
||||
|
||||
pair<ByteArray, uint64_t> Projectile::writeNetState(uint64_t fromVersion) {
|
||||
return m_netGroup.writeNetState(fromVersion);
|
||||
pair<ByteArray, uint64_t> Projectile::writeNetState(uint64_t fromVersion, NetCompatibilityRules rules) {
|
||||
return m_netGroup.writeNetState(fromVersion, rules);
|
||||
}
|
||||
|
||||
void Projectile::readNetState(ByteArray data, float interpolationTime) {
|
||||
m_netGroup.readNetState(std::move(data), interpolationTime);
|
||||
void Projectile::readNetState(ByteArray data, float interpolationTime, NetCompatibilityRules rules) {
|
||||
m_netGroup.readNetState(data, interpolationTime, rules);
|
||||
}
|
||||
|
||||
void Projectile::enableInterpolation(float extrapolationHint) {
|
||||
|
@ -22,9 +22,9 @@ STAR_CLASS(Projectile);
|
||||
class Projectile : public virtual Entity, public virtual ScriptedEntity, public virtual PhysicsEntity, public virtual StatusEffectEntity {
|
||||
public:
|
||||
Projectile(ProjectileConfigPtr const& config, Json const& parameters);
|
||||
Projectile(ProjectileConfigPtr const& config, DataStreamBuffer& netState);
|
||||
Projectile(ProjectileConfigPtr const& config, DataStreamBuffer& netState, NetCompatibilityRules rules = {});
|
||||
|
||||
ByteArray netStore() const;
|
||||
ByteArray netStore(NetCompatibilityRules rules = {}) const;
|
||||
|
||||
EntityType entityType() const override;
|
||||
|
||||
@ -43,8 +43,8 @@ public:
|
||||
ClientEntityMode clientEntityMode() const override;
|
||||
bool masterOnly() const override;
|
||||
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0) override;
|
||||
void readNetState(ByteArray data, float interpolationTime = 0.0f) override;
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0, NetCompatibilityRules rules = {}) override;
|
||||
void readNetState(ByteArray data, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override;
|
||||
|
||||
void enableInterpolation(float extrapolationHint = 0.0f) override;
|
||||
void disableInterpolation() override;
|
||||
|
@ -58,10 +58,11 @@ float ProjectileDatabase::gravityMultiplier(String const& type) const {
|
||||
return config->movementSettings.getFloat("gravityMultiplier", 1);
|
||||
}
|
||||
|
||||
ProjectilePtr ProjectileDatabase::netLoadProjectile(ByteArray const& netStore) const {
|
||||
ProjectilePtr ProjectileDatabase::netLoadProjectile(ByteArray const& netStore, NetCompatibilityRules rules) const {
|
||||
DataStreamBuffer ds(netStore);
|
||||
ds.setStreamCompatibilityVersion(rules);
|
||||
String typeName = ds.read<String>();
|
||||
return make_shared<Projectile>(m_configs.get(typeName), ds);
|
||||
return make_shared<Projectile>(m_configs.get(typeName), ds, rules);
|
||||
}
|
||||
|
||||
ProjectileConfigPtr ProjectileDatabase::readConfig(String const& path) {
|
||||
|
@ -111,7 +111,7 @@ public:
|
||||
float gravityMultiplier(String const& type) const;
|
||||
|
||||
ProjectilePtr createProjectile(String const& type, Json const& parameters = JsonObject()) const;
|
||||
ProjectilePtr netLoadProjectile(ByteArray const& netStore) const;
|
||||
ProjectilePtr netLoadProjectile(ByteArray const& netStore, NetCompatibilityRules rules = {}) const;
|
||||
|
||||
private:
|
||||
ProjectileConfigPtr readConfig(String const& path);
|
||||
|
@ -10,10 +10,11 @@
|
||||
|
||||
namespace Star {
|
||||
|
||||
ServerClientContext::ServerClientContext(ConnectionId clientId, Maybe<HostAddress> remoteAddress, Uuid playerUuid,
|
||||
ServerClientContext::ServerClientContext(ConnectionId clientId, Maybe<HostAddress> remoteAddress, NetCompatibilityRules netRules, Uuid playerUuid,
|
||||
String playerName, String playerSpecies, bool canBecomeAdmin, WorldChunks initialShipChunks)
|
||||
: m_clientId(clientId),
|
||||
m_remoteAddress(remoteAddress),
|
||||
m_netRules(netRules),
|
||||
m_playerUuid(playerUuid),
|
||||
m_playerName(playerName),
|
||||
m_playerSpecies(playerSpecies),
|
||||
@ -88,6 +89,10 @@ bool ServerClientContext::canBecomeAdmin() const {
|
||||
return m_canBecomeAdmin;
|
||||
}
|
||||
|
||||
NetCompatibilityRules ServerClientContext::netRules() const {
|
||||
return m_netRules;
|
||||
}
|
||||
|
||||
String ServerClientContext::descriptiveName() const {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
String hostName = m_remoteAddress ? toString(*m_remoteAddress) : "local";
|
||||
@ -184,7 +189,7 @@ ByteArray ServerClientContext::writeUpdate() {
|
||||
shipChunksUpdate = DataStreamBuffer::serialize(take(m_shipChunksUpdate));
|
||||
|
||||
ByteArray netGroupUpdate;
|
||||
tie(netGroupUpdate, m_netVersion) = m_netGroup.writeNetState(m_netVersion);
|
||||
tie(netGroupUpdate, m_netVersion) = m_netGroup.writeNetState(m_netVersion, m_netRules);
|
||||
|
||||
if (rpcUpdate.empty() && shipChunksUpdate.empty() && netGroupUpdate.empty())
|
||||
return {};
|
||||
|
@ -19,7 +19,7 @@ STAR_CLASS(ServerClientContext);
|
||||
|
||||
class ServerClientContext {
|
||||
public:
|
||||
ServerClientContext(ConnectionId clientId, Maybe<HostAddress> remoteAddress, Uuid playerUuid,
|
||||
ServerClientContext(ConnectionId clientId, Maybe<HostAddress> remoteAddress, NetCompatibilityRules netRules, Uuid playerUuid,
|
||||
String playerName, String playerSpecies, bool canBecomeAdmin, WorldChunks initialShipChunks);
|
||||
|
||||
ConnectionId clientId() const;
|
||||
@ -28,6 +28,7 @@ public:
|
||||
String const& playerName() const;
|
||||
String const& playerSpecies() const;
|
||||
bool canBecomeAdmin() const;
|
||||
NetCompatibilityRules netRules() const;
|
||||
String descriptiveName() const;
|
||||
|
||||
// Register additional rpc methods from other server side services.
|
||||
@ -87,6 +88,7 @@ public:
|
||||
private:
|
||||
ConnectionId const m_clientId;
|
||||
Maybe<HostAddress> const m_remoteAddress;
|
||||
NetCompatibilityRules m_netRules;
|
||||
Uuid const m_playerUuid;
|
||||
String const m_playerName;
|
||||
String const m_playerSpecies;
|
||||
|
@ -66,12 +66,12 @@ void Sky::jumpTo(SkyParameters skyParameters) {
|
||||
m_skyParametersUpdated = true;
|
||||
}
|
||||
|
||||
pair<ByteArray, uint64_t> Sky::writeUpdate(uint64_t fromVersion) {
|
||||
return m_netGroup.writeNetState(fromVersion);
|
||||
pair<ByteArray, uint64_t> Sky::writeUpdate(uint64_t fromVersion, NetCompatibilityRules rules) {
|
||||
return m_netGroup.writeNetState(fromVersion, rules);
|
||||
}
|
||||
|
||||
void Sky::readUpdate(ByteArray data) {
|
||||
m_netGroup.readNetState(std::move(data));
|
||||
void Sky::readUpdate(ByteArray data, NetCompatibilityRules rules) {
|
||||
m_netGroup.readNetState(std::move(data), 0.0f, rules);
|
||||
}
|
||||
|
||||
void Sky::stateUpdate() {
|
||||
|
@ -30,8 +30,8 @@ public:
|
||||
|
||||
void jumpTo(SkyParameters SkyParameters);
|
||||
|
||||
pair<ByteArray, uint64_t> writeUpdate(uint64_t fromVersion = 0);
|
||||
void readUpdate(ByteArray data);
|
||||
pair<ByteArray, uint64_t> writeUpdate(uint64_t fromVersion = 0, NetCompatibilityRules rules = {});
|
||||
void readUpdate(ByteArray data, NetCompatibilityRules rules = {});
|
||||
|
||||
// handles flying and warp state transitions
|
||||
void stateUpdate();
|
||||
|
@ -14,8 +14,7 @@ Stagehand::Stagehand(Json const& config)
|
||||
readConfig(config);
|
||||
}
|
||||
|
||||
Stagehand::Stagehand(ByteArray const& netStore)
|
||||
: Stagehand() {
|
||||
Stagehand::Stagehand(ByteArray const& netStore, NetCompatibilityRules rules) : Stagehand() {
|
||||
readConfig(DataStreamBuffer::deserialize<Json>(netStore));
|
||||
}
|
||||
|
||||
@ -31,7 +30,7 @@ Json Stagehand::diskStore() const {
|
||||
return saveData.set("scriptStorage", m_scriptComponent.getScriptStorage());
|
||||
}
|
||||
|
||||
ByteArray Stagehand::netStore() {
|
||||
ByteArray Stagehand::netStore(NetCompatibilityRules rules) {
|
||||
return DataStreamBuffer::serialize(m_config);
|
||||
}
|
||||
|
||||
@ -77,12 +76,12 @@ RectF Stagehand::metaBoundBox() const {
|
||||
return m_boundBox;
|
||||
}
|
||||
|
||||
pair<ByteArray, uint64_t> Stagehand::writeNetState(uint64_t fromVersion) {
|
||||
return m_netGroup.writeNetState(fromVersion);
|
||||
pair<ByteArray, uint64_t> Stagehand::writeNetState(uint64_t fromVersion, NetCompatibilityRules rules) {
|
||||
return m_netGroup.writeNetState(fromVersion, rules);
|
||||
}
|
||||
|
||||
void Stagehand::readNetState(ByteArray data, float) {
|
||||
m_netGroup.readNetState(std::move(data));
|
||||
void Stagehand::readNetState(ByteArray data, float interpolationTime, NetCompatibilityRules rules) {
|
||||
m_netGroup.readNetState(data, interpolationTime, rules);
|
||||
}
|
||||
|
||||
void Stagehand::update(float dt, uint64_t) {
|
||||
|
@ -15,10 +15,10 @@ STAR_CLASS(Stagehand);
|
||||
class Stagehand : public virtual ScriptedEntity {
|
||||
public:
|
||||
Stagehand(Json const& config);
|
||||
Stagehand(ByteArray const& netStore);
|
||||
Stagehand(ByteArray const& netStore, NetCompatibilityRules rules = {});
|
||||
|
||||
Json diskStore() const;
|
||||
ByteArray netStore();
|
||||
ByteArray netStore(NetCompatibilityRules rules = {});
|
||||
|
||||
void init(World* world, EntityId entityId, EntityMode mode) override;
|
||||
void uninit() override;
|
||||
@ -31,8 +31,8 @@ public:
|
||||
|
||||
RectF metaBoundBox() const override;
|
||||
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0) override;
|
||||
void readNetState(ByteArray data, float interpolationTime = 0.0f) override;
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0, NetCompatibilityRules rules = {}) override;
|
||||
void readNetState(ByteArray data, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override;
|
||||
|
||||
void update(float dt, uint64_t currentStep) override;
|
||||
|
||||
|
@ -18,7 +18,32 @@ StatusController::StatusController(Json const& config) : m_statCollection(config
|
||||
m_parentEntity = nullptr;
|
||||
m_movementController = nullptr;
|
||||
|
||||
m_statusProperties.set(config.getObject("statusProperties", {}));
|
||||
m_statusProperties.reset(config.getObject("statusProperties", {}));
|
||||
m_statusProperties.setOverrides(
|
||||
[&](DataStream& ds, NetCompatibilityRules rules) {
|
||||
if (rules.isLegacy) ds << m_statusProperties.baseMap();
|
||||
else m_statusProperties.NetElementHashMap<String, Json>::netStore(ds, rules);
|
||||
},
|
||||
[&](DataStream& ds, NetCompatibilityRules rules) {
|
||||
if (rules.isLegacy) m_statusProperties.reset(ds.read<JsonObject>());
|
||||
else m_statusProperties.NetElementHashMap<String, Json>::netLoad(ds, rules);
|
||||
},
|
||||
[&](DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) {
|
||||
if (rules.isLegacy) {
|
||||
if (m_statusProperties.shouldWriteNetDelta(fromVersion, rules)) {
|
||||
ds << m_statusProperties.baseMap();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return m_statusProperties.NetElementHashMap<String, Json>::writeNetDelta(ds, fromVersion, rules);
|
||||
},
|
||||
[&](DataStream& ds, float interp, NetCompatibilityRules rules) {
|
||||
if (rules.isLegacy) m_statusProperties.reset(ds.read<JsonObject>());
|
||||
else m_statusProperties.NetElementHashMap<String, Json>::readNetDelta(ds, interp, rules);
|
||||
}
|
||||
);
|
||||
|
||||
m_minimumLiquidStatusEffectPercentage = config.getFloat("minimumLiquidStatusEffectPercentage");
|
||||
m_appliesEnvironmentStatusEffects = config.getBool("appliesEnvironmentStatusEffects");
|
||||
m_appliesWeatherStatusEffects = config.getBool("appliesWeatherStatusEffects");
|
||||
@ -72,7 +97,7 @@ Json StatusController::diskStore() const {
|
||||
}
|
||||
|
||||
return JsonObject{
|
||||
{"statusProperties", m_statusProperties.get()},
|
||||
{"statusProperties", m_statusProperties.baseMap()},
|
||||
{"persistentEffectCategories", std::move(persistentEffectCategories)},
|
||||
{"ephemeralEffects", std::move(ephemeralEffects)},
|
||||
{"resourceValues", std::move(resourceValues)},
|
||||
@ -84,7 +109,7 @@ void StatusController::diskLoad(Json const& store) {
|
||||
clearAllPersistentEffects();
|
||||
clearEphemeralEffects();
|
||||
|
||||
m_statusProperties.set(store.getObject("statusProperties"));
|
||||
m_statusProperties.reset(store.getObject("statusProperties"));
|
||||
|
||||
for (auto const& p : store.getObject("persistentEffectCategories", {}))
|
||||
addPersistentEffects(p.first, p.second.toArray().transformed(jsonToPersistentStatusEffect));
|
||||
@ -103,17 +128,11 @@ void StatusController::diskLoad(Json const& store) {
|
||||
}
|
||||
|
||||
Json StatusController::statusProperty(String const& name, Json const& def) const {
|
||||
return m_statusProperties.get().value(name, def);
|
||||
return m_statusProperties.value(name, def);
|
||||
}
|
||||
|
||||
void StatusController::setStatusProperty(String const& name, Json value) {
|
||||
m_statusProperties.update([&](JsonObject& statusProperties) {
|
||||
if (statusProperties[name] != value) {
|
||||
statusProperties[name] = std::move(value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
m_statusProperties.set(name, value);
|
||||
}
|
||||
|
||||
StringList StatusController::statNames() const {
|
||||
@ -415,15 +434,17 @@ void StatusController::initNetVersion(NetElementVersion const* version) {
|
||||
m_netGroup.initNetVersion(version);
|
||||
}
|
||||
|
||||
void StatusController::netStore(DataStream& ds) const {
|
||||
m_netGroup.netStore(ds);
|
||||
void StatusController::netStore(DataStream& ds, NetCompatibilityRules rules) const {
|
||||
if (!checkWithRules(rules)) return;
|
||||
m_netGroup.netStore(ds, rules);
|
||||
}
|
||||
|
||||
void StatusController::netLoad(DataStream& ds) {
|
||||
void StatusController::netLoad(DataStream& ds, NetCompatibilityRules rules) {
|
||||
if (!checkWithRules(rules)) return;
|
||||
clearAllPersistentEffects();
|
||||
clearEphemeralEffects();
|
||||
|
||||
m_netGroup.netLoad(ds);
|
||||
m_netGroup.netLoad(ds, rules);
|
||||
}
|
||||
|
||||
void StatusController::enableNetInterpolation(float extrapolationHint) {
|
||||
@ -438,12 +459,12 @@ void StatusController::tickNetInterpolation(float dt) {
|
||||
m_netGroup.tickNetInterpolation(dt);
|
||||
}
|
||||
|
||||
bool StatusController::writeNetDelta(DataStream& ds, uint64_t fromStep) const {
|
||||
return m_netGroup.writeNetDelta(ds, fromStep);
|
||||
bool StatusController::writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) const {
|
||||
return m_netGroup.writeNetDelta(ds, fromVersion, rules);
|
||||
}
|
||||
|
||||
void StatusController::readNetDelta(DataStream& ds, float interpolationTime) {
|
||||
m_netGroup.readNetDelta(ds, interpolationTime);
|
||||
void StatusController::readNetDelta(DataStream& ds, float interpolationTime, NetCompatibilityRules rules) {
|
||||
m_netGroup.readNetDelta(ds, interpolationTime, rules);
|
||||
}
|
||||
|
||||
void StatusController::blankNetDelta(float interpolationTime) {
|
||||
@ -576,15 +597,17 @@ void StatusController::EffectAnimator::initNetVersion(NetElementVersion const* v
|
||||
animator.initNetVersion(version);
|
||||
}
|
||||
|
||||
void StatusController::EffectAnimator::netStore(DataStream& ds) const {
|
||||
void StatusController::EffectAnimator::netStore(DataStream& ds, NetCompatibilityRules rules) const {
|
||||
if (!checkWithRules(rules)) return;
|
||||
ds.write(animationConfig);
|
||||
animator.netStore(ds);
|
||||
animator.netStore(ds, rules);
|
||||
}
|
||||
|
||||
void StatusController::EffectAnimator::netLoad(DataStream& ds) {
|
||||
void StatusController::EffectAnimator::netLoad(DataStream& ds, NetCompatibilityRules rules) {
|
||||
if (!checkWithRules(rules)) return;
|
||||
ds.read(animationConfig);
|
||||
animator = animationConfig ? NetworkedAnimator(*animationConfig) : NetworkedAnimator();
|
||||
animator.netLoad(ds);
|
||||
animator.netLoad(ds, rules);
|
||||
}
|
||||
|
||||
void StatusController::EffectAnimator::enableNetInterpolation(float extrapolationHint) {
|
||||
@ -599,12 +622,12 @@ void StatusController::EffectAnimator::tickNetInterpolation(float dt) {
|
||||
animator.tickNetInterpolation(dt);
|
||||
}
|
||||
|
||||
bool StatusController::EffectAnimator::writeNetDelta(DataStream& ds, uint64_t fromVersion) const {
|
||||
return animator.writeNetDelta(ds, fromVersion);
|
||||
bool StatusController::EffectAnimator::writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) const {
|
||||
return animator.writeNetDelta(ds, fromVersion, rules);
|
||||
}
|
||||
|
||||
void StatusController::EffectAnimator::readNetDelta(DataStream& ds, float interpolationTime) {
|
||||
animator.readNetDelta(ds, interpolationTime);
|
||||
void StatusController::EffectAnimator::readNetDelta(DataStream& ds, float interpolationTime, NetCompatibilityRules rules) {
|
||||
animator.readNetDelta(ds, interpolationTime, rules);
|
||||
}
|
||||
|
||||
void StatusController::EffectAnimator::blankNetDelta(float interpolationTime) {
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "StarObserverStream.hpp"
|
||||
#include "StarNetElementSystem.hpp"
|
||||
#include "StarNetElementExt.hpp"
|
||||
#include "StarStatCollection.hpp"
|
||||
#include "StarStatusEffectDatabase.hpp"
|
||||
#include "StarDamage.hpp"
|
||||
@ -103,15 +104,15 @@ public:
|
||||
|
||||
void initNetVersion(NetElementVersion const* version = nullptr) override;
|
||||
|
||||
void netStore(DataStream& ds) const override;
|
||||
void netLoad(DataStream& ds) override;
|
||||
void netStore(DataStream& ds, NetCompatibilityRules rules = {}) const override;
|
||||
void netLoad(DataStream& ds, NetCompatibilityRules rules) override;
|
||||
|
||||
void enableNetInterpolation(float extrapolationHint = 0.0f) override;
|
||||
void disableNetInterpolation() override;
|
||||
void tickNetInterpolation(float dt) override;
|
||||
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromVersion) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0) override;
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules = {}) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override;
|
||||
void blankNetDelta(float interpolationTime) override;
|
||||
|
||||
void tickMaster(float dt);
|
||||
@ -136,15 +137,15 @@ private:
|
||||
|
||||
void initNetVersion(NetElementVersion const* version = nullptr) override;
|
||||
|
||||
void netStore(DataStream& ds) const override;
|
||||
void netLoad(DataStream& ds) override;
|
||||
void netStore(DataStream& ds, NetCompatibilityRules rules = {}) const override;
|
||||
void netLoad(DataStream& ds, NetCompatibilityRules rules) override;
|
||||
|
||||
void enableNetInterpolation(float extrapolationHint = 0.0f) override;
|
||||
void disableNetInterpolation() override;
|
||||
void tickNetInterpolation(float dt) override;
|
||||
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromVersion) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0) override;
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules = {}) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override;
|
||||
void blankNetDelta(float interpolationTime) override;
|
||||
|
||||
Maybe<String> animationConfig;
|
||||
@ -203,7 +204,7 @@ private:
|
||||
|
||||
NetElementGroup m_netGroup;
|
||||
StatCollection m_statCollection;
|
||||
NetElementData<JsonObject> m_statusProperties;
|
||||
NetElementOverride<NetElementHashMap<String, Json>> m_statusProperties;
|
||||
NetElementData<DirectivesGroup> m_parentDirectives;
|
||||
|
||||
UniqueEffectMetadataGroup m_uniqueEffectMetadata;
|
||||
|
@ -453,12 +453,12 @@ void SystemObject::serverUpdate(SystemWorldServer* system, float dt) {
|
||||
}
|
||||
}
|
||||
|
||||
pair<ByteArray, uint64_t> SystemObject::writeNetState(uint64_t fromVersion) {
|
||||
return m_netGroup.writeNetState(fromVersion);
|
||||
pair<ByteArray, uint64_t> SystemObject::writeNetState(uint64_t fromVersion, NetCompatibilityRules rules) {
|
||||
return m_netGroup.writeNetState(fromVersion, rules);
|
||||
}
|
||||
|
||||
void SystemObject::readNetState(ByteArray data, float interpolationTime) {
|
||||
m_netGroup.readNetState(std::move(data), interpolationTime);
|
||||
void SystemObject::readNetState(ByteArray data, float interpolationTime, NetCompatibilityRules rules) {
|
||||
m_netGroup.readNetState(data, interpolationTime, rules);
|
||||
}
|
||||
|
||||
ByteArray SystemObject::netStore() const {
|
||||
@ -615,12 +615,12 @@ void SystemClientShip::serverUpdate(SystemWorld* system, float dt) {
|
||||
}
|
||||
}
|
||||
|
||||
pair<ByteArray, uint64_t> SystemClientShip::writeNetState(uint64_t fromVersion) {
|
||||
return m_netGroup.writeNetState(fromVersion);
|
||||
pair<ByteArray, uint64_t> SystemClientShip::writeNetState(uint64_t fromVersion, NetCompatibilityRules rules) {
|
||||
return m_netGroup.writeNetState(fromVersion, rules);
|
||||
}
|
||||
|
||||
void SystemClientShip::readNetState(ByteArray data, float interpolationTime) {
|
||||
m_netGroup.readNetState(std::move(data), interpolationTime);
|
||||
void SystemClientShip::readNetState(ByteArray data, float interpolationTime, NetCompatibilityRules rules) {
|
||||
m_netGroup.readNetState(data, interpolationTime, rules);
|
||||
}
|
||||
|
||||
ByteArray SystemClientShip::netStore() const {
|
||||
|
@ -155,8 +155,8 @@ public:
|
||||
void clientUpdate(float dt);
|
||||
void serverUpdate(SystemWorldServer* system, float dt);
|
||||
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion);
|
||||
void readNetState(ByteArray data, float interpolationTime);
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion, NetCompatibilityRules rules = {});
|
||||
void readNetState(ByteArray data, float interpolationTime, NetCompatibilityRules rules = {});
|
||||
|
||||
ByteArray netStore() const;
|
||||
Json diskStore() const;
|
||||
@ -198,8 +198,8 @@ public:
|
||||
void clientUpdate(float dt);
|
||||
void serverUpdate(SystemWorld* system, float dt);
|
||||
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion);
|
||||
void readNetState(ByteArray data, float interpolationTime);
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion, NetCompatibilityRules rules = {});
|
||||
void readNetState(ByteArray data, float interpolationTime, NetCompatibilityRules rules = {});
|
||||
|
||||
ByteArray netStore() const;
|
||||
private:
|
||||
|
@ -266,7 +266,7 @@ void SystemWorldServer::queueUpdatePackets() {
|
||||
HashMap<Uuid, ByteArray> shipUpdates;
|
||||
for (auto ship : m_ships.values()) {
|
||||
uint64_t version = versions->ships.maybe(ship->uuid()).value(0);
|
||||
auto shipUpdate = ship->writeNetState(version);
|
||||
auto shipUpdate = ship->writeNetState(version, {});
|
||||
versions->ships.set(ship->uuid(), shipUpdate.second);
|
||||
if (!shipUpdate.first.empty())
|
||||
shipUpdates.set(ship->uuid(), shipUpdate.first);
|
||||
@ -275,7 +275,7 @@ void SystemWorldServer::queueUpdatePackets() {
|
||||
HashMap<Uuid, ByteArray> objectUpdates;
|
||||
for (auto object : m_objects.values()) {
|
||||
uint64_t version = versions->objects.maybe(object->uuid()).value(0);
|
||||
auto objectUpdate = object->writeNetState(version);
|
||||
auto objectUpdate = object->writeNetState(version, {});
|
||||
versions->objects.set(object->uuid(), objectUpdate.second);
|
||||
if (!objectUpdate.first.empty())
|
||||
objectUpdates.set(object->uuid(), objectUpdate.first);
|
||||
|
@ -358,15 +358,17 @@ void TechController::TechAnimator::initNetVersion(NetElementVersion const* versi
|
||||
netGroup.initNetVersion(version);
|
||||
}
|
||||
|
||||
void TechController::TechAnimator::netStore(DataStream& ds) const {
|
||||
void TechController::TechAnimator::netStore(DataStream& ds, NetCompatibilityRules rules) const {
|
||||
if (!checkWithRules(rules)) return;
|
||||
ds << animationConfig;
|
||||
netGroup.netStore(ds);
|
||||
netGroup.netStore(ds, rules);
|
||||
}
|
||||
|
||||
void TechController::TechAnimator::netLoad(DataStream& ds) {
|
||||
void TechController::TechAnimator::netLoad(DataStream& ds, NetCompatibilityRules rules) {
|
||||
if (!checkWithRules(rules)) return;
|
||||
ds >> animationConfig;
|
||||
animator = animationConfig ? NetworkedAnimator(*animationConfig) : NetworkedAnimator();
|
||||
netGroup.netLoad(ds);
|
||||
netGroup.netLoad(ds, rules);
|
||||
}
|
||||
|
||||
void TechController::TechAnimator::enableNetInterpolation(float extrapolationHint) {
|
||||
@ -381,12 +383,12 @@ void TechController::TechAnimator::tickNetInterpolation(float dt) {
|
||||
netGroup.tickNetInterpolation(dt);
|
||||
}
|
||||
|
||||
bool TechController::TechAnimator::writeNetDelta(DataStream& ds, uint64_t fromVersion) const {
|
||||
return netGroup.writeNetDelta(ds, fromVersion);
|
||||
bool TechController::TechAnimator::writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) const {
|
||||
return netGroup.writeNetDelta(ds, fromVersion, rules);
|
||||
}
|
||||
|
||||
void TechController::TechAnimator::readNetDelta(DataStream& ds, float interpolationTime) {
|
||||
netGroup.readNetDelta(ds, interpolationTime);
|
||||
void TechController::TechAnimator::readNetDelta(DataStream& ds, float interpolationTime, NetCompatibilityRules rules) {
|
||||
netGroup.readNetDelta(ds, interpolationTime, rules);
|
||||
}
|
||||
|
||||
void TechController::TechAnimator::blankNetDelta(float interpolationTime) {
|
||||
|
@ -90,15 +90,15 @@ private:
|
||||
|
||||
void initNetVersion(NetElementVersion const* version = nullptr) override;
|
||||
|
||||
void netStore(DataStream& ds) const override;
|
||||
void netLoad(DataStream& ds) override;
|
||||
void netStore(DataStream& ds, NetCompatibilityRules rules = {}) const override;
|
||||
void netLoad(DataStream& ds, NetCompatibilityRules rules) override;
|
||||
|
||||
void enableNetInterpolation(float extrapolationHint = 0.0f) override;
|
||||
void disableNetInterpolation() override;
|
||||
void tickNetInterpolation(float dt) override;
|
||||
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromVersion) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0) override;
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules = {}) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override;
|
||||
void blankNetDelta(float interpolationTime) override;
|
||||
|
||||
// If setting invisible, stops all playing audio
|
||||
|
@ -612,15 +612,17 @@ void ToolUser::NetItem::initNetVersion(NetElementVersion const* version) {
|
||||
netItem->initNetVersion(m_netVersion);
|
||||
}
|
||||
|
||||
void ToolUser::NetItem::netStore(DataStream& ds) const {
|
||||
void ToolUser::NetItem::netStore(DataStream& ds, NetCompatibilityRules rules) const {
|
||||
if (!checkWithRules(rules)) return;
|
||||
const_cast<NetItem*>(this)->updateItemDescriptor();
|
||||
m_itemDescriptor.netStore(ds);
|
||||
m_itemDescriptor.netStore(ds, rules);
|
||||
if (auto netItem = as<NetElement>(m_item.get()))
|
||||
netItem->netStore(ds);
|
||||
netItem->netStore(ds, rules);
|
||||
}
|
||||
|
||||
void ToolUser::NetItem::netLoad(DataStream& ds) {
|
||||
m_itemDescriptor.netLoad(ds);
|
||||
void ToolUser::NetItem::netLoad(DataStream& ds, NetCompatibilityRules rules) {
|
||||
if (!checkWithRules(rules)) return;
|
||||
m_itemDescriptor.netLoad(ds, rules);
|
||||
|
||||
auto itemDatabase = Root::singleton().itemDatabase();
|
||||
if (itemDatabase->loadItem(m_itemDescriptor.get(), m_item)) {
|
||||
@ -633,7 +635,7 @@ void ToolUser::NetItem::netLoad(DataStream& ds) {
|
||||
}
|
||||
|
||||
if (auto netItem = as<NetElement>(m_item.get()))
|
||||
netItem->netLoad(ds);
|
||||
netItem->netLoad(ds, rules);
|
||||
}
|
||||
|
||||
void ToolUser::NetItem::enableNetInterpolation(float extrapolationHint) {
|
||||
@ -657,23 +659,24 @@ void ToolUser::NetItem::tickNetInterpolation(float dt) {
|
||||
}
|
||||
}
|
||||
|
||||
bool ToolUser::NetItem::writeNetDelta(DataStream& ds, uint64_t fromVersion) const {
|
||||
bool ToolUser::NetItem::writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules) const {
|
||||
if (!checkWithRules(rules)) return false;
|
||||
bool deltaWritten = false;
|
||||
const_cast<NetItem*>(this)->updateItemDescriptor();
|
||||
m_buffer.clear();
|
||||
if (m_itemDescriptor.writeNetDelta(m_buffer, fromVersion)) {
|
||||
if (m_itemDescriptor.writeNetDelta(m_buffer, fromVersion, rules)) {
|
||||
deltaWritten = true;
|
||||
ds.write<uint8_t>(1);
|
||||
ds.writeBytes(m_buffer.data());
|
||||
if (auto netItem = as<NetElement>(m_item.get())) {
|
||||
ds.write<uint8_t>(2);
|
||||
netItem->netStore(ds);
|
||||
netItem->netStore(ds, rules);
|
||||
}
|
||||
}
|
||||
|
||||
if (auto netItem = as<NetElement>(m_item.get())) {
|
||||
m_buffer.clear();
|
||||
if (netItem->writeNetDelta(m_buffer, fromVersion)) {
|
||||
if (netItem->writeNetDelta(m_buffer, fromVersion, rules)) {
|
||||
deltaWritten = true;
|
||||
ds.write<uint8_t>(3);
|
||||
ds.writeBytes(m_buffer.data());
|
||||
@ -685,13 +688,14 @@ bool ToolUser::NetItem::writeNetDelta(DataStream& ds, uint64_t fromVersion) cons
|
||||
return deltaWritten;
|
||||
}
|
||||
|
||||
void ToolUser::NetItem::readNetDelta(DataStream& ds, float interpolationTime) {
|
||||
void ToolUser::NetItem::readNetDelta(DataStream& ds, float interpolationTime, NetCompatibilityRules rules) {
|
||||
if (!checkWithRules(rules)) return;
|
||||
while (true) {
|
||||
uint8_t code = ds.read<uint8_t>();
|
||||
if (code == 0) {
|
||||
break;
|
||||
} else if (code == 1) {
|
||||
m_itemDescriptor.readNetDelta(ds);
|
||||
m_itemDescriptor.readNetDelta(ds, 0.0f, rules);
|
||||
if (!m_item || !m_item->matches(m_itemDescriptor.get(), true)) {
|
||||
auto itemDatabase = Root::singleton().itemDatabase();
|
||||
if (itemDatabase->loadItem(m_itemDescriptor.get(), m_item)) {
|
||||
@ -705,12 +709,12 @@ void ToolUser::NetItem::readNetDelta(DataStream& ds, float interpolationTime) {
|
||||
}
|
||||
} else if (code == 2) {
|
||||
if (auto netItem = as<NetElement>(m_item.get()))
|
||||
netItem->netLoad(ds);
|
||||
netItem->netLoad(ds, rules);
|
||||
else
|
||||
throw IOException("Server/Client disagreement about whether an Item is a NetElement in NetItem::readNetDelta");
|
||||
} else if (code == 3) {
|
||||
if (auto netItem = as<NetElement>(m_item.get()))
|
||||
netItem->readNetDelta(ds, interpolationTime);
|
||||
netItem->readNetDelta(ds, interpolationTime, rules);
|
||||
else
|
||||
throw IOException("Server/Client disagreement about whether an Item is a NetElement in NetItem::readNetDelta");
|
||||
} else {
|
||||
|
@ -81,15 +81,15 @@ private:
|
||||
public:
|
||||
void initNetVersion(NetElementVersion const* version = nullptr) override;
|
||||
|
||||
void netStore(DataStream& ds) const override;
|
||||
void netLoad(DataStream& ds) override;
|
||||
void netStore(DataStream& ds, NetCompatibilityRules rules = {}) const override;
|
||||
void netLoad(DataStream& ds, NetCompatibilityRules rules) override;
|
||||
|
||||
void enableNetInterpolation(float extrapolationHint = 0.0f) override;
|
||||
void disableNetInterpolation() override;
|
||||
void tickNetInterpolation(float dt) override;
|
||||
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromVersion) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0) override;
|
||||
bool writeNetDelta(DataStream& ds, uint64_t fromVersion, NetCompatibilityRules rules = {}) const override;
|
||||
void readNetDelta(DataStream& ds, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override;
|
||||
void blankNetDelta(float interpolationTime) override;
|
||||
|
||||
ItemPtr const& get() const;
|
||||
|
@ -94,7 +94,8 @@ Maybe<String> UniverseClient::connect(UniverseConnection connection, bool allowA
|
||||
else if (!protocolResponsePacket->allowed)
|
||||
return String(strf("Join failed! Server does not support connections with protocol version {}", StarProtocolVersion));
|
||||
|
||||
if (!(m_legacyServer = protocolResponsePacket->compressionMode() != PacketCompressionMode::Enabled)) {
|
||||
bool legacyServer = protocolResponsePacket->compressionMode() != PacketCompressionMode::Enabled;
|
||||
if (!legacyServer) {
|
||||
if (auto compressedSocket = as<CompressedPacketSocket>(&connection.packetSocket())) {
|
||||
if (protocolResponsePacket->info) {
|
||||
auto compressionName = protocolResponsePacket->info.getString("compression", "None");
|
||||
@ -104,13 +105,13 @@ Maybe<String> UniverseClient::connect(UniverseConnection connection, bool allowA
|
||||
|
||||
Logger::info("UniverseClient: Using '{}' network stream compression", NetCompressionModeNames.getRight(*compressionMode));
|
||||
compressedSocket->setCompressionStreamEnabled(compressionMode == NetCompressionMode::Zstd);
|
||||
} else if (!m_legacyServer) {
|
||||
} else {
|
||||
Logger::info("UniverseClient: Defaulting to Zstd network stream compression (older server version)");
|
||||
compressedSocket->setCompressionStreamEnabled(true);// old OpenSB server version always expects it!
|
||||
}
|
||||
}
|
||||
}
|
||||
connection.packetSocket().setLegacy(m_legacyServer);
|
||||
connection.packetSocket().setLegacy(legacyServer);
|
||||
auto clientConnect = make_shared<ClientConnectPacket>(Root::singleton().assets()->digest(), allowAssetsMismatch, m_mainPlayer->uuid(), m_mainPlayer->name(),
|
||||
m_mainPlayer->species(), m_playerStorage->loadShipData(m_mainPlayer->uuid()), m_mainPlayer->shipUpgrades(),
|
||||
m_mainPlayer->log()->introComplete(), account);
|
||||
@ -133,14 +134,18 @@ Maybe<String> UniverseClient::connect(UniverseConnection connection, bool allowA
|
||||
packet = connection.pullSingle();
|
||||
}
|
||||
|
||||
NetCompatibilityRules compatibilityRules;
|
||||
compatibilityRules.isLegacy = legacyServer;
|
||||
|
||||
if (auto success = as<ConnectSuccessPacket>(packet)) {
|
||||
m_universeClock = make_shared<Clock>();
|
||||
m_clientContext = make_shared<ClientContext>(success->serverUuid, m_mainPlayer->uuid());
|
||||
m_clientContext->setNetCompatibilityRules(compatibilityRules);
|
||||
m_teamClient = make_shared<TeamClient>(m_mainPlayer, m_clientContext);
|
||||
m_mainPlayer->setClientContext(m_clientContext);
|
||||
m_mainPlayer->setStatistics(m_statistics);
|
||||
m_worldClient = make_shared<WorldClient>(m_mainPlayer);
|
||||
m_worldClient->clientState().setLegacy(m_legacyServer);
|
||||
m_worldClient->clientState().setNetCompatibilityRules(compatibilityRules);
|
||||
m_worldClient->setAsyncLighting(true);
|
||||
for (auto& pair : m_luaCallbacks)
|
||||
m_worldClient->setLuaCallbacks(pair.first, pair.second);
|
||||
@ -149,7 +154,7 @@ Maybe<String> UniverseClient::connect(UniverseConnection connection, bool allowA
|
||||
m_celestialDatabase = make_shared<CelestialSlaveDatabase>(std::move(success->celestialInformation));
|
||||
m_systemWorldClient = make_shared<SystemWorldClient>(m_universeClock, m_celestialDatabase, m_mainPlayer->universeMap());
|
||||
|
||||
Logger::info("UniverseClient: Joined {} server as client {}", m_legacyServer ? "Starbound" : "OpenStarbound", success->clientId);
|
||||
Logger::info("UniverseClient: Joined {} server as client {}", legacyServer ? "Starbound" : "OpenStarbound", success->clientId);
|
||||
return {};
|
||||
} else if (auto failure = as<ConnectFailurePacket>(packet)) {
|
||||
Logger::error("UniverseClient: Join failed: {}", failure->reason);
|
||||
@ -263,7 +268,7 @@ void UniverseClient::update(float dt) {
|
||||
|
||||
m_teamClient->update();
|
||||
|
||||
auto contextUpdate = m_clientContext->writeUpdate();
|
||||
auto contextUpdate = m_clientContext->writeUpdate(m_clientContext->netCompatibilityRules());
|
||||
if (!contextUpdate.empty())
|
||||
m_connection->pushSingle(make_shared<ClientContextUpdatePacket>(std::move(contextUpdate)));
|
||||
|
||||
@ -650,7 +655,7 @@ void UniverseClient::handlePackets(List<PacketPtr> const& packets) {
|
||||
for (auto const& packet : packets) {
|
||||
try {
|
||||
if (auto clientContextUpdate = as<ClientContextUpdatePacket>(packet)) {
|
||||
m_clientContext->readUpdate(clientContextUpdate->updateData);
|
||||
m_clientContext->readUpdate(clientContextUpdate->updateData, m_clientContext->netCompatibilityRules());
|
||||
m_playerStorage->applyShipUpdates(m_clientContext->playerUuid(), m_clientContext->newShipUpdates());
|
||||
|
||||
if (playerIsOriginal())
|
||||
|
@ -126,7 +126,6 @@ private:
|
||||
StatisticsPtr m_statistics;
|
||||
PlayerPtr m_mainPlayer;
|
||||
|
||||
bool m_legacyServer;
|
||||
bool m_pause;
|
||||
ClockPtr m_universeClock;
|
||||
WorldClientPtr m_worldClient;
|
||||
|
@ -835,7 +835,10 @@ void UniverseServer::warpPlayers() {
|
||||
// Checking the spawn target validity then adding the client is not
|
||||
// perfect, it can still become invalid in between, if we fail at
|
||||
// adding the client we need to warp them back.
|
||||
if (toWorld && toWorld->addClient(clientId, warpToWorld.target, !clientContext->remoteAddress(), clientContext->canBecomeAdmin())) {
|
||||
if (toWorld && toWorld->addClient(clientId, warpToWorld.target,
|
||||
!clientContext->remoteAddress(),
|
||||
clientContext->canBecomeAdmin(),
|
||||
clientContext->netRules())) {
|
||||
clientContext->setPlayerWorld(toWorld);
|
||||
m_chatProcessor->joinChannel(clientId, printWorldId(warpToWorld.world));
|
||||
|
||||
@ -1698,7 +1701,8 @@ void UniverseServer::acceptConnection(UniverseConnection connection, Maybe<HostA
|
||||
}
|
||||
|
||||
ConnectionId clientId = m_clients.nextId();
|
||||
auto clientContext = make_shared<ServerClientContext>(clientId, remoteAddress, clientConnect->playerUuid,
|
||||
NetCompatibilityRules netRules(legacyClient);
|
||||
auto clientContext = make_shared<ServerClientContext>(clientId, remoteAddress, netRules, clientConnect->playerUuid,
|
||||
clientConnect->playerName, clientConnect->playerSpecies, administrator, clientConnect->shipChunks);
|
||||
m_clients.add(clientId, clientContext);
|
||||
m_connectionServer->addConnection(clientId, std::move(connection));
|
||||
|
@ -242,12 +242,12 @@ Vec2F Vehicle::velocity() const {
|
||||
return m_movementController.velocity();
|
||||
}
|
||||
|
||||
pair<ByteArray, uint64_t> Vehicle::writeNetState(uint64_t fromVersion) {
|
||||
return m_netGroup.writeNetState(fromVersion);
|
||||
pair<ByteArray, uint64_t> Vehicle::writeNetState(uint64_t fromVersion, NetCompatibilityRules rules) {
|
||||
return m_netGroup.writeNetState(fromVersion, rules);
|
||||
}
|
||||
|
||||
void Vehicle::readNetState(ByteArray data, float interpolationTime) {
|
||||
m_netGroup.readNetState(std::move(data), interpolationTime);
|
||||
void Vehicle::readNetState(ByteArray data, float interpolationTime, NetCompatibilityRules rules) {
|
||||
m_netGroup.readNetState(data, interpolationTime, rules);
|
||||
}
|
||||
|
||||
void Vehicle::enableInterpolation(float extrapolationHint) {
|
||||
|
@ -44,8 +44,8 @@ public:
|
||||
RectF collisionArea() const override;
|
||||
Vec2F velocity() const;
|
||||
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion) override;
|
||||
void readNetState(ByteArray data, float interpolationTime = 0) override;
|
||||
pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0, NetCompatibilityRules rules = {}) override;
|
||||
void readNetState(ByteArray data, float interpolationTime = 0.0f, NetCompatibilityRules rules = {}) override;
|
||||
|
||||
void enableInterpolation(float extrapolationHint) override;
|
||||
void disableInterpolation() override;
|
||||
|
@ -10,7 +10,7 @@ VehicleDatabase::VehicleDatabase() {
|
||||
auto assets = Root::singleton().assets();
|
||||
auto& files = assets->scanExtension("vehicle");
|
||||
assets->queueJsons(files);
|
||||
for (auto& file : files) {
|
||||
for (String file : files) {
|
||||
try {
|
||||
auto config = assets->json(file);
|
||||
String name = config.getString("name");
|
||||
@ -32,15 +32,18 @@ VehiclePtr VehicleDatabase::create(String const& vehicleName, Json const& extraC
|
||||
return make_shared<Vehicle>(configPair->second, configPair->first, extraConfig);
|
||||
}
|
||||
|
||||
ByteArray VehicleDatabase::netStore(VehiclePtr const& vehicle) const {
|
||||
ByteArray VehicleDatabase::netStore(VehiclePtr const& vehicle, NetCompatibilityRules rules) const {
|
||||
DataStreamBuffer ds;
|
||||
ds.setStreamCompatibilityVersion(rules);
|
||||
|
||||
ds.write(vehicle->baseConfig().getString("name"));
|
||||
ds.write(vehicle->dynamicConfig());
|
||||
return ds.takeData();
|
||||
}
|
||||
|
||||
VehiclePtr VehicleDatabase::netLoad(ByteArray const& netStore) const {
|
||||
VehiclePtr VehicleDatabase::netLoad(ByteArray const& netStore, NetCompatibilityRules rules) const {
|
||||
DataStreamBuffer ds(netStore);
|
||||
ds.setStreamCompatibilityVersion(rules);
|
||||
|
||||
String name = ds.read<String>();
|
||||
auto dynamicConfig = ds.read<Json>();
|
||||
|
@ -13,8 +13,8 @@ public:
|
||||
|
||||
VehiclePtr create(String const& vehicleName, Json const& extraConfig = Json()) const;
|
||||
|
||||
ByteArray netStore(VehiclePtr const& vehicle) const;
|
||||
VehiclePtr netLoad(ByteArray const& netStore) const;
|
||||
ByteArray netStore(VehiclePtr const& vehicle, NetCompatibilityRules rules) const;
|
||||
VehiclePtr netLoad(ByteArray const& netStore, NetCompatibilityRules rules) const;
|
||||
|
||||
Json diskStore(VehiclePtr const& vehicle) const;
|
||||
VehiclePtr diskLoad(Json const& diskStore) const;
|
||||
|
@ -55,9 +55,9 @@ void ServerWeather::setClientVisibleRegions(List<RectI> regions) {
|
||||
m_clientVisibleRegions = std::move(regions);
|
||||
}
|
||||
|
||||
pair<ByteArray, uint64_t> ServerWeather::writeUpdate(uint64_t fromVersion) {
|
||||
pair<ByteArray, uint64_t> ServerWeather::writeUpdate(uint64_t fromVersion, NetCompatibilityRules rules) {
|
||||
setNetStates();
|
||||
return m_netGroup.writeNetState(fromVersion);
|
||||
return m_netGroup.writeNetState(fromVersion, rules);
|
||||
}
|
||||
|
||||
void ServerWeather::update(double dt) {
|
||||
@ -263,9 +263,9 @@ void ClientWeather::setup(WorldGeometry worldGeometry, WeatherEffectsActiveQuery
|
||||
m_currentTime = 0.0;
|
||||
}
|
||||
|
||||
void ClientWeather::readUpdate(ByteArray data) {
|
||||
void ClientWeather::readUpdate(ByteArray data, NetCompatibilityRules rules) {
|
||||
if (!data.empty()) {
|
||||
m_netGroup.readNetState(std::move(data));
|
||||
m_netGroup.readNetState(data, 0.0f, rules);
|
||||
getNetStates();
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ public:
|
||||
|
||||
void setClientVisibleRegions(List<RectI> regions);
|
||||
|
||||
pair<ByteArray, uint64_t> writeUpdate(uint64_t fromVersion = 0);
|
||||
pair<ByteArray, uint64_t> writeUpdate(uint64_t fromVersion = 0, NetCompatibilityRules rules = {});
|
||||
|
||||
void update(double dt);
|
||||
|
||||
@ -80,7 +80,7 @@ public:
|
||||
|
||||
void setup(WorldGeometry worldGeometry, WeatherEffectsActiveQuery weatherEffectsActiveQuery);
|
||||
|
||||
void readUpdate(ByteArray data);
|
||||
void readUpdate(ByteArray data, NetCompatibilityRules rules);
|
||||
|
||||
void setVisibleRegion(RectI visibleRegion);
|
||||
|
||||
|
@ -168,7 +168,8 @@ void WorldClient::removeEntity(EntityId entityId, bool andDie) {
|
||||
}
|
||||
|
||||
if (auto version = m_masterEntitiesNetVersion.maybeTake(entity->entityId())) {
|
||||
ByteArray finalNetState = entity->writeNetState(*version).first;
|
||||
auto netRules = m_clientState.netCompatibilityRules();
|
||||
ByteArray finalNetState = entity->writeNetState(*version, netRules).first;
|
||||
m_outgoingPackets.append(make_shared<EntityDestroyPacket>(entity->entityId(), std::move(finalNetState), andDie));
|
||||
}
|
||||
|
||||
@ -767,7 +768,7 @@ void WorldClient::handleIncomingPackets(List<PacketPtr> const& packets) {
|
||||
}
|
||||
|
||||
auto entity = entityFactory->netLoadEntity(entityCreate->entityType, entityCreate->storeData);
|
||||
entity->readNetState(entityCreate->firstNetState);
|
||||
entity->readNetState(entityCreate->firstNetState, 0.0f, m_clientState.netCompatibilityRules());
|
||||
entity->init(this, entityCreate->entityId, EntityMode::Slave);
|
||||
m_entityMap->addEntity(entity);
|
||||
|
||||
@ -788,13 +789,13 @@ void WorldClient::handleIncomingPackets(List<PacketPtr> const& packets) {
|
||||
EntityId entityId = entity->entityId();
|
||||
if (connectionForEntity(entityId) == entityUpdateSet->forConnection) {
|
||||
starAssert(entity->isSlave());
|
||||
entity->readNetState(entityUpdateSet->deltas.value(entityId), interpolationLeadTime);
|
||||
entity->readNetState(entityUpdateSet->deltas.value(entityId), interpolationLeadTime, m_clientState.netCompatibilityRules());
|
||||
}
|
||||
});
|
||||
|
||||
} else if (auto entityDestroy = as<EntityDestroyPacket>(packet)) {
|
||||
if (auto entity = m_entityMap->entity(entityDestroy->entityId)) {
|
||||
entity->readNetState(entityDestroy->finalNetState, m_interpolationTracker.interpolationLeadTime());
|
||||
entity->readNetState(entityDestroy->finalNetState, m_interpolationTracker.interpolationLeadTime(), m_clientState.netCompatibilityRules());
|
||||
|
||||
// Before destroying the entity, we should make sure that the entity is
|
||||
// using the absolute latest data, so we disable interpolation.
|
||||
@ -909,8 +910,8 @@ void WorldClient::handleIncomingPackets(List<PacketPtr> const& packets) {
|
||||
m_interpolationTracker.receiveTimeUpdate(stepUpdate->remoteTime);
|
||||
|
||||
} else if (auto environmentUpdatePacket = as<EnvironmentUpdatePacket>(packet)) {
|
||||
m_sky->readUpdate(environmentUpdatePacket->skyDelta);
|
||||
m_weather.readUpdate(environmentUpdatePacket->weatherDelta);
|
||||
m_sky->readUpdate(environmentUpdatePacket->skyDelta, m_clientState.netCompatibilityRules());
|
||||
m_weather.readUpdate(environmentUpdatePacket->weatherDelta, m_clientState.netCompatibilityRules());
|
||||
|
||||
} else if (auto hit = as<HitRequestPacket>(packet)) {
|
||||
m_damageManager->pushRemoteHitRequest(hit->remoteHitRequest);
|
||||
@ -1229,7 +1230,7 @@ void WorldClient::update(float dt) {
|
||||
|
||||
queueUpdatePackets(m_entityUpdateTimer.wrapTick(dt));
|
||||
|
||||
if ((!m_clientState.legacy() && m_currentStep % 3 == 0) || m_pingTime.isNothing()) {
|
||||
if ((!m_clientState.netCompatibilityRules().isLegacy && m_currentStep % 3 == 0) || m_pingTime.isNothing()) {
|
||||
m_pingTime = Time::monotonicMilliseconds();
|
||||
m_outgoingPackets.append(make_shared<PingPacket>(*m_pingTime));
|
||||
}
|
||||
@ -1325,7 +1326,8 @@ void WorldClient::addEntity(EntityPtr const& entity, EntityId entityId) {
|
||||
notifyEntityCreate(entity);
|
||||
} else {
|
||||
auto entityFactory = Root::singleton().entityFactory();
|
||||
m_outgoingPackets.append(make_shared<SpawnEntityPacket>(entity->entityType(), entityFactory->netStoreEntity(entity), entity->writeNetState().first));
|
||||
auto netRules = m_clientState.netCompatibilityRules();
|
||||
m_outgoingPackets.append(make_shared<SpawnEntityPacket>(entity->entityType(), entityFactory->netStoreEntity(entity), entity->writeNetState(0, netRules).first));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1456,9 +1458,10 @@ void WorldClient::queueUpdatePackets(bool sendEntityUpdates) {
|
||||
if (sendEntityUpdates) {
|
||||
auto entityUpdateSet = make_shared<EntityUpdateSetPacket>();
|
||||
entityUpdateSet->forConnection = *m_clientId;
|
||||
auto netRules = m_clientState.netCompatibilityRules();
|
||||
m_entityMap->forAllEntities([&](EntityPtr const& entity) {
|
||||
if (auto version = m_masterEntitiesNetVersion.ptr(entity->entityId())) {
|
||||
auto updateAndVersion = entity->writeNetState(*version);
|
||||
auto updateAndVersion = entity->writeNetState(*version, netRules);
|
||||
if (!updateAndVersion.first.empty())
|
||||
entityUpdateSet->deltas[entity->entityId()] = std::move(updateAndVersion.first);
|
||||
*version = updateAndVersion.second;
|
||||
@ -1789,13 +1792,13 @@ void WorldClient::initWorld(WorldStartPacket const& startPacket) {
|
||||
centerClientWindowOnPlayer();
|
||||
|
||||
m_sky = make_shared<Sky>();
|
||||
m_sky->readUpdate(startPacket.skyData);
|
||||
m_sky->readUpdate(startPacket.skyData, m_clientState.netCompatibilityRules());
|
||||
|
||||
m_weather.setup(m_geometry, [this](Vec2I const& pos) {
|
||||
auto const& tile = m_tileArray->tile(pos);
|
||||
return !isRealMaterial(tile.background) && !isSolidColliding(tile.getCollision());
|
||||
});
|
||||
m_weather.readUpdate(startPacket.weatherData);
|
||||
m_weather.readUpdate(startPacket.weatherData, m_clientState.netCompatibilityRules());
|
||||
|
||||
m_lightingCalculator.setMonochrome(Root::singleton().configuration()->get("monochromeLighting").toBool());
|
||||
m_lightingCalculator.setParameters(assets->json("/lighting.config:lighting"));
|
||||
@ -1870,7 +1873,8 @@ void WorldClient::tryGiveMainPlayerItem(ItemPtr item, bool silent) {
|
||||
void WorldClient::notifyEntityCreate(EntityPtr const& entity) {
|
||||
if (entity->isMaster() && !m_masterEntitiesNetVersion.contains(entity->entityId())) {
|
||||
// Server was unaware of this entity until now
|
||||
auto firstNetState = entity->writeNetState();
|
||||
auto netRules = m_clientState.netCompatibilityRules();
|
||||
auto firstNetState = entity->writeNetState(0, netRules);
|
||||
m_masterEntitiesNetVersion[entity->entityId()] = firstNetState.second;
|
||||
m_outgoingPackets.append(make_shared<EntityCreatePacket>(entity->entityType(),
|
||||
Root::singleton().entityFactory()->netStoreEntity(entity), std::move(firstNetState.first), entity->entityId()));
|
||||
|
@ -22,8 +22,6 @@ WorldClientState::WorldClientState() {
|
||||
|
||||
m_netGroup.addNetElement(&m_playerId);
|
||||
m_netGroup.addNetElement(&m_clientPresenceEntities);
|
||||
|
||||
m_legacy = false;
|
||||
}
|
||||
|
||||
RectI WorldClientState::window() const {
|
||||
@ -81,20 +79,20 @@ List<RectI> WorldClientState::monitoringRegions(function<Maybe<RectI>(EntityId)>
|
||||
|
||||
ByteArray WorldClientState::writeDelta() {
|
||||
ByteArray delta;
|
||||
tie(delta, m_netVersion) = m_netGroup.writeNetState(m_netVersion);
|
||||
tie(delta, m_netVersion) = m_netGroup.writeNetState(m_netVersion, m_netCompatibilityRules);
|
||||
return delta;
|
||||
}
|
||||
|
||||
void WorldClientState::readDelta(ByteArray delta) {
|
||||
m_netGroup.readNetState(std::move(delta));
|
||||
m_netGroup.readNetState(std::move(delta), 0.0f, m_netCompatibilityRules);
|
||||
}
|
||||
|
||||
void WorldClientState::setLegacy(bool legacy) {
|
||||
m_legacy = legacy;
|
||||
void WorldClientState::setNetCompatibilityRules(NetCompatibilityRules netCompatibilityRules) {
|
||||
m_netCompatibilityRules = netCompatibilityRules;
|
||||
}
|
||||
|
||||
bool WorldClientState::legacy() const {
|
||||
return m_legacy;
|
||||
NetCompatibilityRules WorldClientState::netCompatibilityRules() const {
|
||||
return m_netCompatibilityRules;
|
||||
}
|
||||
|
||||
void WorldClientState::reset() {
|
||||
|
@ -36,9 +36,8 @@ public:
|
||||
ByteArray writeDelta();
|
||||
void readDelta(ByteArray delta);
|
||||
|
||||
// Whether the client is connected to a legacy server.
|
||||
void setLegacy(bool legacy);
|
||||
bool legacy() const;
|
||||
void setNetCompatibilityRules(NetCompatibilityRules netCompatibilityRules);
|
||||
NetCompatibilityRules netCompatibilityRules() const;
|
||||
|
||||
void reset();
|
||||
|
||||
@ -57,7 +56,7 @@ private:
|
||||
NetElementInt m_playerId;
|
||||
NetElementData<List<EntityId>> m_clientPresenceEntities;
|
||||
|
||||
bool m_legacy;
|
||||
NetCompatibilityRules m_netCompatibilityRules;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ bool WorldServer::spawnTargetValid(SpawnTarget const& spawnTarget) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WorldServer::addClient(ConnectionId clientId, SpawnTarget const& spawnTarget, bool isLocal, bool isAdmin) {
|
||||
bool WorldServer::addClient(ConnectionId clientId, SpawnTarget const& spawnTarget, bool isLocal, bool isAdmin, NetCompatibilityRules netRules) {
|
||||
if (m_clientInfo.contains(clientId))
|
||||
return false;
|
||||
|
||||
@ -246,6 +246,7 @@ bool WorldServer::addClient(ConnectionId clientId, SpawnTarget const& spawnTarge
|
||||
auto& clientInfo = m_clientInfo.add(clientId, make_shared<ClientInfo>(clientId, tracker));
|
||||
clientInfo->local = isLocal;
|
||||
clientInfo->admin = isAdmin;
|
||||
clientInfo->clientState.setNetCompatibilityRules(netRules);
|
||||
|
||||
auto worldStartPacket = make_shared<WorldStartPacket>();
|
||||
auto& templateData = worldStartPacket->templateData = m_worldTemplate->store();
|
||||
@ -254,8 +255,8 @@ bool WorldServer::addClient(ConnectionId clientId, SpawnTarget const& spawnTarge
|
||||
&& Root::singletonPtr()->configuration()->getPath("compatibility.customDungeonWorld").optBool().value(false))
|
||||
worldStartPacket->templateData = worldStartPacket->templateData.setPath("worldParameters.primaryDungeon", "testarena");
|
||||
|
||||
tie(worldStartPacket->skyData, clientInfo->skyNetVersion) = m_sky->writeUpdate();
|
||||
tie(worldStartPacket->weatherData, clientInfo->weatherNetVersion) = m_weather.writeUpdate();
|
||||
tie(worldStartPacket->skyData, clientInfo->skyNetVersion) = m_sky->writeUpdate(0, netRules);
|
||||
tie(worldStartPacket->weatherData, clientInfo->weatherNetVersion) = m_weather.writeUpdate(0, netRules);
|
||||
worldStartPacket->playerStart = playerStart;
|
||||
worldStartPacket->playerRespawn = m_playerStart;
|
||||
worldStartPacket->respawnInWorld = m_respawnInWorld;
|
||||
@ -381,7 +382,7 @@ void WorldServer::handleIncomingPackets(ConnectionId clientId, List<PacketPtr> c
|
||||
|
||||
} else if (auto sepacket = as<SpawnEntityPacket>(packet)) {
|
||||
auto entity = entityFactory->netLoadEntity(sepacket->entityType, std::move(sepacket->storeData));
|
||||
entity->readNetState(std::move(sepacket->firstNetState));
|
||||
entity->readNetState(std::move(sepacket->firstNetState), 0.0f, clientInfo->clientState.netCompatibilityRules());
|
||||
addEntity(std::move(entity));
|
||||
|
||||
} else if (auto rdpacket = as<RequestDropPacket>(packet)) {
|
||||
@ -434,7 +435,7 @@ void WorldServer::handleIncomingPackets(ConnectionId clientId, List<PacketPtr> c
|
||||
}
|
||||
|
||||
auto entity = entityFactory->netLoadEntity(entityCreate->entityType, entityCreate->storeData);
|
||||
entity->readNetState(entityCreate->firstNetState);
|
||||
entity->readNetState(entityCreate->firstNetState, 0.0f, clientInfo->clientState.netCompatibilityRules());
|
||||
entity->init(this, entityCreate->entityId, EntityMode::Slave);
|
||||
m_entityMap->addEntity(entity);
|
||||
|
||||
@ -448,14 +449,14 @@ void WorldServer::handleIncomingPackets(ConnectionId clientId, List<PacketPtr> c
|
||||
EntityId entityId = entity->entityId();
|
||||
if (connectionForEntity(entityId) == clientId) {
|
||||
starAssert(entity->isSlave());
|
||||
entity->readNetState(entityUpdateSet->deltas.value(entityId), interpolationLeadTime);
|
||||
entity->readNetState(entityUpdateSet->deltas.value(entityId), interpolationLeadTime, clientInfo->clientState.netCompatibilityRules());
|
||||
}
|
||||
});
|
||||
clientInfo->pendingForward = true;
|
||||
|
||||
} else if (auto entityDestroy = as<EntityDestroyPacket>(packet)) {
|
||||
if (auto entity = m_entityMap->entity(entityDestroy->entityId)) {
|
||||
entity->readNetState(entityDestroy->finalNetState, clientInfo->interpolationTracker.interpolationLeadTime());
|
||||
entity->readNetState(entityDestroy->finalNetState, clientInfo->interpolationTracker.interpolationLeadTime(), clientInfo->clientState.netCompatibilityRules());
|
||||
// Before destroying the entity, we should make sure that the entity is
|
||||
// using the absolute latest data, so we disable interpolation.
|
||||
entity->disableInterpolation();
|
||||
@ -691,6 +692,7 @@ void WorldServer::update(float dt) {
|
||||
queueUpdatePackets(pair.first, sendRemoteUpdates);
|
||||
}
|
||||
m_netStateCache.clear();
|
||||
m_legacyNetStateCache.clear();
|
||||
|
||||
for (auto& pair : m_clientInfo)
|
||||
pair.second->pendingForward = false;
|
||||
@ -1789,10 +1791,10 @@ void WorldServer::queueUpdatePackets(ConnectionId clientId, bool sendRemoteUpdat
|
||||
|
||||
if (shouldRunThisStep("environmentUpdate")) {
|
||||
ByteArray skyDelta;
|
||||
tie(skyDelta, clientInfo->skyNetVersion) = m_sky->writeUpdate(clientInfo->skyNetVersion);
|
||||
tie(skyDelta, clientInfo->skyNetVersion) = m_sky->writeUpdate(clientInfo->skyNetVersion, clientInfo->clientState.netCompatibilityRules());
|
||||
|
||||
ByteArray weatherDelta;
|
||||
tie(weatherDelta, clientInfo->weatherNetVersion) = m_weather.writeUpdate(clientInfo->weatherNetVersion);
|
||||
tie(weatherDelta, clientInfo->weatherNetVersion) = m_weather.writeUpdate(clientInfo->weatherNetVersion, clientInfo->clientState.netCompatibilityRules());
|
||||
|
||||
if (!skyDelta.empty() || !weatherDelta.empty())
|
||||
clientInfo->outgoingPackets.append(make_shared<EnvironmentUpdatePacket>(std::move(skyDelta), std::move(weatherDelta)));
|
||||
@ -1866,12 +1868,14 @@ void WorldServer::queueUpdatePackets(ConnectionId clientId, bool sendRemoteUpdat
|
||||
EntityId entityId = monitoredEntity->entityId();
|
||||
ConnectionId connectionId = connectionForEntity(entityId);
|
||||
if (connectionId != clientId) {
|
||||
auto netRules = clientInfo->clientState.netCompatibilityRules();
|
||||
if (auto version = clientInfo->clientSlavesNetVersion.ptr(entityId)) {
|
||||
if (auto updateSetPacket = updateSetPackets.value(connectionId)) {
|
||||
auto pair = make_pair(entityId, *version);
|
||||
auto i = m_netStateCache.find(pair);
|
||||
if (i == m_netStateCache.end())
|
||||
i = m_netStateCache.insert(pair, monitoredEntity->writeNetState(*version)).first;
|
||||
auto& cache = netRules.isLegacy ? m_legacyNetStateCache : m_netStateCache;
|
||||
auto i = cache.find(pair);
|
||||
if (i == cache.end())
|
||||
i = cache.insert(pair, monitoredEntity->writeNetState(*version, netRules)).first;
|
||||
const auto& netState = i->second;
|
||||
if (!netState.first.empty())
|
||||
updateSetPacket->deltas[entityId] = netState.first;
|
||||
@ -1879,7 +1883,7 @@ void WorldServer::queueUpdatePackets(ConnectionId clientId, bool sendRemoteUpdat
|
||||
}
|
||||
} else if (!monitoredEntity->masterOnly()) {
|
||||
// Client was unaware of this entity until now
|
||||
auto firstUpdate = monitoredEntity->writeNetState();
|
||||
auto firstUpdate = monitoredEntity->writeNetState(0, netRules);
|
||||
clientInfo->clientSlavesNetVersion.add(entityId, firstUpdate.second);
|
||||
clientInfo->outgoingPackets.append(make_shared<EntityCreatePacket>(monitoredEntity->entityType(),
|
||||
entityFactory->netStoreEntity(monitoredEntity), std::move(firstUpdate.first), entityId));
|
||||
@ -2075,7 +2079,8 @@ void WorldServer::removeEntity(EntityId entityId, bool andDie) {
|
||||
for (auto const& pair : m_clientInfo) {
|
||||
auto& clientInfo = pair.second;
|
||||
if (auto version = clientInfo->clientSlavesNetVersion.maybeTake(entity->entityId())) {
|
||||
ByteArray finalDelta = entity->writeNetState(*version).first;
|
||||
auto netRules = clientInfo->clientState.netCompatibilityRules();
|
||||
ByteArray finalDelta = entity->writeNetState(*version, netRules).first;
|
||||
clientInfo->outgoingPackets.append(make_shared<EntityDestroyPacket>(entity->entityId(), std::move(finalDelta), andDie));
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ public:
|
||||
|
||||
// Returns false if the client id already exists, or the spawn target is
|
||||
// invalid.
|
||||
bool addClient(ConnectionId clientId, SpawnTarget const& spawnTarget, bool isLocal, bool isAdmin = false);
|
||||
bool addClient(ConnectionId clientId, SpawnTarget const& spawnTarget, bool isLocal, bool isAdmin = false, NetCompatibilityRules netRules = {});
|
||||
|
||||
// Removes client, sends the WorldStopPacket, and returns any pending packets
|
||||
// for that client
|
||||
@ -375,6 +375,7 @@ private:
|
||||
List<CollisionBlock> m_workingCollisionBlocks;
|
||||
|
||||
HashMap<pair<EntityId, uint64_t>, pair<ByteArray, uint64_t>> m_netStateCache;
|
||||
HashMap<pair<EntityId, uint64_t>, pair<ByteArray, uint64_t>> m_legacyNetStateCache;
|
||||
OrderedHashMap<ConnectionId, shared_ptr<ClientInfo>> m_clientInfo;
|
||||
|
||||
GameTimer m_entityUpdateTimer;
|
||||
|
@ -66,10 +66,10 @@ bool WorldServerThread::spawnTargetValid(SpawnTarget const& spawnTarget) {
|
||||
}
|
||||
}
|
||||
|
||||
bool WorldServerThread::addClient(ConnectionId clientId, SpawnTarget const& spawnTarget, bool isLocal, bool isAdmin) {
|
||||
bool WorldServerThread::addClient(ConnectionId clientId, SpawnTarget const& spawnTarget, bool isLocal, bool isAdmin, NetCompatibilityRules netRules) {
|
||||
try {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
if (m_worldServer->addClient(clientId, spawnTarget, isLocal, isAdmin)) {
|
||||
if (m_worldServer->addClient(clientId, spawnTarget, isLocal, isAdmin, netRules)) {
|
||||
m_clients.add(clientId);
|
||||
return true;
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ public:
|
||||
|
||||
bool spawnTargetValid(SpawnTarget const& spawnTarget);
|
||||
|
||||
bool addClient(ConnectionId clientId, SpawnTarget const& spawnTarget, bool isLocal, bool isAdmin = false);
|
||||
bool addClient(ConnectionId clientId, SpawnTarget const& spawnTarget, bool isLocal, bool isAdmin = false, NetCompatibilityRules netRules = {});
|
||||
// Returns final outgoing packets
|
||||
List<PacketPtr> removeClient(ConnectionId clientId);
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef STAR_ACTIVATABLE_ITEM_HPP
|
||||
#define STAR_ACTIVATABLE_ITEM_HPP
|
||||
#pragma once
|
||||
|
||||
#include "StarConfig.hpp"
|
||||
|
||||
@ -16,6 +15,4 @@ public:
|
||||
virtual void activate() = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#include "StarEntity.hpp"
|
||||
#include "StarDamageManager.hpp"
|
||||
#include "StarNetCompatibility.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
@ -43,11 +44,11 @@ void Entity::uninit() {
|
||||
m_entityId = NullEntityId;
|
||||
}
|
||||
|
||||
pair<ByteArray, uint64_t> Entity::writeNetState(uint64_t) {
|
||||
pair<ByteArray, uint64_t> Entity::writeNetState(uint64_t fromVersion, NetCompatibilityRules rules) {
|
||||
return {ByteArray(), 0};
|
||||
}
|
||||
|
||||
void Entity::readNetState(ByteArray, float) {}
|
||||
void Entity::readNetState(ByteArray data, float interpolationTime, NetCompatibilityRules rules) {}
|
||||
|
||||
void Entity::enableInterpolation(float) {}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "StarCasting.hpp"
|
||||
#include "StarDamage.hpp"
|
||||
#include "StarLightSource.hpp"
|
||||
#include "StarDataStream.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
@ -63,11 +64,11 @@ public:
|
||||
// uninitalized. Should return the delta to be written to the slave, along
|
||||
// with the version to pass into writeDeltaState on the next call. The first
|
||||
// delta written to a slave entity will always be the delta starting with 0.
|
||||
virtual pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0);
|
||||
virtual pair<ByteArray, uint64_t> writeNetState(uint64_t fromVersion = 0, NetCompatibilityRules rules = {});
|
||||
// Will be called with deltas written by writeDeltaState, including if the
|
||||
// delta is empty. interpolationTime will be provided if interpolation is
|
||||
// enabled.
|
||||
virtual void readNetState(ByteArray data, float interpolationTime = 0.0);
|
||||
virtual void readNetState(ByteArray data, float interpolationTime = 0.0f, NetCompatibilityRules rules = {});
|
||||
|
||||
virtual void enableInterpolation(float extrapolationHint);
|
||||
virtual void disableInterpolation();
|
||||
|
@ -237,14 +237,14 @@ LuaCallbacks LuaBindings::makeRootCallbacks() {
|
||||
|
||||
|
||||
callbacks.registerCallback("getConfigurationPath", [root](String const& path) -> Json {
|
||||
if (path.beginsWith("title"))
|
||||
if (path.empty() || path.beginsWith("title"))
|
||||
throw ConfigurationException(strf("cannot get {}", path));
|
||||
else
|
||||
return root->configuration()->getPath(path);
|
||||
});
|
||||
|
||||
callbacks.registerCallback("setConfigurationPath", [root](String const& path, Json const& value) {
|
||||
if (path.beginsWith("safeScripts"))
|
||||
if (path.empty() || path.beginsWith("safeScripts"))
|
||||
throw ConfigurationException(strf("cannot set {}", path));
|
||||
else
|
||||
root->configuration()->setPath(path, value);
|
||||
|
Loading…
x
Reference in New Issue
Block a user