From 640fb032eac08acb1bb3619ebaa2f22aff72b6ef Mon Sep 17 00:00:00 2001 From: Federico Cecchetto Date: Mon, 8 Nov 2021 01:36:48 +0100 Subject: [PATCH] Print errors --- src/component/gsc.cpp | 75 ++++++++------- src/component/gsc.hpp | 4 +- src/game/scripting/array.cpp | 1 + src/game/scripting/array.hpp | 1 + src/game/scripting/execution.hpp | 2 + src/game/scripting/function.cpp | 2 +- src/game/scripting/function.hpp | 4 +- src/game/scripting/script_value.cpp | 11 +++ src/game/scripting/script_value.hpp | 141 ++++++++++++++++++++++++++-- 9 files changed, 191 insertions(+), 50 deletions(-) diff --git a/src/component/gsc.cpp b/src/component/gsc.cpp index e64ff79..4fafc70 100644 --- a/src/component/gsc.cpp +++ b/src/component/gsc.cpp @@ -14,32 +14,6 @@ namespace gsc { - function_args::function_args(std::vector values) - : values_(values) - { - } - - unsigned int function_args::size() const - { - return this->values_.size(); - } - - std::vector function_args::get_raw() const - { - return this->values_; - } - - scripting::script_value function_args::get(const int index) const - { - if (index >= this->values_.size()) - { - throw std::runtime_error(utils::string::va("Insufficient arguments, got %i expected %i", - this->values_.size(), index + 1)); - } - - return this->values_[index]; - } - std::unordered_map functions; std::unordered_map methods; @@ -105,7 +79,7 @@ namespace gsc auto token_map_start = 0x8000; auto field_offset_start = 0xA000; - struct field + struct entity_field { std::string name; std::function getter; @@ -113,7 +87,7 @@ namespace gsc }; std::vector> post_load_callbacks; - std::unordered_map> custom_fields; + std::unordered_map> custom_fields; void call_function(unsigned int id) { @@ -135,8 +109,8 @@ namespace gsc catch (const std::exception& e) { printf("************** Script execution error **************\n"); - printf("Error executing function %s\n", function_name(id).data()); - printf("%s\n", e.what()); + printf("Error executing function %s:\n", function_name(id).data()); + printf(" %s\n", e.what()); printf("****************************************************\n"); } } @@ -161,8 +135,8 @@ namespace gsc catch (const std::exception& e) { printf("************** Script execution error **************\n"); - printf("Error executing method %s\n", method_name(id).data()); - printf("%s\n", e.what()); + printf("Error executing method %s:\n", method_name(id).data()); + printf(" %s\n", e.what()); printf("****************************************************\n"); } } @@ -230,8 +204,8 @@ namespace gsc catch (const std::exception& e) { printf("************** Script execution error **************\n"); - printf("Error getting field %s\n", field.name.data()); - printf("%s\n", e.what()); + printf("Error getting field %s:\n", field.name.data()); + printf(" %s\n", e.what()); printf("****************************************************\n"); } } @@ -254,8 +228,8 @@ namespace gsc catch (const std::exception& e) { printf("************** Script execution error **************\n"); - printf("Error setting field %s\n", field.name.data()); - printf("%s\n", e.what()); + printf("Error setting field %s:\n", field.name.data()); + printf(" %s\n", e.what()); printf("****************************************************\n"); } } @@ -314,6 +288,31 @@ namespace gsc } } + function_args::function_args(std::vector values) + : values_(values) + { + } + + unsigned int function_args::size() const + { + return this->values_.size(); + } + + std::vector function_args::get_raw() const + { + return this->values_; + } + + scripting::value_wrap function_args::get(const int index) const + { + if (index >= this->values_.size()) + { + throw std::runtime_error(utils::string::va("parameter %d does not exist", index)); + } + + return {this->values_[index], index}; + } + class component final : public component_interface { public: @@ -323,7 +322,7 @@ namespace gsc scr_set_object_field_hook.create(0x52BCC0, scr_set_object_field_stub); scr_post_load_scripts_hook.create(0x628B50, scr_post_load_scripts_stub); - gsc::field::add(classid::entity, "flags", + field::add(classid::entity, "flags", [](unsigned int entnum) -> scripting::script_value { const auto entity = &game::g_entities[entnum]; @@ -336,7 +335,7 @@ namespace gsc } ); - gsc::field::add(classid::entity, "clientflags", + field::add(classid::entity, "clientflags", [](unsigned int entnum) -> scripting::script_value { const auto entity = &game::g_entities[entnum]; diff --git a/src/component/gsc.hpp b/src/component/gsc.hpp index fcdafeb..31bdbca 100644 --- a/src/component/gsc.hpp +++ b/src/component/gsc.hpp @@ -18,9 +18,9 @@ namespace gsc unsigned int size() const; std::vector get_raw() const; - scripting::script_value get(const int index) const; + scripting::value_wrap get(const int index) const; - scripting::script_value operator[](const int index) const + scripting::value_wrap operator[](const int index) const { return this->get(index); } diff --git a/src/game/scripting/array.cpp b/src/game/scripting/array.cpp index 8ef8e75..09c22db 100644 --- a/src/game/scripting/array.cpp +++ b/src/game/scripting/array.cpp @@ -1,5 +1,6 @@ #include #include "array.hpp" +#include "script_value.hpp" #include "execution.hpp" namespace scripting diff --git a/src/game/scripting/array.hpp b/src/game/scripting/array.hpp index c31e4cf..adc88d5 100644 --- a/src/game/scripting/array.hpp +++ b/src/game/scripting/array.hpp @@ -1,4 +1,5 @@ #pragma once +#include "game/game.hpp" #include "script_value.hpp" namespace scripting diff --git a/src/game/scripting/execution.hpp b/src/game/scripting/execution.hpp index 71d8e37..c2c6a42 100644 --- a/src/game/scripting/execution.hpp +++ b/src/game/scripting/execution.hpp @@ -1,6 +1,8 @@ #pragma once #include "game/game.hpp" #include "entity.hpp" +#include "array.hpp" +#include "function.hpp" #include "script_value.hpp" namespace scripting diff --git a/src/game/scripting/function.cpp b/src/game/scripting/function.cpp index d63387e..b1f85bc 100644 --- a/src/game/scripting/function.cpp +++ b/src/game/scripting/function.cpp @@ -23,7 +23,7 @@ namespace scripting return this->pos_; } - script_value function::call(entity self, std::vector arguments) const + script_value function::call(const entity& self, std::vector arguments) const { return exec_ent_thread(self, this->pos_, arguments); } diff --git a/src/game/scripting/function.hpp b/src/game/scripting/function.hpp index f42b4eb..8d2639b 100644 --- a/src/game/scripting/function.hpp +++ b/src/game/scripting/function.hpp @@ -12,9 +12,9 @@ namespace scripting script_value get_raw() const; const char* get_pos() const; - script_value call(entity self, std::vector arguments) const; + script_value call(const entity& self, std::vector arguments) const; - script_value operator()(entity self, std::vector arguments) const + script_value operator()(const entity& self, std::vector arguments) const { return this->call(self, arguments); } diff --git a/src/game/scripting/script_value.cpp b/src/game/scripting/script_value.cpp index f821464..1a0558f 100644 --- a/src/game/scripting/script_value.cpp +++ b/src/game/scripting/script_value.cpp @@ -15,6 +15,11 @@ namespace scripting { } + script_value::script_value(const value_wrap& value) + : value_(value.get_raw()) + { + } + script_value::script_value(void* value) { game::VariableValue variable{}; @@ -315,4 +320,10 @@ namespace scripting { return this->value_.get(); } + + value_wrap::value_wrap(const scripting::script_value& value, int argument_index) + : value_(value) + , argument_index_(argument_index) + { + } } diff --git a/src/game/scripting/script_value.hpp b/src/game/scripting/script_value.hpp index 67fd83d..84c3bc7 100644 --- a/src/game/scripting/script_value.hpp +++ b/src/game/scripting/script_value.hpp @@ -8,12 +8,95 @@ namespace scripting class entity; class array; class function; + class value_wrap; + + namespace + { + std::unordered_map typenames = + { + {0, "undefined"}, + {1, "object"}, + {2, "string"}, + {3, "localized string"}, + {4, "vector"}, + {5, "float"}, + {6, "integer"}, + {7, "codepos"}, + {8, "precodepos"}, + {9, "function"}, + {10, "builtin function"}, + {11, "builtin method"}, + {12, "stack"}, + {13, "animation"}, + {14, "pre animation"}, + {15, "thread"}, + {16, "thread"}, + {17, "thread"}, + {18, "thread"}, + {19, "struct"}, + {20, "removed entity"}, + {21, "entity"}, + {22, "array"}, + {23, "removed thread"}, + {24, "count"}, + {25, ""}, + {26, "thread list"}, + {27, "endon list"}, + }; + + std::string get_typename(const game::VariableValue& value) + { + if (value.type == game::SCRIPT_OBJECT) + { + const auto type = game::scr_VarGlob->objectVariableValue[value.u.uintValue].w.type; + return typenames[type]; + } + else + { + return typenames[value.type]; + } + } + + template + std::string get_c_typename() + { + auto& info = typeid(T); + + if (info == typeid(std::string)) + { + return "string"; + } + + if (info == typeid(const char*)) + { + return "string"; + } + + if (info == typeid(entity)) + { + return "entity"; + } + + if (info == typeid(array)) + { + return "array"; + } + + if (info == typeid(vector)) + { + return "vector"; + } + + return info.name(); + } + } class script_value { public: script_value() = default; script_value(const game::VariableValue& value); + script_value(const value_wrap& value); script_value(void* value); @@ -43,7 +126,9 @@ namespace scripting { if (!this->is()) { - throw std::runtime_error("Invalid type"); + const auto type = get_typename(this->get_raw()); + const auto c_type = get_c_typename(); + throw std::runtime_error(std::string("has type '" + type + "' but should be '" + c_type + "'")); } return get(); @@ -52,16 +137,12 @@ namespace scripting template T* as_ptr() { - if (!this->is()) - { - throw std::runtime_error("Invalid type"); - } - const auto value = this->get(); + const auto value = this->as(); if (!value) { - throw std::runtime_error("Null pointer"); + throw std::runtime_error("is null"); } return reinterpret_cast(value); @@ -74,4 +155,50 @@ namespace scripting template T get() const; }; + + class value_wrap + { + public: + value_wrap(const scripting::script_value& value, int argument_index); + + template + T as() const + { + try + { + return this->value_.as(); + } + catch (const std::exception& e) + { + throw std::runtime_error(utils::string::va("parameter %d %s", this->argument_index_, e.what())); + } + } + + template + T* as_ptr() + { + try + { + return this->value_.as_ptr(); + } + catch (const std::exception& e) + { + throw std::runtime_error(utils::string::va("parameter %d %s", this->argument_index_, e.what())); + } + } + + template + T is() const + { + return this->value_.is(); + } + + const game::VariableValue& get_raw() const + { + return this->value_.get_raw(); + } + + int argument_index_{}; + scripting::script_value value_; + }; }