summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md (renamed from CHANGELOG.txt)20
-rw-r--r--README.md (renamed from README.txt)0
-rw-r--r--bowshock/CMakeLists.txt26
-rw-r--r--bowshock/include/bow/application.hxx3
-rw-r--r--bowshock/include/bow/base.hxx21
-rw-r--r--bowshock/include/bow/client.hxx16
-rw-r--r--bowshock/include/bow/logic.hxx62
-rw-r--r--bowshock/include/bow/network.hxx14
-rw-r--r--bowshock/include/bow/server.hxx65
-rw-r--r--bowshock/source/application/Application/constructor.cxx18
-rw-r--r--bowshock/source/application/Application/destructor.cxx3
-rw-r--r--bowshock/source/application/Application/get_quote.cxx8
-rw-r--r--bowshock/source/application/Application/initialise_signal.cxx5
-rw-r--r--bowshock/source/application/Application/parse_parameters.cxx56
-rw-r--r--bowshock/source/application/Application/print_credits.cxx27
-rw-r--r--bowshock/source/application/Application/print_help.cxx21
-rw-r--r--bowshock/source/application/Application/run.cxx4
-rw-r--r--bowshock/source/base/base_directory.cxx (renamed from bowshock/source/base/home_directory.cxx)4
-rw-r--r--bowshock/source/base/terminate.cxx14
-rw-r--r--bowshock/source/client/Client/loop.cxx60
-rw-r--r--bowshock/source/client/Client/run.cxx68
-rw-r--r--bowshock/source/client/Client/start_sequence.cxx4
-rw-r--r--bowshock/source/client/PlayerData/decode_save.cxx11
-rw-r--r--bowshock/source/client/Renderer/constructor.cxx2
-rw-r--r--bowshock/source/client/ShaderProgram/compile_shader.cxx20
-rw-r--r--bowshock/source/logic/Canister/constructor.cxx1
-rw-r--r--bowshock/source/logic/Ship/constructor.cxx1
-rw-r--r--bowshock/source/logic/Star/constructor.cxx1
-rw-r--r--bowshock/source/logic/Station/constructor.cxx1
-rw-r--r--bowshock/source/logic/World/constructor.cxx1
-rw-r--r--bowshock/source/server/ObjectIterator/constructor.cxx7
-rw-r--r--bowshock/source/server/ObjectIterator/operator_equality.cxx13
-rw-r--r--bowshock/source/server/ObjectIterator/operator_increment.cxx9
-rw-r--r--bowshock/source/server/ObjectRoot/add.cxx29
-rw-r--r--bowshock/source/server/ObjectRoot/begin.cxx7
-rw-r--r--bowshock/source/server/ObjectRoot/constructor.cxx7
-rw-r--r--bowshock/source/server/ObjectRoot/destructor.cxx21
-rw-r--r--bowshock/source/server/ObjectRoot/end.cxx11
-rw-r--r--bowshock/source/server/ObjectRoot/operator_increment.cxx9
-rw-r--r--bowshock/source/server/Server/start.cxx4
-rw-r--r--bowshock/source/server/ServerInstance/add_object.cxx25
-rw-r--r--bowshock/source/server/ServerInstance/constructor.cxx4
-rw-r--r--bowshock/source/server/ServerInstance/delete_objects.cxx21
-rw-r--r--bowshock/source/server/ServerInstance/generate_system.cxx14
-rw-r--r--bowshock/source/server/ServerInstance/gravitate.cxx48
-rw-r--r--bowshock/source/server/ServerInstance/loop.cxx18
-rw-r--r--bowshock/source/server/ServerInstance/move.cxx6
-rw-r--r--bowshock/source/server/ServerInstance/run.cxx16
48 files changed, 535 insertions, 291 deletions
diff --git a/CHANGELOG.txt b/CHANGELOG.md
index c91dd27..3d50c6f 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.md
@@ -68,6 +68,26 @@
* Fix shader validation script
* Fix shader
+* Fix CMake not complaining about data directory not being specified
+* Find packages in CMake
+* Update exception specifiers
+* Add terminal parameter for specifying the port number
+* Update help screen
+* Rename terminal paramaeter 'name' to 'save'
+* Add server configuration structure
+* Clean up code
+* Improve commenting
+* Update ware list
+* Add linked-list class for object roots
+* Fix gravitate in the case of overlaping objects
+* Add our own terminate functions for unrecoverable errors
+* Improve error handling
+* Add new header for network formats
+* Fix save path
+* Make readme Markdown
+* Make changelog Markdown
+* Rename home_directory to base_directory
+
# 0.B.2
* Fix data directory not being set correctly by CMake;
diff --git a/README.txt b/README.md
index 6bacdea..6bacdea 100644
--- a/README.txt
+++ b/README.md
diff --git a/bowshock/CMakeLists.txt b/bowshock/CMakeLists.txt
index cd09057..9826336 100644
--- a/bowshock/CMakeLists.txt
+++ b/bowshock/CMakeLists.txt
@@ -2,10 +2,14 @@ cmake_minimum_required(VERSION 3.21)
option(BOW_DATA_DIRECTORY "Directory for storing run-time data (assets, shaders...)." "")
-if("${BOW_DATA_DIRECTORY}" STREQUAL "")
+if(NOT DEFINED BOW_DATA_DIRECTORY)
message(FATAL_ERROR "Data directory (BOW_DATA_DIRECTORY) not specified")
endif()
+find_package(
+ glfw3 REQUIRED
+)
+
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_EXTENSIONS OFF)
@@ -25,6 +29,7 @@ add_executable(
"source/client/Client/constructor.cxx"
"source/client/Client/destructor.cxx"
+ "source/client/Client/loop.cxx"
"source/client/Client/poll_events.cxx"
"source/client/Client/run.cxx"
"source/client/Client/save_path.cxx"
@@ -43,7 +48,8 @@ add_executable(
"source/client/ShaderProgram/constructor.cxx"
"source/client/ShaderProgram/destructor.cxx"
- "source/base/home_directory.cxx"
+ "source/base/base_directory.cxx"
+ "source/base/terminate.cxx"
"source/logic/Canister/constructor.cxx"
"source/logic/Canister/object_type_string.cxx"
@@ -59,11 +65,17 @@ add_executable(
"source/logic/World/constructor.cxx"
"source/logic/World/object_type_string.cxx"
+ "source/server/ObjectIterator/constructor.cxx"
+ "source/server/ObjectIterator/operator_equality.cxx"
+ "source/server/ObjectIterator/operator_increment.cxx"
+ "source/server/ObjectRoot/add.cxx"
+ "source/server/ObjectRoot/begin.cxx"
+ "source/server/ObjectRoot/constructor.cxx"
+ "source/server/ObjectRoot/destructor.cxx"
+ "source/server/ObjectRoot/end.cxx"
"source/server/Server/destructor.cxx"
"source/server/Server/start.cxx"
- "source/server/ServerInstance/add_object.cxx"
"source/server/ServerInstance/constructor.cxx"
- "source/server/ServerInstance/delete_objects.cxx"
"source/server/ServerInstance/generate_system.cxx"
"source/server/ServerInstance/gravitate.cxx"
"source/server/ServerInstance/loop.cxx"
@@ -76,6 +88,7 @@ add_dependencies(
bowshock
glad
+ glfw
)
target_include_directories(
@@ -97,8 +110,8 @@ target_compile_definitions(
bowshock PRIVATE
GLFW_INCLUDE_NONE
- BOW_DATA_DIRECTORY="${BOW_DATA_DIRECTORY}"
- BOW_DEBUG=$<IF:$<STREQUAL:"${CMAKE_BUILD_TYPE}","Debug">,true,false>
+ bow_DATA_DIRECTORY="${BOW_DATA_DIRECTORY}"
+ bow_DEBUG=$<IF:$<STREQUAL:"${CMAKE_BUILD_TYPE}","Debug">,true,false>
)
if(UNIX)
@@ -118,7 +131,6 @@ if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang|GNU")
-Wall
-Wdouble-promotion
-Wextra
- -Wfloat-equal
-Wformat=2
-Winvalid-utf8
-Wmissing-declarations
diff --git a/bowshock/include/bow/application.hxx b/bowshock/include/bow/application.hxx
index ebbeb10..0965730 100644
--- a/bowshock/include/bow/application.hxx
+++ b/bowshock/include/bow/application.hxx
@@ -32,8 +32,9 @@ namespace bow {
private:
::bow::ClientConfiguration client_configuration;
+ ::bow::ServerConfiguration server_configuration;
- ::bow::Client* client;
+ ::bow::Client* client;
::bow::Server* server;
[[noreturn]] static auto print_credits() noexcept -> void;
diff --git a/bowshock/include/bow/base.hxx b/bowshock/include/bow/base.hxx
index a7e3c6b..3691019 100644
--- a/bowshock/include/bow/base.hxx
+++ b/bowshock/include/bow/base.hxx
@@ -2,25 +2,27 @@
#pragma once
-#ifndef BOW_DATA_DIRECTORY
-#error data directory not specified!
+#ifndef bow_DATA_DIRECTORY
+#error data directory not specified
#endif
#include <atomic>
#include <climits>
#include <cstdint>
+#include <exception>
+#include <source_location>
#include <string>
-static_assert(CHAR_BIT == 0x8, "bytes must contain exactly eight bits.");
+static_assert(CHAR_BIT == 0x8, "bytes must contain exactly eight bits");
namespace bow {
- inline ::std::string DATA_DIRECTORY(BOW_DATA_DIRECTORY);
+ inline ::std::string DATA_DIRECTORY(bow_DATA_DIRECTORY);
- constexpr bool DEBUG = BOW_DEBUG;
+ constexpr bool DEBUG = bow_DEBUG;
constexpr ::std::size_t COMMANDER_NAME_LENGTH = 0x10u;
- constexpr ::std::uint8_t NUMBER_OF_QUOTE_IDENTIFIERS = UINT8_C(0x24);
+ constexpr ::std::uint_least8_t NUMBER_OF_QUOTE_IDENTIFIERS = UINT8_C(0x24);
template<typename T> struct Xyz {
T x;
@@ -35,5 +37,10 @@ namespace bow {
// atomic.
extern ::std::atomic_flag GOT_INTERRUPT;
- auto home_directory() noexcept -> ::std::string;
+ [[noreturn]] auto terminate(::std::string const& location, ::std::string const& message) noexcept -> void;
+
+ // Returns the path to the user's home directory.
+ // If we are unable to determine its path, we
+ // instead use the current directory ".".
+ auto base_directory() noexcept -> ::std::string;
}
diff --git a/bowshock/include/bow/client.hxx b/bowshock/include/bow/client.hxx
index 2e2a15d..cc71528 100644
--- a/bowshock/include/bow/client.hxx
+++ b/bowshock/include/bow/client.hxx
@@ -43,10 +43,11 @@ namespace bow {
*/
struct ClientConfiguration {
- ::std::string directory;
- ::std::string save_name;
- bool new_save: 0x1;
- bool skip_start_sequence: 0x1;
+ ::std::string directory;
+ ::std::string save_name;
+ ::std::uint_least16_t network_port;
+ bool new_save: 0x1;
+ bool skip_start_sequence: 0x1;
};
class PlayerData {
@@ -96,8 +97,6 @@ namespace bow {
enum struct ShaderType {
Fragment,
Geometry,
- TesselationControl,
- TesselationEvaluation,
Vertex,
};
@@ -137,7 +136,6 @@ namespace bow {
static auto save_path(::std::string const& directory, ::std::string const& name) noexcept -> ::std::string;
-
auto run() noexcept -> void;
private:
@@ -149,8 +147,8 @@ namespace bow {
auto poll_events() noexcept -> bool;
- auto start_sequence() noexcept -> bool;
+ auto start_sequence() -> bool;
- auto loop() noexcept -> void;
+ auto loop() -> void;
};
}
diff --git a/bowshock/include/bow/logic.hxx b/bowshock/include/bow/logic.hxx
index b5fec0b..ba9c6a1 100644
--- a/bowshock/include/bow/logic.hxx
+++ b/bowshock/include/bow/logic.hxx
@@ -18,71 +18,85 @@ namespace bow {
constexpr double GRAVITY_VALUE = 0x1.258688101B4BB16Dp-34 * ::bow::GRAVITY_FACTOR; // gravitational constant (s^2*m*t^2)
enum struct Ware: ::std::uint8_t {
+ AcidsAndBases,
Air,
- Aluminium,
+ AlcoholicBeverages,
AncientArtefacts,
- AnimalFurs,
- AnimalMeat,
- AnimalSkins,
+ AnimalMeats,
Atomics,
+ Batteries,
BattleWeapons,
Beer,
Biowaste,
- Cheese,
+ Cameras,
+ Cannabis,
ChemicalWaste,
- Cobalt,
- Coffee,
+ Clothing,
+ CoffeeAndTea,
ComputerParts,
Computers,
- Copper,
+ ComputerSoftware,
Cuttlery,
Dairy,
+ Drones,
+ ElectronicComponents,
+ EncryptedData,
+ EnergyGenerators,
Explosives,
+ Films,
FruitsAndVegetables,
Gemstones,
- Gold,
HandWeapons,
HullParts,
- HydrogenFuel,
- Iron,
+ Hypnotics,
Ivory,
+ Jewellry,
Lasers,
- Leather,
- Liquor,
- Lithium,
LiveAnimals,
LuxuryGoods,
+ Machinery,
Magnets,
Medicine,
Minerals,
+ Money,
Monitors,
+ Music,
+ Narcotics,
NerveAgents,
+ NobleGases,
+ NobleMetals,
OrganicDyes,
Paper,
Pearls,
Pesticides,
- Platinum,
- Plutonium,
+ Petroleums,
+ Pharmaceuticals,
+ Pornography,
+ Probes,
+ ProtiumFuel,
Radioactives,
+ Recyclables,
Robots,
Rockets,
Rubbish,
- Silver,
+ ScientificInstruments,
+ SkinsAndFurs,
Slaves,
+ Soils,
+ Spirits,
StorageDevices,
Superconductors,
+ SyntheticDyes,
SyntheticMeat,
- Tea,
- Titanium,
Tobacco,
TritiumFuel,
- Uranium,
+ VirtualIntelligences,
Water,
Wine,
XenoRelics,
};
- enum struct ObjectType : ::std::uint8_t {
+ enum struct ObjectType: ::std::uint8_t {
Canister,
Ship,
Star,
@@ -100,8 +114,6 @@ namespace bow {
::bow::Xyz<double> rotational_velocity; // radians per second
double mass; // kilograms
- ::bow::Object* next;
-
virtual ~Object() noexcept = default;
[[nodiscard]] virtual auto object_type_string() const noexcept -> ::std::string;
@@ -208,9 +220,5 @@ namespace bow {
[[nodiscard]] virtual auto object_type_string() const noexcept -> ::std::string;
};
- struct ObjectRoot {
- ::bow::Object* objects;
- };
-
[[nodiscard]] auto ware_mass(::bow::Ware const ware) noexcept -> double;
}
diff --git a/bowshock/include/bow/network.hxx b/bowshock/include/bow/network.hxx
new file mode 100644
index 0000000..0cad935
--- /dev/null
+++ b/bowshock/include/bow/network.hxx
@@ -0,0 +1,14 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#pragma once
+
+#include <bow/logic.hxx>
+
+namespace bow {
+ // I chose the default port number (37279) as it's
+ // the index number of Proycon in the Hipparcos
+ // Catalogue.
+ constexpr ::std::uint_least16_t DEFAULT_NETWORK_PORT = UINT16_C(0x919F);
+ constexpr ::std::uint_least16_t MINIMUM_NETWORK_PORT = UINT16_C(0x0001);
+ constexpr ::std::uint_least16_t MAXIMUM_NETWORK_PORT = UINT16_C(0xFFFF);
+}
diff --git a/bowshock/include/bow/server.hxx b/bowshock/include/bow/server.hxx
index c1f44f2..71136a4 100644
--- a/bowshock/include/bow/server.hxx
+++ b/bowshock/include/bow/server.hxx
@@ -5,23 +5,70 @@
#include <bow/logic.hxx>
#include <atomic>
+#include <cstddef>
#include <cstdint>
#include <thread>
namespace bow {
- class ServerInstance {
+ struct ServerConfiguration {
+ ::std::uint_least16_t network_port;
+ };
+
+ struct ObjectElement {
+ ::bow::Object* object;
+ ::bow::ObjectElement* next;
+ };
+
+ class ObjectRoot;
+
+ class ObjectIterator {
public:
- explicit ServerInstance(::std::atomic_flag* stop_flag) noexcept;
+ ObjectIterator(::bow::ObjectRoot const& root) noexcept;
- static auto run(::bow::ServerInstance* server) noexcept -> void;
+ ~ObjectIterator() noexcept = default;
+
+ inline auto operator *() noexcept -> ::bow::Object& { return *this->element->object; }
+ inline auto operator *() const noexcept -> ::bow::Object const& { return *this->element->object; }
+
+ auto operator ==(::bow::ObjectIterator const& other) const noexcept -> bool;
+ auto operator ==(::std::nullptr_t) const noexcept -> bool;
+
+ auto operator ++() noexcept -> ::bow::ObjectIterator&;
private:
- ::std::atomic_flag* stop_flag;
+ ::bow::ObjectElement* element;
+ };
+
+ class ObjectRoot {
+ public:
+ ObjectRoot() noexcept;
+
+ ~ObjectRoot() noexcept;
+
+ auto begin() const noexcept -> ::bow::ObjectIterator;
+ auto end() const noexcept -> ::bow::ObjectIterator;
+
+ inline auto has_objects() const noexcept -> bool { return this->elements != nullptr; }
template<::bow::ObjectLike T>
- auto add_object(::bow::ObjectRoot& root, T const& object) -> void;
+ auto add(T const& value) -> T*;
+
+ private:
+ friend ::bow::ObjectIterator;
- auto delete_objects(::bow::ObjectRoot const& root) noexcept -> void;
+ ::bow::ObjectElement* elements;
+ };
+
+ class ServerInstance {
+ public:
+ explicit ServerInstance(::bow::ServerConfiguration const& configuration, ::std::atomic_flag* stop_flag) noexcept;
+
+ static auto run(::bow::ServerInstance* server) noexcept -> void;
+
+ private:
+ ::bow::ServerConfiguration configuration;
+
+ ::std::atomic_flag* stop_flag;
auto generate_system(::bow::ObjectRoot& system, ::std::uint64_t identifier, ::std::uint64_t time) -> void;
@@ -37,11 +84,13 @@ namespace bow {
class Server {
public:
- static auto start() -> ::bow::Server*;
+ static auto start(::bow::ServerConfiguration const& configuration) -> ::bow::Server*;
~Server() noexcept;
private:
+ Server() noexcept = default;
+
::std::thread* thread;
::bow::ServerInstance* instance;
@@ -55,4 +104,4 @@ namespace bow {
}
template<>
-auto bow::ServerInstance::add_object<::bow::Object>(::bow::ObjectRoot& root, ::bow::Object const& object_value) -> void = delete;
+auto bow::ObjectRoot::add<::bow::Object>(::bow::Object const& object_value) -> ::bow::Object* = delete;
diff --git a/bowshock/source/application/Application/constructor.cxx b/bowshock/source/application/Application/constructor.cxx
index a0a900a..7644720 100644
--- a/bowshock/source/application/Application/constructor.cxx
+++ b/bowshock/source/application/Application/constructor.cxx
@@ -2,6 +2,7 @@
#include <bow/application.hxx>
#include <bow/client.hxx>
+#include <bow/network.hxx>
#include <cstdio>
#include <cstdlib>
@@ -16,8 +17,7 @@ bow::Application::Application(int const argc, char const* const* const argv) noe
auto const program_name = [&argc, argv]() -> ::std::string {
if (argc < 0x1) [[unlikely]] {
- ::fmt::print(stderr, "[app] program name not provided\n");
- ::std::abort();
+ ::bow::terminate("app", "program not provided");
} else {
return ::std::string(*argv);
}
@@ -25,20 +25,26 @@ bow::Application::Application(int const argc, char const* const* const argv) noe
this->client_configuration = ::bow::ClientConfiguration {
.directory = ""s,
+ .save_name = "save"s,
+ .network_port = ::bow::DEFAULT_NETWORK_PORT,
.new_save = false,
.skip_start_sequence = false,
};
+ this->server_configuration = ::bow::ServerConfiguration {
+ .network_port = ::bow::DEFAULT_NETWORK_PORT,
+ };
+
+ this->client =nullptr;
+ this->server =nullptr;
+
::std::vector<char const*> parameters(argv + 0x1u, argv + static_cast<::std::size_t>(argc));
this->parse_parameters(program_name, parameters);
if (this->client_configuration.directory.empty()) [[likely]] {
- auto const base_directory = ::bow::home_directory();
+ auto const base_directory = ::bow::base_directory();
this->client_configuration.directory = base_directory + "/.bowshock"s;
}
-
- this->client = nullptr;
- this->server = nullptr;
}
diff --git a/bowshock/source/application/Application/destructor.cxx b/bowshock/source/application/Application/destructor.cxx
index 73a2bf0..51fdec5 100644
--- a/bowshock/source/application/Application/destructor.cxx
+++ b/bowshock/source/application/Application/destructor.cxx
@@ -9,8 +9,7 @@ bow::Application::~Application() noexcept {
::fmt::print(stderr, "[app] quitting\n");
delete this->client;
-
delete this->server;
- ::fmt::print(stderr, "\nGoodbye!\n");
+ ::fmt::print(stderr, "\nGoodbye! \u2764\n");
}
diff --git a/bowshock/source/application/Application/get_quote.cxx b/bowshock/source/application/Application/get_quote.cxx
index f614ccd..ac4494c 100644
--- a/bowshock/source/application/Application/get_quote.cxx
+++ b/bowshock/source/application/Application/get_quote.cxx
@@ -3,8 +3,8 @@
#include <bow/application.hxx>
#include <cstdint>
-#include <cstdio>
-#include <fmt/core.h>
+#include <format>
+#include <stdexcept>
#include <string>
#include <tuple>
@@ -16,9 +16,7 @@ auto bow::Application::get_quote(::std::uint8_t const identifier) -> ::std::tupl
switch (identifier) {
default:
- ::fmt::print(stderr, "[app] invalid quote identifier ({})\n", identifier);
-
- throw ::std::invalid_argument("invalid quote identifier");
+ throw ::std::invalid_argument(::std::format("invalid quote identifier ({})", identifier));
case 0x0u:
quote = "You gotta be heaven to see heaven.";
diff --git a/bowshock/source/application/Application/initialise_signal.cxx b/bowshock/source/application/Application/initialise_signal.cxx
index e77e9ca..c2ebd4a 100644
--- a/bowshock/source/application/Application/initialise_signal.cxx
+++ b/bowshock/source/application/Application/initialise_signal.cxx
@@ -7,6 +7,7 @@
#include <cstdio>
#include <cstdlib>
#include <fmt/core.h>
+#include <format>
#include <stdexcept>
// 31.10.4.
@@ -30,9 +31,7 @@ auto bow::Application::initialise_signal() -> void {
auto const set_handler = []<typename Handler>(int const signal, Handler const& handler) -> void {
if (::std::signal(signal, static_cast<auto (*)(int) -> void>(handler)) == SIG_ERR) [[unlikely]] {
- ::fmt::print(stderr, "[app] unable to set signal handler for {}\n", signal);
-
- throw ::std::runtime_error("unable to set signal handler");
+ throw ::std::runtime_error(::std::format("unable to set signal handler for {}", signal));
}
};
diff --git a/bowshock/source/application/Application/parse_parameters.cxx b/bowshock/source/application/Application/parse_parameters.cxx
index 1993eba..26b353f 100644
--- a/bowshock/source/application/Application/parse_parameters.cxx
+++ b/bowshock/source/application/Application/parse_parameters.cxx
@@ -2,12 +2,16 @@
#include <bow/application.hxx>
#include <bow/client.hxx>
+#include <bow/network.hxx>
+#include <charconv>
#include <cstdio>
#include <fmt/core.h>
+#include <format>
#include <stdexcept>
#include <string>
#include <string_view>
+#include <system_error>
#include <vector>
using namespace ::std::literals::string_literals;
@@ -16,23 +20,46 @@ auto bow::Application::parse_parameters(::std::string const& program_name, ::std
::fmt::print(stderr, "[app] parsing parameters\n");
if (parameters.size() >= 0x1u) [[unlikely]] {
- auto const parse = [&program_name](::bow::ClientConfiguration& client_configuration, ::std::string const& parameter) -> void {
+ auto const parse = [&program_name, this](::std::string const& parameter) -> void {
if (auto const offset = parameter.find("="); offset != ::std::string::npos) {
auto const field = ::std::string_view(parameter.begin(), parameter.begin() + offset);
auto const value = ::std::string_view(parameter.begin() + offset + 0x1u, parameter.end());
if (field == "directory") {
::fmt::print(stderr, "[app] setting directory to \"{}\"\n", value);
+ this->client_configuration.directory = value;
+ } else if (field == "port") {
+ auto const numeric_value = [&field, &value]() -> ::std::uint16_t {
+ ::std::uint_least16_t numeric_value = UINT16_C(0x0);
- client_configuration.directory = value;
- } else if (field == "name") {
- ::fmt::print(stderr, "[app] setting save name to \"{}\"\n", value);
+ auto const result = ::std::from_chars(value.begin(), value.end(), numeric_value);
- client_configuration.save_name = value;
- } else {
- ::fmt::print(stderr, "[app] invalid field name \"{}\"\n", field);
+ bool const out_of_range =
+ result.ec == ::std::errc::result_out_of_range
+ || numeric_value < ::bow::MINIMUM_NETWORK_PORT
+ || numeric_value > ::bow::MAXIMUM_NETWORK_PORT;
+
+ if (out_of_range) [[unlikely]] {
+ ::fmt::print(stderr, "[app] value ({}) for {} is out of range (min. is {}, max. is {})\n", value, field, ::bow::MINIMUM_NETWORK_PORT, ::bow::MAXIMUM_NETWORK_PORT);
+ throw ::std::invalid_argument("value out of range");
+ }
+
+ if (result.ec != ::std::errc()) [[unlikely]] {
+ ::fmt::print(stderr, "[app] invalid value ({}) for {}\n", value, field);
+ throw ::std::invalid_argument("invalid value");
+ }
+
+ return numeric_value;
+ }();
- throw ::std::logic_error("invalid field name");
+ ::fmt::print(stderr, "[app] setting the port number to {}\n", numeric_value);
+ this->client_configuration.network_port = numeric_value;
+ this->server_configuration.network_port = numeric_value;
+ } else if (field == "save") {
+ ::fmt::print(stderr, "[app] setting save name to \"{}\"\n", value);
+ this->client_configuration.save_name = value;
+ } else {
+ throw ::std::invalid_argument(::std::format("invalid field name \"{}\"", field));
}
} else {
auto const setting = ::std::string_view(parameter.begin(), parameter.end());
@@ -43,22 +70,19 @@ auto bow::Application::parse_parameters(::std::string const& program_name, ::std
::bow::Application::print_help(program_name);
} else if (setting == "new") {
::fmt::print(stderr, "[app] using default save file\n");
-
- client_configuration.new_save = true;
+ this->client_configuration.new_save = true;
} else if (setting == "skip") {
::fmt::print(stderr, "[app] skipping start sequence\n");
-
- client_configuration.skip_start_sequence = true;
+ this->client_configuration.skip_start_sequence = true;
} else {
::fmt::print(stderr, "[app] invalid setting\"{}\"\n", setting);
-
- throw ::std::logic_error("invalid setting");
+ throw ::std::invalid_argument("invalid setting");
}
}
};
- for (auto const parameter : parameters) {
- parse(this->client_configuration, parameter);
+ for (auto const parameter: parameters) {
+ parse(parameter);
}
}
}
diff --git a/bowshock/source/application/Application/print_credits.cxx b/bowshock/source/application/Application/print_credits.cxx
index 4a67dfb..1136e05 100644
--- a/bowshock/source/application/Application/print_credits.cxx
+++ b/bowshock/source/application/Application/print_credits.cxx
@@ -7,6 +7,7 @@
#include <filesystem>
#include <fmt/core.h>
#include <stdexcept>
+#include <vector>
auto bow::Application::print_credits() noexcept -> void {
::std::string path = ::bow::DATA_DIRECTORY + "/CREDITS.txt";
@@ -21,24 +22,28 @@ auto bow::Application::print_credits() noexcept -> void {
::std::exit(EXIT_FAILURE);
}
- ::std::string credits;
-
- try {
- credits.reserve(file_size);
- } catch (...) {
- ::fmt::print(stderr, "[app] unable to allocate memory for credits\n");
-
+ auto credits = [file_size]() noexcept -> ::std::vector<char> {
+ try {
+ return ::std::vector<char>(file_size + 0x2u);
+ } catch (...) {
+ ::fmt::print(stderr, "[app] unable to allocate memory for credits\n");
+ ::std::exit(EXIT_FAILURE);
+ }
+ }();
+
+ if (::std::fread(&credits.data()[0x1], sizeof (char), file_size, file) < file_size) [[unlikely]] {
+ ::fmt::print(stderr, "[app] unable to read credits file\n");
::std::exit(EXIT_FAILURE);
}
- ::std::fread(credits.data(), 0x1u, file_size, file);
::std::fclose(file);
- credits.append("\n");
+ credits.front() = '\n';
+ credits.back() = '\n';
- ::std::fputs(credits.c_str(), stdout);
+ ::std::fwrite(credits.data(), sizeof (char), file_size + 0x2u, stdout);
- credits.~basic_string();
+ credits.~vector();
::std::exit(EXIT_SUCCESS);
}
diff --git a/bowshock/source/application/Application/print_help.cxx b/bowshock/source/application/Application/print_help.cxx
index f2e1788..9b4f68f 100644
--- a/bowshock/source/application/Application/print_help.cxx
+++ b/bowshock/source/application/Application/print_help.cxx
@@ -8,16 +8,21 @@
auto bow::Application::print_help(::std::string const& program_name) noexcept -> void {
::fmt::print(
"\n"
- "\x1B[1mBowshock\x1B[0m {:x}.{:x}.{:x}\n"
- "Copyright 2022-2023 Gabriel Bj\u00F8rnager Jensen.\n"
+ "\x1B[1mBowshock\x1B[0m {:X}.{:X}.{:X}\n"
+ "Copyright \u00A9 2022\u20102023 \x1B[1mGabriel Bj\u00F8rnager Jensen\x1B[0m.\n"
"\n"
- "Usage: \"{}\" <configuration> [savefile]\n"
+ "Usage: \"{}\" <parameters> <flags>\n"
"\n"
- "configuration:\n"
- " --credits Print the game \x1B[1mcredits\x1B[0m\n"
- " --print_help Print the\x1B[1mhelp\x1B[0m screen\n"
- " --new Start a \x1B[1mnew\x1B[0m save file\n"
- " --skip_start_sequence \x1B[1mskip\x1B[0m the intro\n"
+ "Parameters:\n"
+ " directory Set the application \x1B[1mdirectory\x1B[0m to be used\n"
+ " port Set the (decimal) \x1B[1mport\x1B[0m number used to connect to the server\n"
+ " save Set the \x1B[1mname\x1B[0m of the save file\n"
+ "\n"
+ "Flags:\n"
+ " credits Print the game \x1B[1mcredits\x1B[0m\n"
+ " help Print the \x1B[1mhelp\x1B[0m screen\n"
+ " new Start a \x1B[1mnew\x1B[0m save file\n"
+ " skip \x1B[1mskip\x1B[0m the intro\n"
"\n",
::bow::VERSION.major, ::bow::VERSION.minor, ::bow::VERSION.patch, program_name
);
diff --git a/bowshock/source/application/Application/run.cxx b/bowshock/source/application/Application/run.cxx
index ebbd7c8..ddbfed8 100644
--- a/bowshock/source/application/Application/run.cxx
+++ b/bowshock/source/application/Application/run.cxx
@@ -14,6 +14,8 @@
#include <string>
#include <tuple>
+#include <format>
+
auto bow::Application::run() -> int {
::std::srand(static_cast<int unsigned>(::std::time(nullptr)));
@@ -44,7 +46,7 @@ auto bow::Application::run() -> int {
this->initialise_signal();
// The server handles all of its exceptions.
- this->server = ::bow::Server::start();
+ this->server = ::bow::Server::start(this->server_configuration);
this->client = new ::bow::Client(this->client_configuration);
diff --git a/bowshock/source/base/home_directory.cxx b/bowshock/source/base/base_directory.cxx
index 2e68917..4d86ce4 100644
--- a/bowshock/source/base/home_directory.cxx
+++ b/bowshock/source/base/base_directory.cxx
@@ -9,11 +9,11 @@
using namespace ::std::literals::string_literals;
-auto bow::home_directory() noexcept -> ::std::string {
+auto bow::base_directory() noexcept -> ::std::string {
auto const pointer = ::std::getenv("HOME");
if (pointer == nullptr) [[unlikely]] {
- ::fmt::print(stderr, "unable to get home directory, using current directory\n");
+ ::fmt::print(stderr, "unable to get home directory - using current directory\n");
return "."s;
}
diff --git a/bowshock/source/base/terminate.cxx b/bowshock/source/base/terminate.cxx
new file mode 100644
index 0000000..94e1ed6
--- /dev/null
+++ b/bowshock/source/base/terminate.cxx
@@ -0,0 +1,14 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/base.hxx>
+
+#include <cstdlib>
+#include <cstdio>
+#include <fmt/core.h>
+#include <string>
+
+auto bow::terminate(::std::string const& location, ::std::string const& message) noexcept -> void {
+ ::fmt::print(stderr, "[{}] terminate due to: {}\n", location, message);
+
+ ::std::abort();
+}
diff --git a/bowshock/source/client/Client/loop.cxx b/bowshock/source/client/Client/loop.cxx
new file mode 100644
index 0000000..04df684
--- /dev/null
+++ b/bowshock/source/client/Client/loop.cxx
@@ -0,0 +1,60 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/client.hxx>
+#include <bow/logic.hxx>
+
+#include <cmath>
+#include <cstdio>
+#include <fmt/core.h>
+#include <glad/glad.h>
+#include <GLFW/glfw3.h>
+
+auto bow::Client::loop() -> void {
+ ::fmt::print(stderr, "[client] entering main loop\n");
+
+ ::GLfloat vertices[] = {
+ -0x1.0000p0f, +0x1.0000p0f, 0x0p0f,
+ +0x1.0000p0f, +0x1.0000p0f, 0x0p0f,
+ +0x0.0000p0f, +0x0.0000p0f, 0x0p0f,
+ };
+
+ glBufferData(GL_ARRAY_BUFFER, sizeof (vertices), vertices, GL_STREAM_DRAW);
+
+ glVertexAttribPointer(0x0, 0x3, GL_FLOAT, GL_FALSE, 0x3* sizeof (::GLfloat), nullptr);
+ glEnableVertexAttribArray(0x0);
+
+ auto const scroll_handler = [](::GLFWwindow* const window, [[maybe_unused]] double const horizontal_offset, double const vertical_offset) -> void {
+ auto const data = static_cast<::bow::PlayerData*>(::glfwGetWindowUserPointer(window));
+
+ data->zoom *= ::std::pow(0x1.04p0f, -static_cast<float>(vertical_offset));
+ };
+
+ ::glfwSetWindowUserPointer(this->renderer.window, &player_data);
+ ::glfwSetScrollCallback(this->renderer.window, scroll_handler);
+
+ for (;;) {
+ if (this->poll_events()) [[unlikely]] { break; }
+
+ ::GLfloat const frame = 0x1p0f * player_data.zoom;
+
+ // Currently, we don't recieve any information from
+ // the server.
+
+ //vertices[0x0] = static_cast<::GLfloat>(system_root.objects->next->position.x) / frame;
+ //vertices[0x1] = static_cast<::GLfloat>(system_root.objects->next->position.y) / frame;
+ //vertices[0x3] = static_cast<::GLfloat>(system_root.objects->position.x) / frame;
+ //vertices[0x4] = static_cast<::GLfloat>(system_root.objects->position.y) / frame;
+ //vertices[0x6] = static_cast<::GLfloat>(objects_root.objects->position.x) / frame;
+ //vertices[0x7] = static_cast<::GLfloat>(objects_root.objects->position.y) / frame;
+
+ this->renderer.render(vertices, sizeof (vertices));
+ }
+
+ ::glfwSetScrollCallback(this->renderer.window, nullptr);
+
+ glDeleteVertexArrays(0x1, &this->renderer.vao);
+ glDeleteBuffers(0x1, &this->renderer.vbo);
+
+ this->player_data.save(::bow::Client::save_path(this->configuration.directory, this->configuration.save_name));
+
+}
diff --git a/bowshock/source/client/Client/run.cxx b/bowshock/source/client/Client/run.cxx
index 4256046..f5327c2 100644
--- a/bowshock/source/client/Client/run.cxx
+++ b/bowshock/source/client/Client/run.cxx
@@ -5,60 +5,38 @@
#include <cmath>
#include <cstdio>
+#include <exception>
#include <fmt/core.h>
+#include <format>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
auto bow::Client::run() noexcept -> void {
::fmt::print(stderr, "[client] running\n");
- if (!this->configuration.skip_start_sequence && start_sequence()) [[unlikely]] { return; }
+ if (!this->configuration.skip_start_sequence) [[likely]] {
+ auto stop = false;
- ::fmt::print(stderr, "[client] entering main loop\n");
+ if constexpr (!::bow::DEBUG) {
+ try {
+ stop = this->start_sequence();
+ } catch (::std::exception const& exception) {
+ ::bow::terminate("client", ::std::format("got uncaught exception: {}", exception.what()));
+ }
+ } else {
+ stop = this->start_sequence();
+ }
- ::GLfloat vertices[] = {
- -0x1.0000p0f, +0x1.0000p0f, 0x0p0f,
- +0x1.0000p0f, +0x1.0000p0f, 0x0p0f,
- +0x0.0000p0f, +0x0.0000p0f, 0x0p0f,
- };
-
- glBufferData(GL_ARRAY_BUFFER, sizeof (vertices), vertices, GL_STREAM_DRAW);
-
- glVertexAttribPointer(0x0, 0x3, GL_FLOAT, GL_FALSE, 0x3* sizeof (::GLfloat), nullptr);
- glEnableVertexAttribArray(0x0);
-
- auto const scroll_handler = [](::GLFWwindow* const window, [[maybe_unused]] double const horizontal_offset, double const vertical_offset) -> void {
- auto const data = static_cast<::bow::PlayerData*>(::glfwGetWindowUserPointer(window));
-
- data->zoom *= ::std::pow(0x1.04p0f, -static_cast<float>(vertical_offset));
- };
-
- ::glfwSetWindowUserPointer(this->renderer.window, &player_data);
- ::glfwSetScrollCallback(this->renderer.window, scroll_handler);
-
- for (;;) {
- if (this->poll_events()) [[unlikely]] { break; }
-
- ::GLfloat const frame = 0x1p0f * player_data.zoom;
-
- // Currently, we don't recieve any information from
- // the server.
-
- //vertices[0x0] = static_cast<::GLfloat>(system_root.objects->next->position.x) / frame;
- //vertices[0x1] = static_cast<::GLfloat>(system_root.objects->next->position.y) / frame;
- //vertices[0x3] = static_cast<::GLfloat>(system_root.objects->position.x) / frame;
- //vertices[0x4] = static_cast<::GLfloat>(system_root.objects->position.y) / frame;
- //vertices[0x6] = static_cast<::GLfloat>(objects_root.objects->position.x) / frame;
- //vertices[0x7] = static_cast<::GLfloat>(objects_root.objects->position.y) / frame;
-
- this->renderer.render(vertices, sizeof (vertices));
+ if (stop) [[unlikely]] { return; }
}
- ::glfwSetScrollCallback(this->renderer.window, nullptr);
-
- glDeleteVertexArrays(0x1, &this->renderer.vao);
- glDeleteBuffers(0x1, &this->renderer.vbo);
-
- this->player_data.save(::bow::Client::save_path(this->configuration.directory, this->configuration.save_name));
-
+ if constexpr (!::bow::DEBUG) {
+ try {
+ this->loop();
+ } catch (::std::exception const& exception) {
+ ::bow::terminate("client", ::std::format("got uncaught exception: {}", exception.what()));
+ }
+ } else {
+ this->loop();
+ }
}
diff --git a/bowshock/source/client/Client/start_sequence.cxx b/bowshock/source/client/Client/start_sequence.cxx
index 48e246c..c1007a5 100644
--- a/bowshock/source/client/Client/start_sequence.cxx
+++ b/bowshock/source/client/Client/start_sequence.cxx
@@ -6,7 +6,7 @@
#include <fmt/core.h>
#include <GLFW/glfw3.h>
-auto bow::Client::start_sequence() noexcept -> bool {
+auto bow::Client::start_sequence() -> bool {
::fmt::print(stderr, "[client] starting start sequence\n");
auto exit = false;
@@ -16,7 +16,7 @@ auto bow::Client::start_sequence() noexcept -> bool {
constexpr ::GLfloat bowshock_blue = 0x1.9999999Ap-3f;
::glfwSetTime(0x0p0);
- for (double duration = 0x0p0;duration <= 0x3p0;duration = ::glfwGetTime()) {
+ for (double duration = 0x0p0; duration <= 0x3p0; duration = ::glfwGetTime()) {
if (poll_events()) [[unlikely]] break;
glClearColor(bowshock_red, bowshock_green, bowshock_blue, 0x1p0);
diff --git a/bowshock/source/client/PlayerData/decode_save.cxx b/bowshock/source/client/PlayerData/decode_save.cxx
index 307f01f..626fce3 100644
--- a/bowshock/source/client/PlayerData/decode_save.cxx
+++ b/bowshock/source/client/PlayerData/decode_save.cxx
@@ -4,9 +4,8 @@
#include <array>
#include <cstdint>
-#include <cstdio>
#include <cstring>
-#include <fmt/core.h>
+#include <format>
#include <stdexcept>
auto bow::PlayerData::decode_save(::bow::PlayerData & buffer, ::std::array<::std::uint8_t, ::bow::SAVE_LENGTH> const& source) -> void {
@@ -58,15 +57,11 @@ auto bow::PlayerData::decode_save(::bow::PlayerData & buffer, ::std::array<::std
decode_value(data.ship_rotational_velocity_z);
if (data.format_version != ::bow::SAVE_FORMAT_VERSION) [[unlikely]] {
- ::fmt::print(stderr, "[client] invalid format ({:#04x}) of save file\n", data.format_version);
-
- throw ::std::logic_error("invalid format of save file");
+ throw ::std::invalid_argument(::std::format("invalid format ({:#04x}) of save file", data.format_version));
}
if (data.ship_type > ::bow::MAXIMUM_SHIP_IDENTIFIER) [[unlikely]] {
- ::fmt::print(stderr, "[client] invalid ship type ({:#04x})\n", data.ship_type);
-
- throw ::std::logic_error("invalid ship type");
+ throw ::std::invalid_argument(::std::format("invalid ship type ({:#04x})\n", data.ship_type));
}
buffer.time = data.time,
diff --git a/bowshock/source/client/Renderer/constructor.cxx b/bowshock/source/client/Renderer/constructor.cxx
index 247a18e..287dd3c 100644
--- a/bowshock/source/client/Renderer/constructor.cxx
+++ b/bowshock/source/client/Renderer/constructor.cxx
@@ -15,7 +15,7 @@ bow::Renderer::Renderer() {
::fmt::print(stderr, "[client] initialising glfw\n");
if (!::glfwInit()) [[unlikely]] {
- throw ::std::runtime_error("[client] unable to initialise glfw");
+ throw ::std::runtime_error("unable to initialise glfw");
}
::fmt::print(stderr, "[client] initialising window\n");
diff --git a/bowshock/source/client/ShaderProgram/compile_shader.cxx b/bowshock/source/client/ShaderProgram/compile_shader.cxx
index 591faf5..f736868 100644
--- a/bowshock/source/client/ShaderProgram/compile_shader.cxx
+++ b/bowshock/source/client/ShaderProgram/compile_shader.cxx
@@ -23,12 +23,6 @@ auto bow::ShaderProgram::compile_shader(::std::string const& name, ::bow::Shader
case ShaderType::Geometry:
return GL_GEOMETRY_SHADER;
- case ShaderType::TesselationControl:
- return GL_TESS_CONTROL_SHADER;
-
- case ShaderType::TesselationEvaluation:
- return GL_TESS_EVALUATION_SHADER;
-
case ShaderType::Vertex:
return GL_VERTEX_SHADER;
}
@@ -46,12 +40,6 @@ auto bow::ShaderProgram::compile_shader(::std::string const& name, ::bow::Shader
case GL_GEOMETRY_SHADER:
return "geom"s;
- case GL_TESS_CONTROL_SHADER:
- return "tesc"s;
-
- case GL_TESS_EVALUATION_SHADER:
- return "tese"s;
-
case GL_VERTEX_SHADER:
return "vert"s;
}
@@ -68,12 +56,6 @@ auto bow::ShaderProgram::compile_shader(::std::string const& name, ::bow::Shader
case GL_GEOMETRY_SHADER:
return "geometry"s;
- case GL_TESS_CONTROL_SHADER:
- return "tesselation control"s;
-
- case GL_TESS_EVALUATION_SHADER:
- return "tesselation evaluation"s;
-
case GL_VERTEX_SHADER:
return "vertex"s;
}
@@ -122,7 +104,7 @@ auto bow::ShaderProgram::compile_shader(::std::string const& name, ::bow::Shader
delete[] log;
- throw ::std::runtime_error {"unable to compile shader"};
+ throw ::std::runtime_error("unable to compile shader");
}
return shader;
diff --git a/bowshock/source/logic/Canister/constructor.cxx b/bowshock/source/logic/Canister/constructor.cxx
index 4607b4c..0067623 100644
--- a/bowshock/source/logic/Canister/constructor.cxx
+++ b/bowshock/source/logic/Canister/constructor.cxx
@@ -18,7 +18,6 @@ bow::Canister::Canister() noexcept {
this->rotational_velocity.y = 0x0p0;
this->rotational_velocity.z = 0x0p0;
this->mass = 0x0p0;
- this->next = nullptr;
this->content = ::bow::Ware::Biowaste;
this->mass = ::bow::ware_mass(this->content) * 0x1p0;
diff --git a/bowshock/source/logic/Ship/constructor.cxx b/bowshock/source/logic/Ship/constructor.cxx
index f3c35f0..50d46a7 100644
--- a/bowshock/source/logic/Ship/constructor.cxx
+++ b/bowshock/source/logic/Ship/constructor.cxx
@@ -18,7 +18,6 @@ bow::Ship::Ship() noexcept {
this->rotational_velocity.y = 0x0p0;
this->rotational_velocity.z = 0x0p0;
this->mass = 0x0p0;
- this->next = nullptr;
this->type = ::bow::Ship::Type::Aquila;
this->mass = this->net_mass();
diff --git a/bowshock/source/logic/Star/constructor.cxx b/bowshock/source/logic/Star/constructor.cxx
index 60449e1..8db89f2 100644
--- a/bowshock/source/logic/Star/constructor.cxx
+++ b/bowshock/source/logic/Star/constructor.cxx
@@ -18,6 +18,5 @@ bow::Star::Star() noexcept {
this->rotational_velocity.y = 0x0p0;
this->rotational_velocity.z = 0x0p0;
this->mass = 0x1p0;
- this->next = nullptr;
this->type = ::bow::Star::Type::G;
}
diff --git a/bowshock/source/logic/Station/constructor.cxx b/bowshock/source/logic/Station/constructor.cxx
index 9e80db4..df6eecf 100644
--- a/bowshock/source/logic/Station/constructor.cxx
+++ b/bowshock/source/logic/Station/constructor.cxx
@@ -18,6 +18,5 @@ bow::Station::Station() noexcept {
this->rotational_velocity.y = 0x0p0;
this->rotational_velocity.z = 0x0p0;
this->mass = 0x0p0;
- this->next = nullptr;
this->type = ::bow::Station::Type::Orbis;
}
diff --git a/bowshock/source/logic/World/constructor.cxx b/bowshock/source/logic/World/constructor.cxx
index 316ca95..57d1cd1 100644
--- a/bowshock/source/logic/World/constructor.cxx
+++ b/bowshock/source/logic/World/constructor.cxx
@@ -18,6 +18,5 @@ bow::World::World() noexcept {
this->rotational_velocity.y = 0x0p0;
this->rotational_velocity.z = 0x0p0;
this->mass = 0x1p0;
- this->next = nullptr;
this->type = ::bow::World::Type::RockyWorld;
}
diff --git a/bowshock/source/server/ObjectIterator/constructor.cxx b/bowshock/source/server/ObjectIterator/constructor.cxx
new file mode 100644
index 0000000..0a9a88c
--- /dev/null
+++ b/bowshock/source/server/ObjectIterator/constructor.cxx
@@ -0,0 +1,7 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/server.hxx>
+
+bow::ObjectIterator::ObjectIterator(::bow::ObjectRoot const& root) noexcept {
+ this->element = root.elements;
+}
diff --git a/bowshock/source/server/ObjectIterator/operator_equality.cxx b/bowshock/source/server/ObjectIterator/operator_equality.cxx
new file mode 100644
index 0000000..ca86aca
--- /dev/null
+++ b/bowshock/source/server/ObjectIterator/operator_equality.cxx
@@ -0,0 +1,13 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/server.hxx>
+
+#include <cstddef>
+
+auto bow::ObjectIterator::operator ==(::bow::ObjectIterator const& other) const noexcept -> bool {
+ return this->element == other.element;
+}
+
+auto bow::ObjectIterator::operator ==(::std::nullptr_t) const noexcept -> bool {
+ return this->element == nullptr;
+}
diff --git a/bowshock/source/server/ObjectIterator/operator_increment.cxx b/bowshock/source/server/ObjectIterator/operator_increment.cxx
new file mode 100644
index 0000000..deab4ff
--- /dev/null
+++ b/bowshock/source/server/ObjectIterator/operator_increment.cxx
@@ -0,0 +1,9 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/server.hxx>
+
+auto bow::ObjectIterator::operator ++() noexcept -> ::bow::ObjectIterator& {
+ this->element = this->element->next;
+
+ return *this;
+}
diff --git a/bowshock/source/server/ObjectRoot/add.cxx b/bowshock/source/server/ObjectRoot/add.cxx
new file mode 100644
index 0000000..15778bf
--- /dev/null
+++ b/bowshock/source/server/ObjectRoot/add.cxx
@@ -0,0 +1,29 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/server.hxx>
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <fmt/core.h>
+
+template<::bow::ObjectLike T>
+auto bow::ObjectRoot::add(T const& object_value) -> T* {
+ ::fmt::print(stderr, "[server] adding object of type {}\n", object_value.object_type_string());
+
+ // Ignore exceptions:
+ auto const element = new ::bow::ObjectElement;
+ element->object = new T;
+ *element->object = object_value;
+
+ element->next = this->elements;
+ this->elements = element;
+
+ return static_cast<T*>(element->object);
+}
+
+template auto ::bow::ObjectRoot::add<::bow::Canister>(::bow::Canister const& object_value) -> ::bow::Canister*;
+template auto ::bow::ObjectRoot::add<::bow::Ship>( ::bow::Ship const& object_value) -> ::bow::Ship*;
+template auto ::bow::ObjectRoot::add<::bow::Star>( ::bow::Star const& object_value) -> ::bow::Star*;
+template auto ::bow::ObjectRoot::add<::bow::Station>( ::bow::Station const& object_value) -> ::bow::Station*;
+template auto ::bow::ObjectRoot::add<::bow::World>( ::bow::World const& object_value) -> ::bow::World*;
diff --git a/bowshock/source/server/ObjectRoot/begin.cxx b/bowshock/source/server/ObjectRoot/begin.cxx
new file mode 100644
index 0000000..3810f5d
--- /dev/null
+++ b/bowshock/source/server/ObjectRoot/begin.cxx
@@ -0,0 +1,7 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/server.hxx>
+
+auto bow::ObjectRoot::begin() const noexcept -> ::bow::ObjectIterator {
+ return ::bow::ObjectIterator(*this);
+}
diff --git a/bowshock/source/server/ObjectRoot/constructor.cxx b/bowshock/source/server/ObjectRoot/constructor.cxx
new file mode 100644
index 0000000..50755c3
--- /dev/null
+++ b/bowshock/source/server/ObjectRoot/constructor.cxx
@@ -0,0 +1,7 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/server.hxx>
+
+bow::ObjectRoot::ObjectRoot() noexcept {
+ this->elements = nullptr;
+}
diff --git a/bowshock/source/server/ObjectRoot/destructor.cxx b/bowshock/source/server/ObjectRoot/destructor.cxx
new file mode 100644
index 0000000..dd1b4d3
--- /dev/null
+++ b/bowshock/source/server/ObjectRoot/destructor.cxx
@@ -0,0 +1,21 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/server.hxx>
+
+#include <cstdio>
+#include <fmt/core.h>
+#include <type_traits>
+
+bow::ObjectRoot::~ObjectRoot() noexcept {
+ ::fmt::print(stderr, "[server] deleting objects\n");
+
+ ::bow::ObjectElement* element;
+ ::bow::ObjectElement* next;
+
+ for (element = this->elements; element != nullptr; element = next) {
+ ::fmt::print(stderr, "[server] deleting object of type {}\n", element->object->object_type_string());
+
+ next = element->next;
+ delete element;
+ }
+}
diff --git a/bowshock/source/server/ObjectRoot/end.cxx b/bowshock/source/server/ObjectRoot/end.cxx
new file mode 100644
index 0000000..b461626
--- /dev/null
+++ b/bowshock/source/server/ObjectRoot/end.cxx
@@ -0,0 +1,11 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/server.hxx>
+
+auto bow::ObjectRoot::end() const noexcept -> ::bow::ObjectIterator {
+ auto iterator = ::bow::ObjectIterator(*this);
+
+ while (++iterator != nullptr) {}
+
+ return iterator;
+}
diff --git a/bowshock/source/server/ObjectRoot/operator_increment.cxx b/bowshock/source/server/ObjectRoot/operator_increment.cxx
new file mode 100644
index 0000000..a9ab381
--- /dev/null
+++ b/bowshock/source/server/ObjectRoot/operator_increment.cxx
@@ -0,0 +1,9 @@
+// Copyright 2022-2023 Gabriel Bjørnager Jensen.
+
+#include <bow/server.hxx>
+
+auto bow::ObjectIterator::operator ++() noexcept -> T& {
+ this->object = this->object->next;
+
+ return *this;
+}
diff --git a/bowshock/source/server/Server/start.cxx b/bowshock/source/server/Server/start.cxx
index d5b7bd5..7647261 100644
--- a/bowshock/source/server/Server/start.cxx
+++ b/bowshock/source/server/Server/start.cxx
@@ -9,12 +9,12 @@
#include <thread>
#include <utility>
-auto bow::Server::start() -> ::bow::Server* {
+auto bow::Server::start(::bow::ServerConfiguration const& configuration) -> ::bow::Server* {
::fmt::print(stderr, "[app] starting server\n");
auto stop_flag = new ::std::atomic_flag();
- auto server = new ::bow::ServerInstance(stop_flag);
+ auto server = new ::bow::ServerInstance(configuration, stop_flag);
auto thread = new ::std::thread(::bow::ServerInstance::run, server);
diff --git a/bowshock/source/server/ServerInstance/add_object.cxx b/bowshock/source/server/ServerInstance/add_object.cxx
deleted file mode 100644
index 3e5126b..0000000
--- a/bowshock/source/server/ServerInstance/add_object.cxx
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2022-2023 Gabriel Bjørnager Jensen.
-
-#include <bow/server.hxx>
-
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <fmt/core.h>
-
-template<::bow::ObjectLike T>
-auto bow::ServerInstance::add_object(::bow::ObjectRoot& root, T const& object_value) -> void {
- ::fmt::print(stderr, "[server] adding object of type {}\n", object_value.object_type_string());
-
- auto const object = new T;
- *object = object_value;
-
- object->next = root.objects;
- root.objects = object;
-}
-
-template auto ::bow::ServerInstance::add_object<::bow::Canister>(::bow::ObjectRoot& root, ::bow::Canister const& object_value) -> void;
-template auto ::bow::ServerInstance::add_object<::bow::Ship>( ::bow::ObjectRoot& root, ::bow::Ship const& object_value) -> void;
-template auto ::bow::ServerInstance::add_object<::bow::Star>( ::bow::ObjectRoot& root, ::bow::Star const& object_value) -> void;
-template auto ::bow::ServerInstance::add_object<::bow::Station>( ::bow::ObjectRoot& root, ::bow::Station const& object_value) -> void;
-template auto ::bow::ServerInstance::add_object<::bow::World>( ::bow::ObjectRoot& root, ::bow::World const& object_value) -> void;
diff --git a/bowshock/source/server/ServerInstance/constructor.cxx b/bowshock/source/server/ServerInstance/constructor.cxx
index 7ac0cec..0ca263f 100644
--- a/bowshock/source/server/ServerInstance/constructor.cxx
+++ b/bowshock/source/server/ServerInstance/constructor.cxx
@@ -4,6 +4,8 @@
#include <atomic>
-::bow::ServerInstance::ServerInstance(::std::atomic_flag* stop_flag) noexcept {
+::bow::ServerInstance::ServerInstance(::bow::ServerConfiguration const& configuration, ::std::atomic_flag* stop_flag) noexcept {
+ this->configuration = configuration;
+
this->stop_flag = stop_flag;
}
diff --git a/bowshock/source/server/ServerInstance/delete_objects.cxx b/bowshock/source/server/ServerInstance/delete_objects.cxx
deleted file mode 100644
index bd8a970..0000000
--- a/bowshock/source/server/ServerInstance/delete_objects.cxx
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2022-2023 Gabriel Bjørnager Jensen.
-
-#include <bow/server.hxx>
-
-#include <cstdio>
-#include <fmt/core.h>
-#include <type_traits>
-
-auto bow::ServerInstance::delete_objects(::bow::ObjectRoot const& root) noexcept -> void {
- ::fmt::print(stderr, "[server] deleting objects\n");
-
- ::bow::Object* object;
- ::bow::Object* next;
-
- for (object = root.objects; object != nullptr; object = next) {
- ::fmt::print(stderr, "[server] deleting object of type {}\n", object->object_type_string());
-
- next = object->next;
- delete object;
- }
-}
diff --git a/bowshock/source/server/ServerInstance/generate_system.cxx b/bowshock/source/server/ServerInstance/generate_system.cxx
index a3188f1..9b97300 100644
--- a/bowshock/source/server/ServerInstance/generate_system.cxx
+++ b/bowshock/source/server/ServerInstance/generate_system.cxx
@@ -10,23 +10,22 @@
auto bow::ServerInstance::generate_system(::bow::ObjectRoot& system, ::std::uint64_t const identifier, ::std::uint64_t const time) -> void {
::fmt::print(stderr, "[server] generating system ({:x})\n", identifier);
- if (system.objects != nullptr) [[likely]] {
- this->delete_objects(system);
+ if (system.has_objects()) [[likely]] {
+ system.~ObjectRoot();
}
// Note: The following code is only temporary;
- auto const star = []() -> ::bow::Star {
+ system.add([]() -> ::bow::Star {
auto star = ::bow::Star();
star.mass = 0x1p0,
star.type = ::bow::Star::Type::G;
return star;
- }();
- this->add_object(system, star);
+ }());
- auto const world = []() -> ::bow::World {
+ system.add([]() -> ::bow::World {
auto world = ::bow::World();
world.position.y = 0x1.F76F144Dp-1;
@@ -36,8 +35,7 @@ auto bow::ServerInstance::generate_system(::bow::ObjectRoot& system, ::std::uint
world.type = ::bow::World::Type::RockyWorld;
return world;
- }();
- this->add_object(system, world);
+ }());
this->simulate(system, time);
}
diff --git a/bowshock/source/server/ServerInstance/gravitate.cxx b/bowshock/source/server/ServerInstance/gravitate.cxx
index 0a390de..6dbad5d 100644
--- a/bowshock/source/server/ServerInstance/gravitate.cxx
+++ b/bowshock/source/server/ServerInstance/gravitate.cxx
@@ -15,11 +15,17 @@ namespace bow {
auto const angle_y = ::std::atan2(distance_y, distance_x);
auto const angle_z = ::std::atan2(distance_z, distance_x);
- auto const acceleration = par.mass/(distance*distance)*::bow::GRAVITY_VALUE;
+ // If two objects overlap - that is, they have a
+ // absolute spacing of zero, then we discard the
+ // accelerations. We use a value as it makes these
+ // function branchless.
+ auto const no_overlap = ::std::abs(distance) != 0x0p0;
- auto const velocity_x = ::std::cos(angle_y)*acceleration;
- auto const velocity_y = ::std::sin(angle_y)*acceleration;
- auto const velocity_z = ::std::sin(angle_z)*acceleration;
+ auto const acceleration = par.mass/(distance * distance) * ::bow::GRAVITY_VALUE * static_cast<double>(no_overlap);
+
+ auto const velocity_x = ::std::cos(angle_y) * acceleration;
+ auto const velocity_y = ::std::sin(angle_y) * acceleration;
+ auto const velocity_z = ::std::sin(angle_z) * acceleration;
object.positional_velocity.x += velocity_x;
object.positional_velocity.y += velocity_y;
@@ -27,24 +33,26 @@ namespace bow {
}
static void gravitate_pair(::bow::Object& obj0, ::bow::Object& obj1) noexcept {
- auto const distance_x = obj1.position.x-obj0.position.x;
- auto const distance_y = obj1.position.y-obj0.position.y;
- auto const distance_z = obj1.position.z-obj0.position.z;
- auto const distance = ::std::sqrt(distance_x*distance_x+distance_y*distance_y+distance_z*distance_z);
+ auto const distance_x = obj1.position.x - obj0.position.x;
+ auto const distance_y = obj1.position.y - obj0.position.y;
+ auto const distance_z = obj1.position.z - obj0.position.z;
+ auto const distance = ::std::sqrt(distance_x * distance_x + distance_y * distance_y + distance_z * distance_z);
auto const angle_y = ::std::atan2(distance_y, distance_x);
auto const angle_z = ::std::atan2(distance_z, distance_x);
- auto acceleration0 = ::bow::GRAVITY_VALUE/(distance*distance);
- auto const acceleration1 = acceleration0*obj0.mass; // This is negative.
- acceleration0 *= obj1.mass;
+ auto const no_overlap = ::std::abs(distance) != 0x0p0;
+
+ auto acceleration0 = ::bow::GRAVITY_VALUE / (distance * distance);
+ auto const acceleration1 = acceleration0 * obj0.mass * static_cast<double>(no_overlap); // This is negative.
+ acceleration0 *= obj1.mass * static_cast<double>(no_overlap);
auto velocity_x0 = ::std::cos(angle_y);
auto velocity_y0 = ::std::sin(angle_y);
auto velocity_z0 = ::std::sin(angle_z);
- auto const velocity_x1 = velocity_x0*acceleration1;
- auto const velocity_y1 = velocity_y0*acceleration1;
- auto const velocity_z1 = velocity_z0*acceleration1;
+ auto const velocity_x1 = velocity_x0 * acceleration1;
+ auto const velocity_y1 = velocity_y0 * acceleration1;
+ auto const velocity_z1 = velocity_z0 * acceleration1;
velocity_x0 *= acceleration0;
velocity_y0 *= acceleration0;
velocity_z0 *= acceleration0;
@@ -60,17 +68,17 @@ namespace bow {
}
auto bow::ServerInstance::gravitate(::bow::ObjectRoot& system) noexcept -> void {
- for (::bow::Object* obj0 = system.objects; obj0 != nullptr; obj0 = obj0->next) {
- for (::bow::Object* obj1 = obj0->next; obj1 != nullptr; obj1 = obj1->next) {
- ::bow::gravitate_pair(*obj0, *obj1);
+ for (auto& object0: system) {
+ for (auto& object1: system) {
+ ::bow::gravitate_pair(object0, object1);
}
}
}
auto bow::ServerInstance::gravitate(::bow::ObjectRoot& objects, ::bow::ObjectRoot const& system) noexcept -> void {
- for (::bow::Object* object = objects.objects; object != nullptr; object = object->next) {
- for (::bow::Object* par = system.objects; par != nullptr; par = par->next) {
- ::bow::gravitate_single(*object, *par);
+ for (auto& object0: objects) {
+ for (auto const& object1: system) {
+ ::bow::gravitate_single(object0, object1);
}
}
}
diff --git a/bowshock/source/server/ServerInstance/loop.cxx b/bowshock/source/server/ServerInstance/loop.cxx
index b7854e0..06fc267 100644
--- a/bowshock/source/server/ServerInstance/loop.cxx
+++ b/bowshock/source/server/ServerInstance/loop.cxx
@@ -12,26 +12,21 @@ auto bow::ServerInstance::loop() -> void {
::fmt::print(stderr, "[server] entering main loop\n");
// For stellar bodies:
- ::bow::ObjectRoot system_root = {
- .objects = nullptr,
- };
+ auto system_root = ::bow::ObjectRoot();
- // For miscellaneous objects (canisters, shps...):
- ::bow::ObjectRoot objects_root = {
- .objects = nullptr,
- };
+ // For miscellaneous objects (canisters, ships, etc.):
+ auto objects_root = ::bow::ObjectRoot();
this->generate_system(system_root, 0x0u, 0x0u);
- auto const canister = []() -> ::bow::Canister {
+ objects_root.add([]() -> ::bow::Canister {
auto canister = ::bow::Canister();
canister.position.y = -0x2p0;
canister.positional_velocity.x = -0x1p-12;
return canister;
- }();
- this->add_object(objects_root, canister);
+ }());
while (!this->stop_flag->test() && !::bow::GOT_INTERRUPT.test()) {
this->gravitate(system_root);
@@ -42,7 +37,4 @@ auto bow::ServerInstance::loop() -> void {
}
::fmt::print(stderr, "[server] submitting\n");
-
- this->delete_objects(objects_root);
- this->delete_objects(system_root);
}
diff --git a/bowshock/source/server/ServerInstance/move.cxx b/bowshock/source/server/ServerInstance/move.cxx
index 03a4210..ee16b0e 100644
--- a/bowshock/source/server/ServerInstance/move.cxx
+++ b/bowshock/source/server/ServerInstance/move.cxx
@@ -4,16 +4,12 @@
#include <bow/logic.hxx>
auto bow::ServerInstance::move(::bow::ObjectRoot& root) noexcept -> void {
- auto const move = [](::bow::Object& object) -> void {
+ for (auto& object: root) {
object.position.x += object.positional_velocity.x;
object.position.y += object.positional_velocity.y;
object.position.z += object.positional_velocity.z;
object.rotation.x += object.rotational_velocity.x;
object.rotation.y += object.rotational_velocity.y;
object.rotation.z += object.rotational_velocity.z;
- };
-
- for (::bow::Object* object = root.objects; object != nullptr; object = object->next) {
- move(*object);
}
}
diff --git a/bowshock/source/server/ServerInstance/run.cxx b/bowshock/source/server/ServerInstance/run.cxx
index 2275190..0460ddb 100644
--- a/bowshock/source/server/ServerInstance/run.cxx
+++ b/bowshock/source/server/ServerInstance/run.cxx
@@ -3,8 +3,9 @@
#include <bow/server.hxx>
#include <cstdio>
+#include <exception>
#include <fmt/core.h>
-#include <stdexcept>
+#include <format>
auto bow::ServerInstance::run(::bow::ServerInstance* server) noexcept -> void {
::fmt::print(stderr, "[server] angle unit: {:.3f} rad\n", 0x1p0);
@@ -13,6 +14,15 @@ auto bow::ServerInstance::run(::bow::ServerInstance* server) noexcept -> void {
::fmt::print(stderr, "[server] time unit: {:.3f} s\n", ::bow::TIME_MODIFIER);
::fmt::print(stderr, "[server] gravitational constant: {:.9f} (factor: {:.3f}))\n", ::bow::GRAVITY_VALUE, ::bow::GRAVITY_FACTOR);
- // We ignore exceptions for debug purposes.
- server->loop();
+ if constexpr (!::bow::DEBUG) {
+ try {
+ server->loop();
+ } catch (::std::exception const& exception) {
+ ::bow::terminate("server", ::std::format("got uncaught exception: {}", exception.what()));
+ } catch (...) {
+ ::bow::terminate("server", "got uncaught exception");
+ }
+ } else {
+ server->loop();
+ }
}