diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..4a24aec4 --- /dev/null +++ b/.clang-format @@ -0,0 +1,46 @@ +BasedOnStyle: LLVM +AccessModifierOffset: -4 +AlignAfterOpenBracket: BlockIndent +AlignArrayOfStructures: Left +AlignConsecutiveDeclarations: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false +AlignConsecutiveAssignments: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: true + PadOperators: true +AlignConsecutiveMacros: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowAllArgumentsOnNextLine: false +AlignOperands: AlignAfterOperator +AlignConsecutiveBitFields: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false +AllowShortLambdasOnASingleLine: All +AllowShortBlocksOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: AllIfsAndElse +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakTemplateDeclarations: 'Yes' +BinPackArguments: false +BinPackParameters: false +BreakBeforeBraces: Custom +BreakBeforeBinaryOperators: NonAssignment +ColumnLimit: 120 +CommentPragmas: '^ IWYU pragma:' +ConstructorInitializerIndentWidth: 0 +IndentWidth: 4 +Language: Cpp +MaxEmptyLinesToKeep: 2 +PackConstructorInitializers: CurrentLine +PointerAlignment: Left +TabWidth: 4 +UseTab: Never +SortIncludes: CaseSensitive diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 00000000..915eee83 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,145 @@ +# Generated from CLion Inspection settings +--- +Checks: '-*, +bugprone-argument-comment, +bugprone-assert-side-effect, +bugprone-bad-signal-to-kill-thread, +bugprone-branch-clone, +bugprone-copy-constructor-init, +bugprone-dangling-handle, +bugprone-dynamic-static-initializers, +bugprone-fold-init-type, +bugprone-forward-declaration-namespace, +bugprone-forwarding-reference-overload, +bugprone-inaccurate-erase, +bugprone-incorrect-roundings, +bugprone-integer-division, +bugprone-lambda-function-name, +bugprone-macro-parentheses, +bugprone-macro-repeated-side-effects, +bugprone-misplaced-operator-in-strlen-in-alloc, +bugprone-misplaced-pointer-arithmetic-in-alloc, +bugprone-misplaced-widening-cast, +bugprone-move-forwarding-reference, +bugprone-multiple-statement-macro, +bugprone-no-escape, +bugprone-not-null-terminated-result, +bugprone-parent-virtual-call, +bugprone-posix-return, +bugprone-reserved-identifier, +bugprone-sizeof-container, +bugprone-sizeof-expression, +bugprone-spuriously-wake-up-functions, +bugprone-string-constructor, +bugprone-string-integer-assignment, +bugprone-string-literal-with-embedded-nul, +bugprone-suspicious-enum-usage, +bugprone-suspicious-include, +bugprone-suspicious-memory-comparison, +bugprone-suspicious-memset-usage, +bugprone-suspicious-missing-comma, +bugprone-suspicious-semicolon, +bugprone-suspicious-string-compare, +bugprone-swapped-arguments, +bugprone-terminating-continue, +bugprone-throw-keyword-missing, +bugprone-too-small-loop-variable, +bugprone-undefined-memory-manipulation, +bugprone-undelegated-constructor, +bugprone-unhandled-self-assignment, +bugprone-unused-raii, +bugprone-unused-return-value, +bugprone-use-after-move, +bugprone-virtual-near-miss, +cert-dcl21-cpp, +cert-dcl58-cpp, +cert-err34-c, +cert-err52-cpp, +cert-err60-cpp, +cert-flp30-c, +cert-msc50-cpp, +cert-msc51-cpp, +cert-str34-c, +cppcoreguidelines-interfaces-global-init, +cppcoreguidelines-narrowing-conversions, +cppcoreguidelines-pro-type-member-init, +cppcoreguidelines-slicing, +google-default-arguments, +google-explicit-constructor, +google-runtime-operator, +hicpp-exception-baseclass, +hicpp-multiway-paths-covered, +misc-misplaced-const, +misc-new-delete-overloads, +misc-non-copyable-objects, +misc-throw-by-value-catch-by-reference, +misc-unconventional-assign-operator, +misc-uniqueptr-reset-release, +modernize-avoid-bind, +modernize-concat-nested-namespaces, +modernize-deprecated-headers, +modernize-deprecated-ios-base-aliases, +modernize-loop-convert, +modernize-make-shared, +modernize-make-unique, +modernize-pass-by-value, +modernize-raw-string-literal, +modernize-redundant-void-arg, +modernize-replace-auto-ptr, +modernize-replace-disallow-copy-and-assign-macro, +modernize-replace-random-shuffle, +modernize-return-braced-init-list, +modernize-shrink-to-fit, +modernize-unary-static-assert, +modernize-use-auto, +modernize-use-bool-literals, +modernize-use-emplace, +modernize-use-equals-default, +modernize-use-equals-delete, +modernize-use-nodiscard, +modernize-use-noexcept, +modernize-use-nullptr, +modernize-use-override, +modernize-use-transparent-functors, +modernize-use-uncaught-exceptions, +mpi-buffer-deref, +mpi-type-mismatch, +openmp-use-default-none, +performance-faster-string-find, +performance-for-range-copy, +performance-implicit-conversion-in-loop, +performance-inefficient-algorithm, +performance-inefficient-string-concatenation, +performance-inefficient-vector-operation, +performance-move-const-arg, +performance-move-constructor-init, +performance-no-automatic-move, +performance-noexcept-move-constructor, +performance-trivially-destructible, +performance-type-promotion-in-math-fn, +performance-unnecessary-copy-initialization, +performance-unnecessary-value-param, +portability-simd-intrinsics, +readability-avoid-const-params-in-decls, +readability-const-return-type, +readability-container-size-empty, +readability-convert-member-functions-to-static, +readability-delete-null-pointer, +readability-deleted-default, +readability-inconsistent-declaration-parameter-name, +readability-make-member-function-const, +readability-misleading-indentation, +readability-misplaced-array-index, +readability-non-const-parameter, +readability-redundant-control-flow, +readability-redundant-declaration, +readability-redundant-function-ptr-dereference, +readability-redundant-smartptr-get, +readability-redundant-string-cstr, +readability-redundant-string-init, +readability-simplify-subscript-expr, +readability-static-accessed-through-instance, +readability-static-definition-in-anonymous-namespace, +readability-string-compare, +readability-uniqueptr-delete-release, +readability-use-anyofallof' diff --git a/.clangd b/.clangd index 0d674195..797c8f30 100644 --- a/.clangd +++ b/.clangd @@ -8,3 +8,8 @@ CompileFlags: Add: - "-ferror-limit=0" - "-D__FUNCTION__=\"dummy\"" + - "-Yumc/_HeaderOutputPredefine.h" + - "-FImc/_HeaderOutputPredefine.h" # clangd bug can't find pch file + Remove: + - "/Yu_HeaderOutputPredefine.h" + - "/FI_HeaderOutputPredefine.h" diff --git a/.gitattributes b/.gitattributes index 5c0a0eac..8327acb8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,90 @@ -## C++ +## https://github.com/gitattributes/gitattributes/blob/master/Common.gitattributes +# Common settings that generally should always be used with your language specific settings + +# Auto detect text files and perform LF normalization +* text=auto + +# +# The above will handle all files NOT found below +# + +# Documents +*.bibtex text diff=bibtex +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain +*.md text diff=markdown +*.mdx text diff=markdown +*.tex text diff=tex +*.adoc text +*.textile text +*.mustache text +*.csv text eol=crlf +*.tab text +*.tsv text +*.txt text +*.sql text +*.epub diff=astextplain + +# Graphics +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.tif binary +*.tiff binary +*.ico binary +# SVG treated as text by default. +*.svg text +# If you want to treat it as binary, +# use the following line instead. +# *.svg binary +*.eps binary + +# Scripts +*.bash text eol=lf +*.fish text eol=lf +*.sh text eol=lf +*.zsh text eol=lf +# These are explicitly windows files and should use crlf +*.bat text eol=crlf +*.cmd text eol=crlf +*.ps1 text eol=crlf + +# Serialisation +*.json text +*.toml text +*.xml text +*.yaml text +*.yml text + +# Archives +*.7z binary +*.gz binary +*.tar binary +*.tgz binary +*.zip binary + +# Text files where line endings should be preserved +*.patch -text + +# +# Exclude files from exporting +# + +.gitattributes export-ignore +.gitignore export-ignore +.gitkeep export-ignore + + +## https://github.com/gitattributes/gitattributes/blob/master/C%2B%2B.gitattributes # Sources *.c text diff=cpp *.cc text diff=cpp @@ -38,4 +124,4 @@ *.app binary -## Others +## Project specific diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 55c7b8be..6a3d4dc2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,9 +9,9 @@ jobs: matrix: backend: - lua - - nodejs - - python310 - - quickjs + # - nodejs + # - python310 + # - quickjs runs-on: windows-latest steps: - uses: actions/checkout@v4 diff --git a/.gitignore b/.gitignore index 9453999e..6fa53991 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -## C++ +# https://github.com/github/gitignore/blob/main/C++.gitignore # Prerequisites *.d @@ -33,7 +33,7 @@ *.app -## CMake +# https://github.com/github/gitignore/blob/main/CMake.gitignore CMakeLists.txt.user CMakeCache.txt CMakeFiles @@ -47,16 +47,514 @@ CTestTestfile.cmake _deps -## Others -.idea -.vscode -docs -lib +# https://github.com/github/gitignore/blob/main/Global/Ninja.gitignore +.ninja_deps +.ninja_log -# Xmake cache -.xmake/ -build/ -.cache/ -# MacOS Cache -.DS_Store \ No newline at end of file +# https://github.com/github/gitignore/blob/main/VisualStudio.gitignore +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml + + +# https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + + +# https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + + +# XMake +/.xmake/ +/build/ +/CMakeLists.txt + + +# Project specific ignores +/.idea/ +/.vscode/ +/bin/ diff --git a/src/ThreadPool.h b/src/ThreadPool.h index c8b393e3..b8fa023b 100644 --- a/src/ThreadPool.h +++ b/src/ThreadPool.h @@ -14,75 +14,71 @@ class ThreadPool { public: - ThreadPool(size_t); + ThreadPool(size_t); - // add new work item to the pool - template - decltype(auto) enqueue(F&& f, Args&&... args) { - auto task = - std::make_shared()>>([f = std::forward(f), args...] { - return f(args...); - }); - auto res = task->get_future(); - { - std::unique_lock lock(queue_mutex); + // add new work item to the pool + template + decltype(auto) enqueue(F&& f, Args&&... args) { + auto task = + std::make_shared()>>([f = std::forward(f), args...] { + return f(args...); + }); + auto res = task->get_future(); + { + std::unique_lock lock(queue_mutex); - // don't allow enqueueing after stopping the pool - if (stop) - throw std::runtime_error("enqueue on stopped ThreadPool"); + // don't allow enqueueing after stopping the pool + if (stop) throw std::runtime_error("enqueue on stopped ThreadPool"); - tasks.emplace([task] { (*task)(); }); - } - condition.notify_one(); + tasks.emplace([task] { (*task)(); }); + } + condition.notify_one(); - return res; - } + return res; + } - ~ThreadPool(); + ~ThreadPool(); private: - // need to keep track of threads so we can join them - std::vector workers; - // the task queue - std::queue> tasks; + // need to keep track of threads so we can join them + std::vector workers; + // the task queue + std::queue> tasks; - // synchronization - std::mutex queue_mutex; - std::condition_variable condition; - bool stop; + // synchronization + std::mutex queue_mutex; + std::condition_variable condition; + bool stop; }; // the constructor just launches some amount of workers inline ThreadPool::ThreadPool(size_t threads) : stop(false) { - for (size_t i = 0; i < threads; ++i) - workers.emplace_back([this] { - for (;;) { - std::function task; + for (size_t i = 0; i < threads; ++i) + workers.emplace_back([this] { + for (;;) { + std::function task; - { - std::unique_lock lock(this->queue_mutex); - this->condition.wait( - lock, [this] { return this->stop || !this->tasks.empty(); }); - if (this->stop && this->tasks.empty()) - return; - task = std::move(this->tasks.front()); - this->tasks.pop(); - } + { + std::unique_lock lock(this->queue_mutex); + this->condition.wait(lock, [this] { return this->stop || !this->tasks.empty(); }); + if (this->stop && this->tasks.empty()) return; + task = std::move(this->tasks.front()); + this->tasks.pop(); + } - task(); - } - }); + task(); + } + }); } // the destructor joins all threads inline ThreadPool::~ThreadPool() { - { - std::unique_lock lock(queue_mutex); - stop = true; - } - condition.notify_all(); - for (std::thread &worker : workers) - worker.join(); + { + std::unique_lock lock(queue_mutex); + stop = true; + } + condition.notify_all(); + for (std::thread& worker : workers) worker.join(); } #endif diff --git a/src/api/APIHelp.cpp b/src/api/APIHelp.cpp index b508d0c8..2d5c21ae 100644 --- a/src/api/APIHelp.cpp +++ b/src/api/APIHelp.cpp @@ -19,522 +19,497 @@ #include "api/NetworkAPI.h" #include "api/PlayerAPI.h" #include "engine/EngineOwnData.h" -#include "main/Global.hpp" +#include "main/Global.h" #include "api/NativeAPI.h" //////////////////// APIs //////////////////// -template void PrintValue(T &out, Local v) { - switch (v.getKind()) { - case ValueKind::kString: - out << v.asString().toString(); - break; - case ValueKind::kNumber: - if (CheckIsFloat(v)) - out << v.asNumber().toDouble(); - else - out << v.asNumber().toInt64(); - break; - case ValueKind::kBoolean: - out << v.asBoolean().value(); - break; - case ValueKind::kNull: - out << ""; - break; - case ValueKind::kArray: { - Local arr = v.asArray(); - if (arr.size() == 0) - out << "[]"; - else { - static std::vector> arrStack = {}; - if (std::find(arrStack.begin(), arrStack.end(), arr) == arrStack.end()) { - arrStack.push_back(arr); - out << '['; - PrintValue(out, arr.get(0)); - for (int i = 1; i < arr.size(); ++i) { - out << ','; - PrintValue(out, arr.get(i)); +template +void PrintValue(T& out, Local v) { + switch (v.getKind()) { + case ValueKind::kString: + out << v.asString().toString(); + break; + case ValueKind::kNumber: + if (CheckIsFloat(v)) out << v.asNumber().toDouble(); + else out << v.asNumber().toInt64(); + break; + case ValueKind::kBoolean: + out << v.asBoolean().value(); + break; + case ValueKind::kNull: + out << ""; + break; + case ValueKind::kArray: { + Local arr = v.asArray(); + if (arr.size() == 0) out << "[]"; + else { + static std::vector> arrStack = {}; + if (std::find(arrStack.begin(), arrStack.end(), arr) == arrStack.end()) { + arrStack.push_back(arr); + out << '['; + PrintValue(out, arr.get(0)); + for (int i = 1; i < arr.size(); ++i) { + out << ','; + PrintValue(out, arr.get(i)); + } + out << ']'; + arrStack.pop_back(); + } else { + out << ""; + } } - out << ']'; - arrStack.pop_back(); - } else { - out << ""; - } - } - break; - } - case ValueKind::kObject: { - // 自定义类型也会被识别为Object,优先处理 - // IntPos - IntPos *intpos = IntPos::extractPos(v); - if (intpos != nullptr) { - out << DimId2Name(intpos->dim) << "(" << intpos->x << "," << intpos->y - << "," << intpos->z << ")"; - break; + break; } + case ValueKind::kObject: { + // 自定义类型也会被识别为Object,优先处理 + // IntPos + IntPos* intpos = IntPos::extractPos(v); + if (intpos != nullptr) { + out << DimId2Name(intpos->dim) << "(" << intpos->x << "," << intpos->y << "," << intpos->z << ")"; + break; + } - // FloatPos - FloatPos *floatpos = FloatPos::extractPos(v); - if (floatpos != nullptr) { - out << std::fixed << std::setprecision(2) << DimId2Name(floatpos->dim) - << "(" << floatpos->x << "," << floatpos->y << "," << floatpos->z - << ")"; - break; - } + // FloatPos + FloatPos* floatpos = FloatPos::extractPos(v); + if (floatpos != nullptr) { + out << std::fixed << std::setprecision(2) << DimId2Name(floatpos->dim) << "(" << floatpos->x << "," + << floatpos->y << "," << floatpos->z << ")"; + break; + } - // 其他自定义类型 - if (IsInstanceOf(v)) { - std::stringstream ss; - ss << std::hex - << (intptr_t)EngineScope::currentEngine() - ->getNativeInstance(v) - ->get(); - out << ss.str(); - break; - } - if (IsInstanceOf(v)) { - std::stringstream ss; - ScriptNativeFunction *func = - EngineScope::currentEngine()->getNativeInstance( - v); - ss << std::hex << "Address: " << (intptr_t)func->mFunction << " " - << "Symbol: " << func->mSymbol << " " - << "ReturnType: " << magic_enum::enum_name(func->mReturnVal) << " " - << "Params: " << func->mParams.size(); - for (size_t i = 0; i < func->mParams.size(); ++i) { - ss << " [" << i << "]" << magic_enum::enum_name(func->mParams[i]); - } + // 其他自定义类型 + if (IsInstanceOf(v)) { + std::stringstream ss; + ss << std::hex << (intptr_t)EngineScope::currentEngine()->getNativeInstance(v)->get(); + out << ss.str(); + break; + } + if (IsInstanceOf(v)) { + std::stringstream ss; + ScriptNativeFunction* func = EngineScope::currentEngine()->getNativeInstance(v); + ss << std::hex << "Address: " << (intptr_t)func->mFunction << " " + << "Symbol: " << func->mSymbol << " " + << "ReturnType: " << magic_enum::enum_name(func->mReturnVal) << " " + << "Params: " << func->mParams.size(); + for (size_t i = 0; i < func->mParams.size(); ++i) { + ss << " [" << i << "]" << magic_enum::enum_name(func->mParams[i]); + } - out << ss.str(); - break; - } - if (IsInstanceOf(v)) { - out << ""; - break; - } - if (IsInstanceOf(v)) { - out << ""; - break; - } - if (IsInstanceOf(v)) { - out << ""; - break; - } - if (IsInstanceOf(v)) { - out << ""; - break; - } - if (IsInstanceOf(v)) { - out << ""; - break; - } - if (IsInstanceOf(v)) { - out << ""; - break; - } - if (IsInstanceOf(v)) { - out << ""; - break; - } - if (IsInstanceOf(v)) { - out << ""; - break; - } - if (IsInstanceOf(v)) { - out << ""; - break; - } - if (IsInstanceOf(v)) { - out << ""; - break; - } - if (IsInstanceOf(v)) { - out << ""; - break; - } - if (IsNbtClass(v)) { - out << ""; - break; - } - if (IsInstanceOf(v)) { - out << ""; - } - if (IsInstanceOf(v)) { - out << ""; + out << ss.str(); + break; + } + if (IsInstanceOf(v)) { + out << ""; + break; + } + if (IsInstanceOf(v)) { + out << ""; + break; + } + if (IsInstanceOf(v)) { + out << ""; + break; + } + if (IsInstanceOf(v)) { + out << ""; + break; + } + if (IsInstanceOf(v)) { + out << ""; + break; + } + if (IsInstanceOf(v)) { + out << ""; + break; + } + if (IsInstanceOf(v)) { + out << ""; + break; + } + if (IsInstanceOf(v)) { + out << ""; + break; + } + if (IsInstanceOf(v)) { + out << ""; + break; + } + if (IsInstanceOf(v)) { + out << ""; + break; + } + if (IsInstanceOf(v)) { + out << ""; + break; + } + if (IsNbtClass(v)) { + out << ""; + break; + } + if (IsInstanceOf(v)) { + out << ""; + } + if (IsInstanceOf(v)) { + out << ""; + } + if (IsInstanceOf(v)) { + out << ""; + } + if (IsInstanceOf(v)) { + out << ""; + } + if (IsInstanceOf(v)) { + out << ""; + } + + Local obj = v.asObject(); + std::vector keys = obj.getKeyNames(); + if (keys.empty()) out << "{}"; + else { + static std::vector> objStack = {}; + if (std::find(objStack.begin(), objStack.end(), obj) == objStack.end()) { + objStack.push_back(obj); + out << '{'; + out << keys[0] + ":"; + PrintValue(out, obj.get(keys[0])); + for (int i = 1; i < keys.size(); ++i) { + out << "," + keys[i] + ":"; + PrintValue(out, obj.get(keys[i])); + } + out << '}'; + objStack.pop_back(); + } else { + out << ""; + } + } + break; } - if (IsInstanceOf(v)) { - out << ""; + case ValueKind::kByteBuffer: { + Local bytes = v.asByteBuffer(); + out << ((const char*)bytes.getRawBytes(), bytes.byteLength()); + break; } - if (IsInstanceOf(v)) { - out << ""; + case ValueKind::kFunction: { + out << ""; + break; } - if (IsInstanceOf(v)) { - out << ""; + default: { + out << ""; + break; } - - Local obj = v.asObject(); - std::vector keys = obj.getKeyNames(); - if (keys.empty()) - out << "{}"; - else { - static std::vector> objStack = {}; - if (std::find(objStack.begin(), objStack.end(), obj) == objStack.end()) { - objStack.push_back(obj); - out << '{'; - out << keys[0] + ":"; - PrintValue(out, obj.get(keys[0])); - for (int i = 1; i < keys.size(); ++i) { - out << "," + keys[i] + ":"; - PrintValue(out, obj.get(keys[i])); - } - out << '}'; - objStack.pop_back(); - } else { - out << ""; - } } - break; - } - case ValueKind::kByteBuffer: { - Local bytes = v.asByteBuffer(); - out << ((const char *)bytes.getRawBytes(), bytes.byteLength()); - break; - } - case ValueKind::kFunction: { - out << ""; - break; - } - default: { - out << ""; - break; - } - } } -template void PrintValue(std::ostream &out, Local v); +template void PrintValue(std::ostream& out, Local v); std::string ValueToString(Local v) { - std::ostringstream sout; - PrintValue(sout, v); - return sout.str(); + std::ostringstream sout; + PrintValue(sout, v); + return sout.str(); } -bool CheckIsFloat(const Local &num) { - try { - return fabs(num.asNumber().toDouble() - num.asNumber().toInt64()) >= 1e-15; - } catch (...) { - return false; - } +bool CheckIsFloat(const Local& num) { + try { + return fabs(num.asNumber().toDouble() - num.asNumber().toInt64()) >= 1e-15; + } catch (...) { + return false; + } } ///////////////////// Json To Value ///////////////////// -Local BigInteger_Helper(ordered_json &i) { - if (i.is_number_integer()) { - if (i.is_number_unsigned()) { - auto ui = i.get(); - if (ui <= LLONG_MAX) - return Number::newNumber((int64_t)ui); - return Number::newNumber((double)ui); +Local BigInteger_Helper(ordered_json& i) { + if (i.is_number_integer()) { + if (i.is_number_unsigned()) { + auto ui = i.get(); + if (ui <= LLONG_MAX) return Number::newNumber((int64_t)ui); + return Number::newNumber((double)ui); + } + return Number::newNumber(i.get()); } - return Number::newNumber(i.get()); - } - return Local(); + return Local(); } -void JsonToValue_Helper(Local &res, ordered_json &j); +void JsonToValue_Helper(Local& res, ordered_json& j); -void JsonToValue_Helper(Local &res, const string &key, - ordered_json &j) { - switch (j.type()) { - case ordered_json::value_t::string: - res.set(key, String::newString(j.get())); - break; - case ordered_json::value_t::number_integer: - case ordered_json::value_t::number_unsigned: - res.set(key, BigInteger_Helper(j)); - break; - case ordered_json::value_t::number_float: - res.set(key, Number::newNumber(j.get())); - break; - case ordered_json::value_t::boolean: - res.set(key, Boolean::newBoolean(j.get())); - break; - case ordered_json::value_t::null: - res.set(key, Local()); - break; - case ordered_json::value_t::array: { - Local arrToAdd = Array::newArray(); - for (ordered_json::iterator it = j.begin(); it != j.end(); ++it) - JsonToValue_Helper(arrToAdd, *it); - res.set(key, arrToAdd); - break; - } - case ordered_json::value_t::object: { - Local objToAdd = Object::newObject(); - for (ordered_json::iterator it = j.begin(); it != j.end(); ++it) - JsonToValue_Helper(objToAdd, it.key(), it.value()); - res.set(key, objToAdd); - break; - } - default: - res.set(key, Local()); - break; - } +void JsonToValue_Helper(Local& res, const string& key, ordered_json& j) { + switch (j.type()) { + case ordered_json::value_t::string: + res.set(key, String::newString(j.get())); + break; + case ordered_json::value_t::number_integer: + case ordered_json::value_t::number_unsigned: + res.set(key, BigInteger_Helper(j)); + break; + case ordered_json::value_t::number_float: + res.set(key, Number::newNumber(j.get())); + break; + case ordered_json::value_t::boolean: + res.set(key, Boolean::newBoolean(j.get())); + break; + case ordered_json::value_t::null: + res.set(key, Local()); + break; + case ordered_json::value_t::array: { + Local arrToAdd = Array::newArray(); + for (ordered_json::iterator it = j.begin(); it != j.end(); ++it) JsonToValue_Helper(arrToAdd, *it); + res.set(key, arrToAdd); + break; + } + case ordered_json::value_t::object: { + Local objToAdd = Object::newObject(); + for (ordered_json::iterator it = j.begin(); it != j.end(); ++it) + JsonToValue_Helper(objToAdd, it.key(), it.value()); + res.set(key, objToAdd); + break; + } + default: + res.set(key, Local()); + break; + } } -void JsonToValue_Helper(Local &res, ordered_json &j) { - switch (j.type()) { - case ordered_json::value_t::string: - res.add(String::newString(j.get())); - break; - case ordered_json::value_t::number_integer: - case ordered_json::value_t::number_unsigned: - res.add(BigInteger_Helper(j)); - break; - case ordered_json::value_t::number_float: - res.add(Number::newNumber(j.get())); - break; - case ordered_json::value_t::boolean: - res.add(Boolean::newBoolean(j.get())); - break; - case ordered_json::value_t::null: - res.add(Local()); - break; - case ordered_json::value_t::array: { - Local arrToAdd = Array::newArray(); - for (ordered_json::iterator it = j.begin(); it != j.end(); ++it) - JsonToValue_Helper(arrToAdd, *it); - res.add(arrToAdd); - break; - } - case ordered_json::value_t::object: { - Local objToAdd = Object::newObject(); - for (ordered_json::iterator it = j.begin(); it != j.end(); ++it) - JsonToValue_Helper(objToAdd, it.key(), it.value()); - res.add(objToAdd); - break; - } - default: - res.add(Local()); - break; - } +void JsonToValue_Helper(Local& res, ordered_json& j) { + switch (j.type()) { + case ordered_json::value_t::string: + res.add(String::newString(j.get())); + break; + case ordered_json::value_t::number_integer: + case ordered_json::value_t::number_unsigned: + res.add(BigInteger_Helper(j)); + break; + case ordered_json::value_t::number_float: + res.add(Number::newNumber(j.get())); + break; + case ordered_json::value_t::boolean: + res.add(Boolean::newBoolean(j.get())); + break; + case ordered_json::value_t::null: + res.add(Local()); + break; + case ordered_json::value_t::array: { + Local arrToAdd = Array::newArray(); + for (ordered_json::iterator it = j.begin(); it != j.end(); ++it) JsonToValue_Helper(arrToAdd, *it); + res.add(arrToAdd); + break; + } + case ordered_json::value_t::object: { + Local objToAdd = Object::newObject(); + for (ordered_json::iterator it = j.begin(); it != j.end(); ++it) + JsonToValue_Helper(objToAdd, it.key(), it.value()); + res.add(objToAdd); + break; + } + default: + res.add(Local()); + break; + } } Local JsonToValue(ordered_json j) { - Local res; + Local res; - switch (j.type()) { - case ordered_json::value_t::string: - res = String::newString(j.get()); - break; - case ordered_json::value_t::number_integer: - case ordered_json::value_t::number_unsigned: - res = BigInteger_Helper(j); - break; - case ordered_json::value_t::number_float: - res = Number::newNumber(j.get()); - break; - case ordered_json::value_t::boolean: - res = Boolean::newBoolean(j.get()); - break; - case ordered_json::value_t::null: - res = Local(); - break; - case ordered_json::value_t::array: { - Local resArr = Array::newArray(); - for (ordered_json::iterator it = j.begin(); it != j.end(); ++it) - JsonToValue_Helper(resArr, *it); - res = resArr; - break; - } - case ordered_json::value_t::object: { - Local resObj = Object::newObject(); - for (ordered_json::iterator it = j.begin(); it != j.end(); ++it) - JsonToValue_Helper(resObj, it.key(), it.value()); - res = resObj; - break; - } - default: - res = Local(); - break; - } + switch (j.type()) { + case ordered_json::value_t::string: + res = String::newString(j.get()); + break; + case ordered_json::value_t::number_integer: + case ordered_json::value_t::number_unsigned: + res = BigInteger_Helper(j); + break; + case ordered_json::value_t::number_float: + res = Number::newNumber(j.get()); + break; + case ordered_json::value_t::boolean: + res = Boolean::newBoolean(j.get()); + break; + case ordered_json::value_t::null: + res = Local(); + break; + case ordered_json::value_t::array: { + Local resArr = Array::newArray(); + for (ordered_json::iterator it = j.begin(); it != j.end(); ++it) JsonToValue_Helper(resArr, *it); + res = resArr; + break; + } + case ordered_json::value_t::object: { + Local resObj = Object::newObject(); + for (ordered_json::iterator it = j.begin(); it != j.end(); ++it) + JsonToValue_Helper(resObj, it.key(), it.value()); + res = resObj; + break; + } + default: + res = Local(); + break; + } - return res; + return res; } Local JsonToValue(std::string jsonStr) { - try { - if (jsonStr.empty()) - return String::newString(""); - if (jsonStr.front() == '\"' && jsonStr.back() == '\"') - return String::newString(jsonStr.substr(1, jsonStr.size() - 2)); - auto j = ordered_json::parse(jsonStr, nullptr, true, true); - return JsonToValue(j); - } catch (const ordered_json::exception &e) { - logger.warn("{}{}", tr("llse.apiHelp.parseJson.fail"), - ll::string_utils::tou8str(e.what())); - return String::newString(jsonStr); - } + try { + if (jsonStr.empty()) return String::newString(""); + if (jsonStr.front() == '\"' && jsonStr.back() == '\"') + return String::newString(jsonStr.substr(1, jsonStr.size() - 2)); + auto j = ordered_json::parse(jsonStr, nullptr, true, true); + return JsonToValue(j); + } catch (const ordered_json::exception& e) { + logger.warn("{}{}", tr("llse.apiHelp.parseJson.fail"), ll::string_utils::tou8str(e.what())); + return String::newString(jsonStr); + } } ///////////////////// Value To Json ///////////////////// -void ValueToJson_Obj_Helper(ordered_json &res, const Local &v); +void ValueToJson_Obj_Helper(ordered_json& res, const Local& v); -void ValueToJson_Arr_Helper(ordered_json &res, const Local &v) { - for (int i = 0; i < v.size(); ++i) { - switch (v.get(i).getKind()) { +void ValueToJson_Arr_Helper(ordered_json& res, const Local& v) { + for (int i = 0; i < v.size(); ++i) { + switch (v.get(i).getKind()) { + case ValueKind::kString: + res.push_back(v.get(i).asString().toString()); + break; + case ValueKind::kNumber: + if (CheckIsFloat(v.get(i))) res.push_back(v.get(i).asNumber().toDouble()); + else res.push_back(v.get(i).asNumber().toInt64()); + break; + case ValueKind::kBoolean: + res.push_back(v.get(i).asBoolean().value()); + break; + case ValueKind::kNull: + res.push_back(nullptr); + break; + case ValueKind::kArray: { + Local arrToAdd = v.get(i).asArray(); + if (arrToAdd.size() == 0) res.push_back(ordered_json::array()); + else { + ordered_json arrJson = ordered_json::array(); + ValueToJson_Arr_Helper(arrJson, arrToAdd); + res.push_back(arrJson); + } + break; + } + case ValueKind::kObject: { + Local objToAdd = v.get(i).asObject(); + if (objToAdd.getKeyNames().empty()) res.push_back(ordered_json::object()); + else { + ordered_json objJson = ordered_json::object(); + ValueToJson_Obj_Helper(objJson, objToAdd); + res.push_back(objJson); + } + break; + } + default: + res.push_back(nullptr); + break; + } + } +} + +void ValueToJson_Obj_Helper(ordered_json& res, const Local& v) { + auto keys = v.getKeyNames(); + for (auto& key : keys) { + switch (v.get(key).getKind()) { + case ValueKind::kString: + res.push_back({key, v.get(key).asString().toString()}); + break; + case ValueKind::kNumber: + if (CheckIsFloat(v.get(key))) res.push_back({key, v.get(key).asNumber().toDouble()}); + else res.push_back({key, v.get(key).asNumber().toInt64()}); + break; + case ValueKind::kBoolean: + res.push_back({key, v.get(key).asBoolean().value()}); + break; + case ValueKind::kNull: + res.push_back({key, nullptr}); + break; + case ValueKind::kArray: { + Local arrToAdd = v.get(key).asArray(); + if (arrToAdd.size() == 0) res.push_back({key, ordered_json::array()}); + else { + ordered_json arrJson = ordered_json::array(); + ValueToJson_Arr_Helper(arrJson, arrToAdd); + res.push_back({key, arrJson}); + } + break; + } + case ValueKind::kObject: { + Local objToAdd = v.get(key).asObject(); + if (objToAdd.getKeyNames().empty()) res.push_back({key, ordered_json::object()}); + else { + ordered_json objJson = ordered_json::object(); + ValueToJson_Obj_Helper(objJson, objToAdd); + res.push_back({key, objJson}); + } + break; + } + default: + res.push_back({key, nullptr}); + break; + } + } +} + +std::string ValueToJson(Local v, int formatIndent) { + string result; + switch (v.getKind()) { case ValueKind::kString: - res.push_back(v.get(i).asString().toString()); - break; + result = "\"" + v.asString().toString() + "\""; + ReplaceStr(result, "\n", "\\n"); + break; case ValueKind::kNumber: - if (CheckIsFloat(v.get(i))) - res.push_back(v.get(i).asNumber().toDouble()); - else - res.push_back(v.get(i).asNumber().toInt64()); - break; + if (CheckIsFloat(v)) { + result = std::to_string(v.asNumber().toDouble()); + } else { + result = std::to_string(v.asNumber().toInt64()); + } + break; case ValueKind::kBoolean: - res.push_back(v.get(i).asBoolean().value()); - break; + result = std::to_string(v.asBoolean().value()); + break; case ValueKind::kNull: - res.push_back(nullptr); - break; + result = ""; + break; case ValueKind::kArray: { - Local arrToAdd = v.get(i).asArray(); - if (arrToAdd.size() == 0) - res.push_back(ordered_json::array()); - else { - ordered_json arrJson = ordered_json::array(); - ValueToJson_Arr_Helper(arrJson, arrToAdd); - res.push_back(arrJson); - } - break; + ordered_json jsonRes = ordered_json::array(); + ValueToJson_Arr_Helper(jsonRes, v.asArray()); + result = jsonRes.dump(formatIndent); + break; } case ValueKind::kObject: { - Local objToAdd = v.get(i).asObject(); - if (objToAdd.getKeyNames().empty()) - res.push_back(ordered_json::object()); - else { - ordered_json objJson = ordered_json::object(); - ValueToJson_Obj_Helper(objJson, objToAdd); - res.push_back(objJson); - } - break; + ordered_json jsonRes = ordered_json::object(); + ValueToJson_Obj_Helper(jsonRes, v.asObject()); + result = jsonRes.dump(formatIndent); + break; } default: - res.push_back(nullptr); - break; + result = ""; + break; } - } + return result; } -void ValueToJson_Obj_Helper(ordered_json &res, const Local &v) { - auto keys = v.getKeyNames(); - for (auto &key : keys) { - switch (v.get(key).getKind()) { +std::string ValueKindToString(const ValueKind& kind) { + switch (kind) { case ValueKind::kString: - res.push_back({key, v.get(key).asString().toString()}); - break; + return "string"; case ValueKind::kNumber: - if (CheckIsFloat(v.get(key))) - res.push_back({key, v.get(key).asNumber().toDouble()}); - else - res.push_back({key, v.get(key).asNumber().toInt64()}); - break; + return "number"; case ValueKind::kBoolean: - res.push_back({key, v.get(key).asBoolean().value()}); - break; + return "boolean"; case ValueKind::kNull: - res.push_back({key, nullptr}); - break; - case ValueKind::kArray: { - Local arrToAdd = v.get(key).asArray(); - if (arrToAdd.size() == 0) - res.push_back({key, ordered_json::array()}); - else { - ordered_json arrJson = ordered_json::array(); - ValueToJson_Arr_Helper(arrJson, arrToAdd); - res.push_back({key, arrJson}); - } - break; - } - case ValueKind::kObject: { - Local objToAdd = v.get(key).asObject(); - if (objToAdd.getKeyNames().empty()) - res.push_back({key, ordered_json::object()}); - else { - ordered_json objJson = ordered_json::object(); - ValueToJson_Obj_Helper(objJson, objToAdd); - res.push_back({key, objJson}); - } - break; - } + return "null"; + case ValueKind::kObject: + return "object"; + case ValueKind::kArray: + return "array"; + case ValueKind::kFunction: + return "function"; + case ValueKind::kByteBuffer: + return "bytebuffer"; default: - res.push_back({key, nullptr}); - break; + return "unknown"; } - } } - -std::string ValueToJson(Local v, int formatIndent) { - string result; - switch (v.getKind()) { - case ValueKind::kString: - result = "\"" + v.asString().toString() + "\""; - ReplaceStr(result, "\n", "\\n"); - break; - case ValueKind::kNumber: - if (CheckIsFloat(v)) { - result = std::to_string(v.asNumber().toDouble()); - } else { - result = std::to_string(v.asNumber().toInt64()); - } - break; - case ValueKind::kBoolean: - result = std::to_string(v.asBoolean().value()); - break; - case ValueKind::kNull: - result = ""; - break; - case ValueKind::kArray: { - ordered_json jsonRes = ordered_json::array(); - ValueToJson_Arr_Helper(jsonRes, v.asArray()); - result = jsonRes.dump(formatIndent); - break; - } - case ValueKind::kObject: { - ordered_json jsonRes = ordered_json::object(); - ValueToJson_Obj_Helper(jsonRes, v.asObject()); - result = jsonRes.dump(formatIndent); - break; - } - default: - result = ""; - break; - } - return result; -} - -std::string ValueKindToString(const ValueKind &kind) { - switch (kind) { - case ValueKind::kString: - return "string"; - case ValueKind::kNumber: - return "number"; - case ValueKind::kBoolean: - return "boolean"; - case ValueKind::kNull: - return "null"; - case ValueKind::kObject: - return "object"; - case ValueKind::kArray: - return "array"; - case ValueKind::kFunction: - return "function"; - case ValueKind::kByteBuffer: - return "bytebuffer"; - default: - return "unknown"; - } -} \ No newline at end of file diff --git a/src/api/APIHelp.h b/src/api/APIHelp.h index 3692c8fc..e264a956 100644 --- a/src/api/APIHelp.h +++ b/src/api/APIHelp.h @@ -8,25 +8,23 @@ #include "mc/world/level/Level.h" #include "engine/EngineOwnData.h" -#include "main/Global.hpp" +#include "main/Global.h" #include "utils/JsonHelper.h" #include "utils/UsingScriptX.inc" #include "ll/api/utils/ErrorUtils.h" // 输出异常信息 -inline void PrintException(const script::Exception &e) { - std::ostringstream sout; - sout << "script::Exception: "; - sout << e; - logger.error(sout.str()); +inline void PrintException(const script::Exception& e) { + std::ostringstream sout; + sout << "script::Exception: "; + sout << e; + logger.error(sout.str()); } -inline void PrintScriptStackTrace(std::string const &msg = "") { - if (!msg.empty()) - PrintException(script::Exception(msg)); - else - logger.error(script::Exception(msg).stacktrace()); +inline void PrintScriptStackTrace(std::string const& msg = "") { + if (!msg.empty()) PrintException(script::Exception(msg)); + else logger.error(script::Exception(msg).stacktrace()); } // 方便提取类型 @@ -34,273 +32,275 @@ inline void PrintScriptStackTrace(std::string const &msg = "") { #define toInt() asNumber().toInt32() // 实例类类型检查 -template bool inline IsInstanceOf(Local v) { - return EngineScope::currentEngine()->isInstanceOf(v); +template +bool inline IsInstanceOf(Local v) { + return EngineScope::currentEngine()->isInstanceOf(v); } -std::string ValueKindToString(const ValueKind &kind); +std::string ValueKindToString(const ValueKind& kind); #if !defined(NEW_DEFINES) // 输出脚本调用堆栈,API名称,以及插件名 -#define LOG_ERROR_WITH_SCRIPT_INFO(...) \ - PrintScriptStackTrace(__VA_ARGS__); \ - logger.error("In API: " __FUNCTION__); \ - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName) +#define LOG_ERROR_WITH_SCRIPT_INFO(...) \ + PrintScriptStackTrace(__VA_ARGS__); \ + logger.error("In API: " __FUNCTION__); \ + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName) // 参数类型错误输出 -#define LOG_WRONG_ARG_TYPE() \ - LOG_ERROR_WITH_SCRIPT_INFO("Wrong type of argument!"); +#define LOG_WRONG_ARG_TYPE() LOG_ERROR_WITH_SCRIPT_INFO("Wrong type of argument!"); // 参数数量错误输出 #define LOG_TOO_FEW_ARGS() LOG_ERROR_WITH_SCRIPT_INFO("Too Few arguments!"); // 参数数量错误输出 -#define LOG_WRONG_ARGS_COUNT() \ - LOG_ERROR_WITH_SCRIPT_INFO("Wrong number of arguments!"); +#define LOG_WRONG_ARGS_COUNT() LOG_ERROR_WITH_SCRIPT_INFO("Wrong number of arguments!"); // 至少COUNT个参数 -#define CHECK_ARGS_COUNT(ARGS, COUNT) \ - if (ARGS.size() < COUNT) { \ - LOG_TOO_FEW_ARGS(); \ - return Local(); \ - } +#define CHECK_ARGS_COUNT(ARGS, COUNT) \ + if (ARGS.size() < COUNT) { \ + LOG_TOO_FEW_ARGS(); \ + return Local(); \ + } // 检查是否TYPE类型 -#define CHECK_ARG_TYPE(ARG, TYPE) \ - if (ARG.getKind() != TYPE) { \ - LOG_WRONG_ARG_TYPE(); \ - return Local(); \ - } +#define CHECK_ARG_TYPE(ARG, TYPE) \ + if (ARG.getKind() != TYPE) { \ + LOG_WRONG_ARG_TYPE(); \ + return Local(); \ + } // 截获引擎异常 -#define CATCH(LOG) \ - catch (...) { \ - ll::error_utils::printCurrentException(logger); \ - LOG_ERROR_WITH_SCRIPT_INFO(); \ - return Local(); \ - } +#define CATCH(LOG) \ + catch (...) { \ + ll::error_utils::printCurrentException(logger); \ + LOG_ERROR_WITH_SCRIPT_INFO(); \ + return Local(); \ + } // 至少COUNT个参数_Constructor -#define CHECK_ARGS_COUNT_C(ARGS, COUNT) \ - if (ARGS.size() < COUNT) { \ - LOG_TOO_FEW_ARGS(); \ - return nullptr; \ - } +#define CHECK_ARGS_COUNT_C(ARGS, COUNT) \ + if (ARGS.size() < COUNT) { \ + LOG_TOO_FEW_ARGS(); \ + return nullptr; \ + } // 检查是否TYPE类型_Constructor -#define CHECK_ARG_TYPE_C(ARG, TYPE) \ - if (ARG.getKind() != TYPE) { \ - LOG_WRONG_ARG_TYPE(); \ - return nullptr; \ - } +#define CHECK_ARG_TYPE_C(ARG, TYPE) \ + if (ARG.getKind() != TYPE) { \ + LOG_WRONG_ARG_TYPE(); \ + return nullptr; \ + } // 检查是否TYPE类型_Setter -#define CHECK_ARG_TYPE_S(ARG, TYPE) \ - if (ARG.getKind() != TYPE) { \ - LOG_WRONG_ARG_TYPE(); \ - return; \ - } +#define CHECK_ARG_TYPE_S(ARG, TYPE) \ + if (ARG.getKind() != TYPE) { \ + LOG_WRONG_ARG_TYPE(); \ + return; \ + } // 截获引擎异常_Constructor -#define CATCH_C(LOG) \ - catch (...) { \ - ll::error_utils::printCurrentException(logger); \ - LOG_ERROR_WITH_SCRIPT_INFO(); \ - return nullptr; \ - } +#define CATCH_C(LOG) \ + catch (...) { \ + ll::error_utils::printCurrentException(logger); \ + LOG_ERROR_WITH_SCRIPT_INFO(); \ + return nullptr; \ + } // 截获引擎异常_Setter -#define CATCH_S(LOG) \ - catch (...) { \ - ll::error_utils::printCurrentException(logger); \ - LOG_ERROR_WITH_SCRIPT_INFO(); \ - return; \ - } +#define CATCH_S(LOG) \ + catch (...) { \ + ll::error_utils::printCurrentException(logger); \ + LOG_ERROR_WITH_SCRIPT_INFO(); \ + return; \ + } // 截获引擎异常_Constructor -#define CATCH_WITHOUT_RETURN(LOG) \ - catch (...) { \ - ll::error_utils::printCurrentException(logger); \ - LOG_ERROR_WITH_SCRIPT_INFO(); \ - } +#define CATCH_WITHOUT_RETURN(LOG) \ + catch (...) { \ + ll::error_utils::printCurrentException(logger); \ + LOG_ERROR_WITH_SCRIPT_INFO(); \ + } // 截获回调函数异常 -#define CATCH_IN_CALLBACK(callback) \ - catch (const Exception &e) { \ - PrintException(e); \ - logger.error(std::string("In callback for ") + callback); \ - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); \ - } +#define CATCH_IN_CALLBACK(callback) \ + catch (const Exception& e) { \ + PrintException(e); \ + logger.error(std::string("In callback for ") + callback); \ + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); \ + } #else // 新的宏定义, 把异常抛入脚本层处理 -#define CATCH_AND_THROW \ - catch (const Exception &e) { \ - throw e; \ - } \ - catch (const std::exception &e) { \ - throw Exception(e.what()); \ - } \ - catch (...) { \ - throw Exception("Unknown exception in " __FUNCTION__); \ - } - -#define CHECK_ARGS_COUNT(count) \ - if (args.size() != count) { \ - throw Exception( \ - fmt::format("Invalid arguments count: {}, expect {}, in API {}", \ - args.size(), count, __FUNCTION__)); \ - } - -#define CHECK_ARGS_LEAST_COUNT(count) \ - if (args.size() < count) { \ - throw Exception(fmt::format( \ - "Invalid arguments count: {}, expect at least {}, in API {}", \ - args.size(), count, __FUNCTION__)); \ - } - -#define CHECK_ARG_TYPE(index, type) \ - if (args[index].getKind() != ValueKind::type) { \ - throw Exception( \ - fmt::format("Wrong type of arguments[{}]: {}, expect {}, in API {}", \ - index, ValueKindToString(args[index].getKind()), \ - ValueKindToString(ValueKind::type), __FUNCTION__)); \ - } - -#define CHECK_VAL_TYPE(val, type) \ - if (val.getKind() != ValueKind::type) { \ - throw Exception( \ - fmt::format("Wrong type of value: {}, expect {}, in API {}", \ - ValueKindToString(val.getKind()), \ - ValueKindToString(ValueKind::type), __FUNCTION__)); \ - } +#define CATCH_AND_THROW \ + catch (const Exception& e) { \ + throw e; \ + } \ + catch (const std::exception& e) { \ + throw Exception(e.what()); \ + } \ + catch (...) { \ + throw Exception("Unknown exception in " __FUNCTION__); \ + } + +#define CHECK_ARGS_COUNT(count) \ + if (args.size() != count) { \ + throw Exception( \ + fmt::format("Invalid arguments count: {}, expect {}, in API {}", args.size(), count, __FUNCTION__) \ + ); \ + } + +#define CHECK_ARGS_LEAST_COUNT(count) \ + if (args.size() < count) { \ + throw Exception(fmt::format( \ + "Invalid arguments count: {}, expect at least {}, in API {}", \ + args.size(), \ + count, \ + __FUNCTION__ \ + )); \ + } + +#define CHECK_ARG_TYPE(index, type) \ + if (args[index].getKind() != ValueKind::type) { \ + throw Exception(fmt::format( \ + "Wrong type of arguments[{}]: {}, expect {}, in API {}", \ + index, \ + ValueKindToString(args[index].getKind()), \ + ValueKindToString(ValueKind::type), \ + __FUNCTION__ \ + )); \ + } + +#define CHECK_VAL_TYPE(val, type) \ + if (val.getKind() != ValueKind::type) { \ + throw Exception(fmt::format( \ + "Wrong type of value: {}, expect {}, in API {}", \ + ValueKindToString(val.getKind()), \ + ValueKindToString(ValueKind::type), \ + __FUNCTION__ \ + )); \ + } #endif // 判断是否为浮点数 -bool CheckIsFloat(const Local &num); +bool CheckIsFloat(const Local& num); // 序列化 -template void PrintValue(T &out, Local v); +template +void PrintValue(T& out, Local v); std::string ValueToString(Local v); // Json 序列化 反序列化 Local JsonToValue(std::string jsonStr); Local JsonToValue(ordered_json j); -std::string ValueToJson(Local v, int formatIndent = -1); +std::string ValueToJson(Local v, int formatIndent = -1); // Get the enum's ClassDefine object // Limitation: enum values must be in range of [-128, 128) -template struct EnumDefineBuilder { - template inline static Local serialize() { - return Number::newNumber(static_cast(val)); - } - - inline static Local keys() { - try { - auto arr = Array::newArray(); - for (auto &name : magic_enum::enum_names()) { - arr.add(String::newString(name)); - } - return arr; - } catch (const std::exception &) { - logger.error("Error in " __FUNCTION__); +template +struct EnumDefineBuilder { + template + inline static Local serialize() { + return Number::newNumber(static_cast(val)); } - return Local(); - } - - inline static Local toObject() { - try { - auto obj = Object::newObject(); - for (auto &[value, name] : magic_enum::enum_entries()) { - obj.set(String::newString(name), Number::newNumber((int)value)); - } - return obj; - } catch (const std::exception &) { - logger.error("Error in " __FUNCTION__); - } - return Local(); - } - inline static Local getName(const Arguments &args) { - try { - if (args.size() < 1) + inline static Local keys() { + try { + auto arr = Array::newArray(); + for (auto& name : magic_enum::enum_names()) { + arr.add(String::newString(name)); + } + return arr; + } catch (const std::exception&) { + logger.error("Error in " __FUNCTION__); + } return Local(); - if (args[0].isString()) - return magic_enum::enum_cast(args[0].toStr()).has_value() - ? args[0] - : Local(); - if (args[0].isNumber()) - return String::newString( - magic_enum::enum_name(static_cast(args[0].toInt()))); - return Local(); - } catch (const std::exception &) { - logger.error("Error in " __FUNCTION__); } - return Local(); - } - - inline static Local toString() { - try { - return String::newString(typeid(Type).name() + 5); - } catch (const std::exception &) { - logger.error("Error in " __FUNCTION__); + + inline static Local toObject() { + try { + auto obj = Object::newObject(); + for (auto& [value, name] : magic_enum::enum_entries()) { + obj.set(String::newString(name), Number::newNumber((int)value)); + } + return obj; + } catch (const std::exception&) { + logger.error("Error in " __FUNCTION__); + } + return Local(); } - return Local(); - } - - template , char> max = - static_cast(*magic_enum::enum_values().rbegin())> - inline static void buildBuilder(script::ClassDefineBuilder &builder) { - if constexpr (static_cast(val) > max) - return; - if constexpr (!magic_enum::enum_name(val).empty()) { - fmt::print("{} = {},\n", magic_enum::enum_name(val), - static_cast(val)); - builder.property(magic_enum::enum_name(val).data(), &serialize); + + inline static Local getName(const Arguments& args) { + try { + if (args.size() < 1) return Local(); + if (args[0].isString()) + return magic_enum::enum_cast(args[0].toStr()).has_value() ? args[0] : Local(); + if (args[0].isNumber()) return String::newString(magic_enum::enum_name(static_cast(args[0].toInt()))); + return Local(); + } catch (const std::exception&) { + logger.error("Error in " __FUNCTION__); + } + return Local(); } - buildBuilder((static_cast(val) + 1)), max>(builder); - } - - template , char> max = - static_cast(*magic_enum::enum_values().rbegin())> - inline static ClassDefine build(std::string const &enumName) { - script::ClassDefineBuilder builder = defineClass(enumName); - // fmt::print("枚举 {} 可能取值:\n", enumName); - // buildBuilder<*magic_enum::enum_values().begin(), max>(builder); - - for (auto &[val, name] : magic_enum::enum_entries()) { - // fmt::print("{} = {},\n", name, static_cast(val)); - auto _val = val; - auto _name = name; - builder.property(std::string(name), [=]() -> Local { + + inline static Local toString() { try { - return Number::newNumber(static_cast(_val)); - } catch (const std::exception &) { - logger.error("Error in get {}.{}", enumName, _name); + return String::newString(typeid(Type).name() + 5); + } catch (const std::exception&) { + logger.error("Error in " __FUNCTION__); } return Local(); - }); } - builder.property("keys", &keys); - // builder.property("object", &toObject); - builder.function("getName", &getName); - // fmt::print("\n"); - return builder.build(); - } + template < + Type val, + std::enable_if_t, char> max = static_cast(*magic_enum::enum_values().rbegin())> + inline static void buildBuilder(script::ClassDefineBuilder& builder) { + if constexpr (static_cast(val) > max) return; + if constexpr (!magic_enum::enum_name(val).empty()) { + fmt::print("{} = {},\n", magic_enum::enum_name(val), static_cast(val)); + builder.property(magic_enum::enum_name(val).data(), &serialize); + } + buildBuilder((static_cast(val) + 1)), max>(builder); + } + + template < + std::enable_if_t, char> max = static_cast(*magic_enum::enum_values().rbegin())> + inline static ClassDefine build(std::string const& enumName) { + script::ClassDefineBuilder builder = defineClass(enumName); + // fmt::print("枚举 {} 可能取值:\n", enumName); + // buildBuilder<*magic_enum::enum_values().begin(), max>(builder); + + for (auto& [val, name] : magic_enum::enum_entries()) { + // fmt::print("{} = {},\n", name, static_cast(val)); + auto _val = val; + auto _name = name; + builder.property(std::string(name), [=]() -> Local { + try { + return Number::newNumber(static_cast(_val)); + } catch (const std::exception&) { + logger.error("Error in get {}.{}", enumName, _name); + } + return Local(); + }); + } + + builder.property("keys", &keys); + // builder.property("object", &toObject); + builder.function("getName", &getName); + // fmt::print("\n"); + return builder.build(); + } }; -inline void ReplaceStr(std::string &str, const std::string &from, - const std::string &to) { - size_t startPos = 0; - while ((startPos = str.find(from, startPos)) != std::string::npos) { - str.replace(startPos, from.length(), to); - startPos += to.length(); - } +inline void ReplaceStr(std::string& str, const std::string& from, const std::string& to) { + size_t startPos = 0; + while ((startPos = str.find(from, startPos)) != std::string::npos) { + str.replace(startPos, from.length(), to); + startPos += to.length(); + } } diff --git a/src/api/BaseAPI.cpp b/src/api/BaseAPI.cpp index 2efcd063..7dc58cb6 100644 --- a/src/api/BaseAPI.cpp +++ b/src/api/BaseAPI.cpp @@ -8,47 +8,42 @@ #include "api/APIHelp.h" #include "api/McAPI.h" -#include "main/Global.hpp" +#include "main/Global.h" #include "mc/common/Common.h" #include "mc/common/SharedConstants.h" ///////////////////// Enum ////////////////////// -ClassDefine DamageCauseEnumBuilder = - EnumDefineBuilder::build("DamageCause"); +ClassDefine DamageCauseEnumBuilder = EnumDefineBuilder::build("DamageCause"); //////////////////// Class Definition //////////////////// -ClassDefine IntPosBuilder = - defineClass("IntPos") - .constructor(&IntPos::create) - .instanceProperty("x", &IntPos::getX, &IntPos::setX) - .instanceProperty("y", &IntPos::getY, &IntPos::setY) - .instanceProperty("z", &IntPos::getZ, &IntPos::setZ) - .instanceProperty("dim", &IntPos::getDim) - .instanceProperty("dimid", &IntPos::getDimId, &IntPos::setDimId) +ClassDefine IntPosBuilder = defineClass("IntPos") + .constructor(&IntPos::create) + .instanceProperty("x", &IntPos::getX, &IntPos::setX) + .instanceProperty("y", &IntPos::getY, &IntPos::setY) + .instanceProperty("z", &IntPos::getZ, &IntPos::setZ) + .instanceProperty("dim", &IntPos::getDim) + .instanceProperty("dimid", &IntPos::getDimId, &IntPos::setDimId) - .instanceFunction("toString", &IntPos::toString) - .build(); + .instanceFunction("toString", &IntPos::toString) + .build(); -ClassDefine FloatPosBuilder = - defineClass("FloatPos") - .constructor(&FloatPos::create) - .instanceProperty("x", &FloatPos::getX, &FloatPos::setX) - .instanceProperty("y", &FloatPos::getY, &FloatPos::setY) - .instanceProperty("z", &FloatPos::getZ, &FloatPos::setZ) - .instanceProperty("dim", &FloatPos::getDim) - .instanceProperty("dimid", &FloatPos::getDimId, &FloatPos::setDimId) +ClassDefine FloatPosBuilder = defineClass("FloatPos") + .constructor(&FloatPos::create) + .instanceProperty("x", &FloatPos::getX, &FloatPos::setX) + .instanceProperty("y", &FloatPos::getY, &FloatPos::setY) + .instanceProperty("z", &FloatPos::getZ, &FloatPos::setZ) + .instanceProperty("dim", &FloatPos::getDim) + .instanceProperty("dimid", &FloatPos::getDimId, &FloatPos::setDimId) - .instanceFunction("toString", &FloatPos::toString) - .build(); + .instanceFunction("toString", &FloatPos::toString) + .build(); ClassDefine DirectionAngleBuilder = defineClass("DirectionAngle") .constructor(&DirectionAngle::create) - .instanceProperty("pitch", &DirectionAngle::getPitch, - &DirectionAngle::setPitch) - .instanceProperty("yaw", &DirectionAngle::getYaw, - &DirectionAngle::setYaw) + .instanceProperty("pitch", &DirectionAngle::getPitch, &DirectionAngle::setPitch) + .instanceProperty("yaw", &DirectionAngle::getYaw, &DirectionAngle::setYaw) .instanceFunction("toFacing", &DirectionAngle::toFacing) .instanceFunction("toString", &DirectionAngle::toString) @@ -57,215 +52,198 @@ ClassDefine DirectionAngleBuilder = //////////////////// IntPos //////////////////// -IntPos *IntPos::create(const Arguments &args) { - if (args.size() < 3) - return nullptr; - try { - IntPos *p = new IntPos(args.thiz()); - p->x = args[0].asNumber().toInt32(); - p->y = args[1].asNumber().toInt32(); - p->z = args[2].asNumber().toInt32(); - p->dim = args[3].asNumber().toInt32(); - return p; - } catch (...) { - return nullptr; - } +IntPos* IntPos::create(const Arguments& args) { + if (args.size() < 3) return nullptr; + try { + IntPos* p = new IntPos(args.thiz()); + p->x = args[0].asNumber().toInt32(); + p->y = args[1].asNumber().toInt32(); + p->z = args[2].asNumber().toInt32(); + p->dim = args[3].asNumber().toInt32(); + return p; + } catch (...) { + return nullptr; + } } Local IntPos::newPos(int x, int y, int z, int dim) { - return EngineScope::currentEngine()->newNativeClass(x, y, z, dim); + return EngineScope::currentEngine()->newNativeClass(x, y, z, dim); } -Local IntPos::newPos(const BlockPos &b, int dim) { - return IntPos::newPos(b.x, b.y, b.z, dim); -} +Local IntPos::newPos(const BlockPos& b, int dim) { return IntPos::newPos(b.x, b.y, b.z, dim); } -Local IntPos::newPos(const IntVec4 &v) { - return IntPos::newPos(v.x, v.y, v.z, v.dim); -} +Local IntPos::newPos(const IntVec4& v) { return IntPos::newPos(v.x, v.y, v.z, v.dim); } -Local IntPos::newPos(const BlockPos *b, int dim) { - return IntPos::newPos(b->x, b->y, b->z, dim); -} +Local IntPos::newPos(const BlockPos* b, int dim) { return IntPos::newPos(b->x, b->y, b->z, dim); } -Local IntPos::newPos(const BlockPos *b, BlockSource *bs) { - return IntPos::newPos(b->x, b->y, b->z, (int)bs->getDimensionId()); +Local IntPos::newPos(const BlockPos* b, BlockSource* bs) { + return IntPos::newPos(b->x, b->y, b->z, (int)bs->getDimensionId()); } -IntPos *IntPos::extractPos(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine()->getNativeInstance(v); - else - return nullptr; +IntPos* IntPos::extractPos(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v); + else return nullptr; } Local IntPos::getDim() { return String::newString(DimId2Name(dim)); } Local IntPos::toString() { - try { - return String::newString( - fmt::format("{}({}, {}, {})", DimId2Name(dim), x, y, z)); - } - CATCH("Fail in toString!"); + try { + return String::newString(fmt::format("{}({}, {}, {})", DimId2Name(dim), x, y, z)); + } + CATCH("Fail in toString!"); } //////////////////// FloatPos //////////////////// -FloatPos *FloatPos::create(const Arguments &args) { - if (args.size() < 3) - return nullptr; - try { - FloatPos *p = new FloatPos(args.thiz()); - p->x = args[0].asNumber().toFloat(); - p->y = args[1].asNumber().toFloat(); - p->z = args[2].asNumber().toFloat(); - p->dim = args[3].asNumber().toInt32(); - return p; - } catch (...) { - return nullptr; - } +FloatPos* FloatPos::create(const Arguments& args) { + if (args.size() < 3) return nullptr; + try { + FloatPos* p = new FloatPos(args.thiz()); + p->x = args[0].asNumber().toFloat(); + p->y = args[1].asNumber().toFloat(); + p->z = args[2].asNumber().toFloat(); + p->dim = args[3].asNumber().toInt32(); + return p; + } catch (...) { + return nullptr; + } } Local FloatPos::newPos(double x, double y, double z, int dim) { - return EngineScope::currentEngine()->newNativeClass(x, y, z, dim); + return EngineScope::currentEngine()->newNativeClass(x, y, z, dim); } -Local FloatPos::newPos(const Vec3 &v, int dim) { - return FloatPos::newPos(v.x, v.y, v.z, dim); -} +Local FloatPos::newPos(const Vec3& v, int dim) { return FloatPos::newPos(v.x, v.y, v.z, dim); } -Local FloatPos::newPos(const FloatVec4 &v) { - return FloatPos::newPos(v.x, v.y, v.z, v.dim); -} +Local FloatPos::newPos(const FloatVec4& v) { return FloatPos::newPos(v.x, v.y, v.z, v.dim); } -FloatPos *FloatPos::extractPos(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine()->getNativeInstance(v); - else - return nullptr; +FloatPos* FloatPos::extractPos(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v); + else return nullptr; } Local FloatPos::getDim() { - string name; - switch (dim) { - case 0: - name = tr("base.getDimName.0"); - break; - case 1: - name = tr("base.getDimName.1"); - break; - case 2: - name = tr("base.getDimName.2"); - break; - default: - name = tr("base.getDimName.unknown"); - break; - } - return String::newString(name); + string name; + switch (dim) { + case 0: + name = tr("base.getDimName.0"); + break; + case 1: + name = tr("base.getDimName.1"); + break; + case 2: + name = tr("base.getDimName.2"); + break; + default: + name = tr("base.getDimName.unknown"); + break; + } + return String::newString(name); } Local FloatPos::toString() { - try { - return String::newString( - fmt::format("{}({}, {}, {})", DimId2Name(dim), x, y, z)); - } - CATCH("Fail in toString!"); + try { + return String::newString(fmt::format("{}({}, {}, {})", DimId2Name(dim), x, y, z)); + } + CATCH("Fail in toString!"); } //////////////////// DirectionAngle //////////////////// -DirectionAngle *DirectionAngle::create(const Arguments &args) { - if (args.size() < 2) - return nullptr; - try { - DirectionAngle *pa = new DirectionAngle(args.thiz()); - pa->pitch = args[0].asNumber().toDouble(); - pa->yaw = args[1].asNumber().toDouble(); - return pa; - } catch (...) { - return nullptr; - } +DirectionAngle* DirectionAngle::create(const Arguments& args) { + if (args.size() < 2) return nullptr; + try { + DirectionAngle* pa = new DirectionAngle(args.thiz()); + pa->pitch = args[0].asNumber().toDouble(); + pa->yaw = args[1].asNumber().toDouble(); + return pa; + } catch (...) { + return nullptr; + } } -DirectionAngle *DirectionAngle::extract(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine()->getNativeInstance(v); - else - return nullptr; +DirectionAngle* DirectionAngle::extract(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v); + else return nullptr; } Local DirectionAngle::toString() { - try { - return String::newString(fmt::format("({}, {})", pitch, yaw)); - } - CATCH("Fail in toString"); + try { + return String::newString(fmt::format("({}, {})", pitch, yaw)); + } + CATCH("Fail in toString"); } Local DirectionAngle::toFacing() { - int facing = -1; - switch (Facing::convertYRotationToFacingDirection(yaw)) { - case 2: - facing = 0; - break; - case 3: - facing = 2; - break; - case 4: - facing = 3; - break; - case 5: - facing = 1; - break; - } - return Number::newNumber(facing); + int facing = -1; + switch (Facing::convertYRotationToFacingDirection(yaw)) { + case 2: + facing = 0; + break; + case 3: + facing = 2; + break; + case 4: + facing = 3; + break; + case 5: + facing = 1; + break; + } + return Number::newNumber(facing); } Local DirectionAngle::newAngle(float pitch, float yaw) { - return EngineScope::currentEngine()->newNativeClass(pitch, - yaw); + return EngineScope::currentEngine()->newNativeClass(pitch, yaw); } //////////////////// APIs //////////////////// -Local McClass::newIntPos(const Arguments &args) { - CHECK_ARGS_COUNT(args, 4) - CHECK_ARG_TYPE(args[0], ValueKind::kNumber) - CHECK_ARG_TYPE(args[1], ValueKind::kNumber) - CHECK_ARG_TYPE(args[2], ValueKind::kNumber) - CHECK_ARG_TYPE(args[3], ValueKind::kNumber) - - try { - return IntPos::newPos(args[0].toInt(), args[1].toInt(), args[2].toInt(), - args[3].toInt()); - } - CATCH("Fail in NewIntPos!") -} - -Local McClass::newFloatPos(const Arguments &args) { - CHECK_ARGS_COUNT(args, 4) - CHECK_ARG_TYPE(args[0], ValueKind::kNumber) - CHECK_ARG_TYPE(args[1], ValueKind::kNumber) - CHECK_ARG_TYPE(args[2], ValueKind::kNumber) - CHECK_ARG_TYPE(args[3], ValueKind::kNumber) - - try { - return FloatPos::newPos(args[0].asNumber().toFloat(), - args[1].asNumber().toFloat(), - args[2].asNumber().toFloat(), args[3].toInt()); - } - CATCH("Fail in NewFloatPos!") +Local McClass::newIntPos(const Arguments& args) { + CHECK_ARGS_COUNT(args, 4) + CHECK_ARG_TYPE(args[0], ValueKind::kNumber) + CHECK_ARG_TYPE(args[1], ValueKind::kNumber) + CHECK_ARG_TYPE(args[2], ValueKind::kNumber) + CHECK_ARG_TYPE(args[3], ValueKind::kNumber) + + try { + return IntPos::newPos(args[0].toInt(), args[1].toInt(), args[2].toInt(), args[3].toInt()); + } + CATCH("Fail in NewIntPos!") +} + +Local McClass::newFloatPos(const Arguments& args) { + CHECK_ARGS_COUNT(args, 4) + CHECK_ARG_TYPE(args[0], ValueKind::kNumber) + CHECK_ARG_TYPE(args[1], ValueKind::kNumber) + CHECK_ARG_TYPE(args[2], ValueKind::kNumber) + CHECK_ARG_TYPE(args[3], ValueKind::kNumber) + + try { + return FloatPos::newPos( + args[0].asNumber().toFloat(), + args[1].asNumber().toFloat(), + args[2].asNumber().toFloat(), + args[3].toInt() + ); + } + CATCH("Fail in NewFloatPos!") +} + +Local McClass::getBDSVersion(const Arguments& args) { + try { + return String::newString(Common::getGameVersionString()); + } + CATCH("Fail in GetBDSVersion!") +} + +Local McClass::getServerProtocolVersion(const Arguments& args) { + try { + return Number::newNumber(SharedConstants::NetworkProtocolVersion); + } + CATCH("Fail in GetServerProtocolVersion!") } - -Local McClass::getBDSVersion(const Arguments &args) { - try { - return String::newString(Common::getGameVersionString()); - } - CATCH("Fail in GetBDSVersion!") -} - -Local McClass::getServerProtocolVersion(const Arguments &args) { - try { - return Number::newNumber(SharedConstants::NetworkProtocolVersion); - } - CATCH("Fail in GetServerProtocolVersion!") -} \ No newline at end of file diff --git a/src/api/BaseAPI.h b/src/api/BaseAPI.h index 00a71378..eae8634e 100644 --- a/src/api/BaseAPI.h +++ b/src/api/BaseAPI.h @@ -1,7 +1,7 @@ #pragma once #include "api/APIHelp.h" -#include "main/Global.hpp" +#include "main/Global.h" #include class BlockSource; @@ -12,9 +12,7 @@ extern ClassDefine DamageCauseEnumBuilder; //////////////////// Classes //////////////////// class IntPos : public IntVec4, public ScriptClass { public: - explicit IntPos(const Local& scriptObj) - : ScriptClass(scriptObj) { - } + explicit IntPos(const Local& scriptObj) : ScriptClass(scriptObj) {} static IntPos* create(const Arguments& args); static Local newPos(int x, int y, int z, int dim = -1); @@ -22,77 +20,43 @@ class IntPos : public IntVec4, public ScriptClass { static Local newPos(const BlockPos* b, int dim = -1); static Local newPos(const BlockPos* b, BlockSource* bs); static Local newPos(const IntVec4& v); - static IntPos* extractPos(Local v); + static IntPos* extractPos(Local v); - Local getX() { - return Number::newNumber(x); - } - Local getY() { - return Number::newNumber(y); - } - Local getZ() { - return Number::newNumber(z); - } + Local getX() { return Number::newNumber(x); } + Local getY() { return Number::newNumber(y); } + Local getZ() { return Number::newNumber(z); } Local getDim(); - Local getDimId() { - return Number::newNumber(dim); - } - void setX(const Local& value) { - x = value.asNumber().toInt64(); - } - void setY(const Local& value) { - y = value.asNumber().toInt64(); - } - void setZ(const Local& value) { - z = value.asNumber().toInt64(); - } - void setDimId(const Local& value) { - dim = value.asNumber().toInt32(); - } + Local getDimId() { return Number::newNumber(dim); } + void setX(const Local& value) { x = value.asNumber().toInt64(); } + void setY(const Local& value) { y = value.asNumber().toInt64(); } + void setZ(const Local& value) { z = value.asNumber().toInt64(); } + void setDimId(const Local& value) { dim = value.asNumber().toInt32(); } Local toString(); }; extern ClassDefine IntPosBuilder; class FloatPos : public FloatVec4, public ScriptClass { public: - explicit FloatPos(const Local& scriptObj) - : ScriptClass(scriptObj) { - } + explicit FloatPos(const Local& scriptObj) : ScriptClass(scriptObj) {} static FloatPos* create(const Arguments& args); static Local newPos(double x, double y, double z, int dim = -1); static Local newPos(const Vec3& v, int dim = -1); static Local newPos(const FloatVec4& v); - static FloatPos* extractPos(Local v); + static FloatPos* extractPos(Local v); - Local getX() { - return Number::newNumber(x); - } - Local getY() { - return Number::newNumber(y); - } - Local getZ() { - return Number::newNumber(z); - } + Local getX() { return Number::newNumber(x); } + Local getY() { return Number::newNumber(y); } + Local getZ() { return Number::newNumber(z); } Local getDim(); - Local getDimId() { - return Number::newNumber(dim); - } + Local getDimId() { return Number::newNumber(dim); } Local toString(); - void setX(const Local& value) { - x = value.asNumber().toInt64(); - } - void setY(const Local& value) { - y = value.asNumber().toInt64(); - } - void setZ(const Local& value) { - z = value.asNumber().toInt64(); - } - void setDimId(const Local& value) { - dim = value.asNumber().toInt32(); - } + void setX(const Local& value) { x = value.asNumber().toInt64(); } + void setY(const Local& value) { y = value.asNumber().toInt64(); } + void setZ(const Local& value) { z = value.asNumber().toInt64(); } + void setDimId(const Local& value) { dim = value.asNumber().toInt32(); } }; extern ClassDefine FloatPosBuilder; @@ -100,27 +64,17 @@ class DirectionAngle : public ScriptClass { public: double pitch = 0, yaw = 0; - explicit DirectionAngle(const Local& scriptObj) - : ScriptClass(scriptObj) { - } + explicit DirectionAngle(const Local& scriptObj) : ScriptClass(scriptObj) {} static DirectionAngle* create(const Arguments& args); static DirectionAngle* extract(Local value); static Local newAngle(float pitch, float yaw); - Local getPitch() { - return Number::newNumber(pitch); - } - Local getYaw() { - return Number::newNumber(yaw); - } - void setPitch(const Local& value) { - pitch = value.asNumber().toDouble(); - } - void setYaw(const Local& value) { - yaw = value.asNumber().toDouble(); - } - Local toString(); + Local getPitch() { return Number::newNumber(pitch); } + Local getYaw() { return Number::newNumber(yaw); } + void setPitch(const Local& value) { pitch = value.asNumber().toDouble(); } + void setYaw(const Local& value) { yaw = value.asNumber().toDouble(); } + Local toString(); Local toFacing(); }; -extern ClassDefine DirectionAngleBuilder; \ No newline at end of file +extern ClassDefine DirectionAngleBuilder; diff --git a/src/api/BlockAPI.cpp b/src/api/BlockAPI.cpp index f3c6650c..96ceaab4 100644 --- a/src/api/BlockAPI.cpp +++ b/src/api/BlockAPI.cpp @@ -1,4 +1,5 @@ #include "api/BlockAPI.h" +#include "ScriptX/ScriptX.h" #include "api/APIHelp.h" #include "api/BaseAPI.h" #include "api/BlockEntityAPI.h" @@ -16,7 +17,6 @@ #include "mc/world/level/block/Block.h" #include "mc/world/level/block/actor/BlockActor.h" #include "mc/world/level/dimension/Dimension.h" -#include "ScriptX/ScriptX.h" #include //////////////////// Class Definition //////////////////// @@ -47,8 +47,7 @@ ClassDefine BlockClassBuilder = .instanceProperty("isStemBlock", &BlockClass::isStemBlock) .instanceProperty("isSlabBlock", &BlockClass::isSlabBlock) .instanceProperty("isUnbreakable", &BlockClass::isUnbreakable) - .instanceProperty("isWaterBlockingBlock", - &BlockClass::isWaterBlockingBlock) + .instanceProperty("isWaterBlockingBlock", &BlockClass::isWaterBlockingBlock) .instanceFunction("setNbt", &BlockClass::setNbt) .instanceFunction("getNbt", &BlockClass::getNbt) @@ -67,546 +66,524 @@ ClassDefine BlockClassBuilder = //////////////////// Classes //////////////////// -BlockClass::BlockClass(Block const *p) - : ScriptClass(ScriptClass::ConstructFromCpp{}), - block(const_cast(p)) { - preloadData({0, 0, 0}, -1); +BlockClass::BlockClass(Block const* p) +: ScriptClass(ScriptClass::ConstructFromCpp{}), + block(const_cast(p)) { + preloadData({0, 0, 0}, -1); } -BlockClass::BlockClass(Block const *p, BlockPos bp, int dim) - : ScriptClass(ScriptClass::ConstructFromCpp{}), - block(const_cast(p)) { - preloadData(bp, dim); +BlockClass::BlockClass(Block const* p, BlockPos bp, int dim) +: ScriptClass(ScriptClass::ConstructFromCpp{}), + block(const_cast(p)) { + preloadData(bp, dim); } // generating function -Local BlockClass::newBlock(Block const *p, BlockPos const *pos, - int dim) { - auto newp = new BlockClass(p, *pos, dim); - return newp->getScriptObject(); +Local BlockClass::newBlock(Block const* p, BlockPos const* pos, int dim) { + auto newp = new BlockClass(p, *pos, dim); + return newp->getScriptObject(); } -Local BlockClass::newBlock(BlockPos const *pos, int dim) { - Block bl = ll::service::getLevel()->getDimension(dim)->getBlockSourceFromMainChunkSource().getBlock(*pos); - return BlockClass::newBlock(&bl, pos, dim); +Local BlockClass::newBlock(BlockPos const* pos, int dim) { + Block bl = ll::service::getLevel()->getDimension(dim)->getBlockSourceFromMainChunkSource().getBlock(*pos); + return BlockClass::newBlock(&bl, pos, dim); } -Local BlockClass::newBlock(const BlockPos &pos, int dim) { - return newBlock((BlockPos *)&pos, dim); -} +Local BlockClass::newBlock(const BlockPos& pos, int dim) { return newBlock((BlockPos*)&pos, dim); } -Local BlockClass::newBlock(Block const *p, BlockPos const *pos, - BlockSource const *bs) { - auto newp = new BlockClass(p, *pos, bs->getDimensionId()); - return newp->getScriptObject(); +Local BlockClass::newBlock(Block const* p, BlockPos const* pos, BlockSource const* bs) { + auto newp = new BlockClass(p, *pos, bs->getDimensionId()); + return newp->getScriptObject(); } Local BlockClass::newBlock(IntVec4 pos) { - BlockPos bp = {(float)pos.x, (float)pos.y, (float)pos.z}; - Block bl = ll::service::getLevel()->getDimension(pos.dim)->getBlockSourceFromMainChunkSource().getBlock(bp); - return BlockClass::newBlock(&bl, &bp, pos.dim); + BlockPos bp = {(float)pos.x, (float)pos.y, (float)pos.z}; + Block bl = ll::service::getLevel()->getDimension(pos.dim)->getBlockSourceFromMainChunkSource().getBlock(bp); + return BlockClass::newBlock(&bl, &bp, pos.dim); } -Block *BlockClass::extract(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine() - ->getNativeInstance(v) - ->get(); - else - return nullptr; +Block* BlockClass::extract(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v)->get(); + else return nullptr; } // member function void BlockClass::preloadData(BlockPos bp, int dim) { - name = block->getName().getString(); // TODO - type = block->getName().getString(); - id = block->getBlockItemId(); - pos = {bp.x, bp.y, bp.z, dim}; + name = block->getName().getString(); // TODO + type = block->getName().getString(); + id = block->getBlockItemId(); + pos = {bp.x, bp.y, bp.z, dim}; } Local BlockClass::getName() { - try { - // preloaded - return String::newString(name); - } - CATCH("Fail in getBlockName!"); + try { + // preloaded + return String::newString(name); + } + CATCH("Fail in getBlockName!"); } Local BlockClass::getType() { - try { - // preloaded - return String::newString(type); - } - CATCH("Fail in getBlockType!"); + try { + // preloaded + return String::newString(type); + } + CATCH("Fail in getBlockType!"); } Local BlockClass::getId() { - try { - // preloaded - return Number::newNumber(id); - } - CATCH("Fail in getBlockId!"); + try { + // preloaded + return Number::newNumber(id); + } + CATCH("Fail in getBlockId!"); } Local BlockClass::getPos() { - try { - // preloaded - return IntPos::newPos(pos); - } - CATCH("Fail in getBlockPos!"); + try { + // preloaded + return IntPos::newPos(pos); + } + CATCH("Fail in getBlockPos!"); } Local BlockClass::getTileData() { - try { - // preloaded - return Number::newNumber(block->getVariant()); - } - CATCH("Fail in getTileData!"); + try { + // preloaded + return Number::newNumber(block->getVariant()); + } + CATCH("Fail in getTileData!"); } Local BlockClass::getVariant() { - try { - return Number::newNumber(block->getVariant()); - } - CATCH("Fail in getVariant!"); + try { + return Number::newNumber(block->getVariant()); + } + CATCH("Fail in getVariant!"); } Local BlockClass::getTranslucency() { - try { - return Number::newNumber(block->getTranslucency()); - } - CATCH("Fail in getTranslucency!"); + try { + return Number::newNumber(block->getTranslucency()); + } + CATCH("Fail in getTranslucency!"); } Local BlockClass::getThickness() { - try { - return Number::newNumber(block->getThickness()); - } - CATCH("Fail in getThickness!"); + try { + return Number::newNumber(block->getThickness()); + } + CATCH("Fail in getThickness!"); } Local BlockClass::isAir() { - try { - return Boolean::newBoolean(block->isAir()); - } - CATCH("Fail in isAir!"); + try { + return Boolean::newBoolean(block->isAir()); + } + CATCH("Fail in isAir!"); } Local BlockClass::isBounceBlock() { - try { - return Boolean::newBoolean(block->isBounceBlock()); - } - CATCH("Fail in isBounceBlock!"); + try { + return Boolean::newBoolean(block->isBounceBlock()); + } + CATCH("Fail in isBounceBlock!"); } Local BlockClass::isButtonBlock() { - try { - return Boolean::newBoolean(block->isButtonBlock()); - } - CATCH("Fail in isButtonBlock!"); + try { + return Boolean::newBoolean(block->isButtonBlock()); + } + CATCH("Fail in isButtonBlock!"); } Local BlockClass::isCropBlock() { - try { - return Boolean::newBoolean(block->isCropBlock()); - } - CATCH("Fail in isCropBlock!"); + try { + return Boolean::newBoolean(block->isCropBlock()); + } + CATCH("Fail in isCropBlock!"); } Local BlockClass::isDoorBlock() { - try { - return Boolean::newBoolean(block->isDoorBlock()); - } - CATCH("Fail in isDoorBlock!"); + try { + return Boolean::newBoolean(block->isDoorBlock()); + } + CATCH("Fail in isDoorBlock!"); } Local BlockClass::isFenceBlock() { - try { - return Boolean::newBoolean(block->isFenceBlock()); - } - CATCH("Fail in isFenceBlock!"); + try { + return Boolean::newBoolean(block->isFenceBlock()); + } + CATCH("Fail in isFenceBlock!"); } Local BlockClass::isFenceGateBlock() { - try { - return Boolean::newBoolean(block->isFenceGateBlock()); - } - CATCH("Fail in isFenceGateBlock!"); + try { + return Boolean::newBoolean(block->isFenceGateBlock()); + } + CATCH("Fail in isFenceGateBlock!"); } Local BlockClass::isThinFenceBlock() { - try { - return Boolean::newBoolean(block->isThinFenceBlock()); - } - CATCH("Fail in isThinFenceBlock!"); + try { + return Boolean::newBoolean(block->isThinFenceBlock()); + } + CATCH("Fail in isThinFenceBlock!"); } Local BlockClass::isHeavyBlock() { - try { - return Boolean::newBoolean(block->isFallingBlock()); - } - CATCH("Fail in isHeavyBlock!"); + try { + return Boolean::newBoolean(block->isFallingBlock()); + } + CATCH("Fail in isHeavyBlock!"); } Local BlockClass::isStemBlock() { - try { - return Boolean::newBoolean(block->isStemBlock()); - } - CATCH("Fail in isStemBlock!"); + try { + return Boolean::newBoolean(block->isStemBlock()); + } + CATCH("Fail in isStemBlock!"); } Local BlockClass::isSlabBlock() { - try { - return Boolean::newBoolean(block->isSlabBlock()); - } - CATCH("Fail in isSlabBlock!"); + try { + return Boolean::newBoolean(block->isSlabBlock()); + } + CATCH("Fail in isSlabBlock!"); } Local BlockClass::isUnbreakable() { - try { - return Boolean::newBoolean(block->isUnbreakable()); - } - CATCH("Fail in isUnbreakable!"); + try { + return Boolean::newBoolean(block->isUnbreakable()); + } + CATCH("Fail in isUnbreakable!"); } Local BlockClass::isWaterBlockingBlock() { - try { - return Boolean::newBoolean(block->isWaterBlocking()); - } - CATCH("Fail in isWaterBlockingBlock!"); + try { + return Boolean::newBoolean(block->isWaterBlocking()); + } + CATCH("Fail in isWaterBlockingBlock!"); } -Local BlockClass::asPointer(const Arguments &args) { - try { - return NativePointer::newNativePointer(block); - } - CATCH("Fail in asPointer!"); +Local BlockClass::asPointer(const Arguments& args) { + try { + return NativePointer::newNativePointer(block); + } + CATCH("Fail in asPointer!"); } -Local BlockClass::destroyBlock(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kBoolean); +Local BlockClass::destroyBlock(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kBoolean); - try { - // same as `Level::getBlockInstance(pos.getBlockPos(), - // pos.dim).breakNaturally()` when drop - BlockSource& bl = ll::service::getLevel()->getDimension(pos.dim)->getBlockSourceFromMainChunkSource(); - return Boolean::newBoolean(ll::service::getLevel()->destroyBlock( - bl, pos.getBlockPos(), args[0].asBoolean().value())); - } - CATCH("Fail in destroyBlock!"); + try { + // same as `Level::getBlockInstance(pos.getBlockPos(), + // pos.dim).breakNaturally()` when drop + BlockSource& bl = ll::service::getLevel()->getDimension(pos.dim)->getBlockSourceFromMainChunkSource(); + return Boolean::newBoolean( + ll::service::getLevel()->destroyBlock(bl, pos.getBlockPos(), args[0].asBoolean().value()) + ); + } + CATCH("Fail in destroyBlock!"); } -Local BlockClass::getNbt(const Arguments &args) { - try { - return NbtCompoundClass::pack( - std::move(block->getSerializationId().clone())); - } - CATCH("Fail in getNbt!"); +Local BlockClass::getNbt(const Arguments& args) { + try { + return NbtCompoundClass::pack(std::move(block->getSerializationId().clone())); + } + CATCH("Fail in getNbt!"); } #include "mc/world/level/block/utils/BlockSerializationUtils.h" -Local BlockClass::setNbt(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - - try { - auto nbt = NbtCompoundClass::extract(args[0]); - if (!nbt) - return Local(); // Null - - // update Pre Data - auto result = BlockSerializationUtils::tryGetBlockFromNBT(*nbt); - const Block *bl = result.second; - if (bl) { -ll::service::getLevel()->getDimension(pos.dim)->getBlockSourceFromMainChunkSource().setBlock(pos.getBlockPos(), *bl, 3, nullptr, nullptr); - } - preloadData(pos.getBlockPos(), pos.getDimensionId()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setNbt!") -} - -Local BlockClass::getBlockState(const Arguments &args) { - try { - auto list = block->getSerializationId(); - try { - return Tag2Value((Tag *)list.get("states"), true); - } catch (...) { - return Array::newArray(); - } - } catch (const std::out_of_range &e) { - return Object::newObject(); - } - CATCH("Fail in getBlockState!") -} - -Local BlockClass::hasContainer(const Arguments &args) { - try { - Block bl = - ll::service::getLevel()->getDimension(pos.dim)->getBlockSourceFromMainChunkSource().getBlock(pos.getBlockPos()); - return Boolean::newBoolean(bl.isContainerBlock()); - } - CATCH("Fail in hasContainer!"); -} - -Local BlockClass::getContainer(const Arguments &args) { - try { - Container* container = ll::service::getLevel() - ->getDimension(pos.dim) - ->getBlockSourceFromMainChunkSource() - .getBlockEntity(pos.getBlockPos()) - ->getContainer(); - return container ? ContainerClass::newContainer(container) : Local(); - } - CATCH("Fail in getContainer!"); -} - -Local BlockClass::hasBlockEntity(const Arguments &args) { - try { - return Boolean::newBoolean(block->hasBlockEntity()); - } - CATCH("Fail in hasBlockEntity!"); -} - -Local BlockClass::getBlockEntity(const Arguments &args) { - try { - BlockActor* be = ll::service::getLevel()-> - getDimension(pos.dim)-> - getBlockSourceFromMainChunkSource(). - getBlockEntity( - pos.getBlockPos() - ); - return be ? BlockEntityClass::newBlockEntity(be, pos.dim) : Local(); - } - CATCH("Fail in getBlockEntity!"); -} - -Local BlockClass::removeBlockEntity(const Arguments &args) { - try { -ll::service::getLevel()->getDimension(pos.dim)->getBlockSourceFromMainChunkSource().removeBlockEntity(pos.getBlockPos()); //==========??? - return Boolean::newBoolean(true); - } - CATCH("Fail in removeBlockEntity!"); +Local BlockClass::setNbt(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + + try { + auto nbt = NbtCompoundClass::extract(args[0]); + if (!nbt) return Local(); // Null + + // update Pre Data + auto result = BlockSerializationUtils::tryGetBlockFromNBT(*nbt); + const Block* bl = result.second; + if (bl) { + ll::service::getLevel() + ->getDimension(pos.dim) + ->getBlockSourceFromMainChunkSource() + .setBlock(pos.getBlockPos(), *bl, 3, nullptr, nullptr); + } + preloadData(pos.getBlockPos(), pos.getDimensionId()); + return Boolean::newBoolean(true); + } + CATCH("Fail in setNbt!") +} + +Local BlockClass::getBlockState(const Arguments& args) { + try { + auto list = block->getSerializationId(); + try { + return Tag2Value((Tag*)list.get("states"), true); + } catch (...) { + return Array::newArray(); + } + } catch (const std::out_of_range& e) { + return Object::newObject(); + } + CATCH("Fail in getBlockState!") +} + +Local BlockClass::hasContainer(const Arguments& args) { + try { + Block bl = ll::service::getLevel()->getDimension(pos.dim)->getBlockSourceFromMainChunkSource().getBlock( + pos.getBlockPos() + ); + return Boolean::newBoolean(bl.isContainerBlock()); + } + CATCH("Fail in hasContainer!"); +} + +Local BlockClass::getContainer(const Arguments& args) { + try { + Container* container = ll::service::getLevel() + ->getDimension(pos.dim) + ->getBlockSourceFromMainChunkSource() + .getBlockEntity(pos.getBlockPos()) + ->getContainer(); + return container ? ContainerClass::newContainer(container) : Local(); + } + CATCH("Fail in getContainer!"); +} + +Local BlockClass::hasBlockEntity(const Arguments& args) { + try { + return Boolean::newBoolean(block->hasBlockEntity()); + } + CATCH("Fail in hasBlockEntity!"); +} + +Local BlockClass::getBlockEntity(const Arguments& args) { + try { + BlockActor* be = + ll::service::getLevel()->getDimension(pos.dim)->getBlockSourceFromMainChunkSource().getBlockEntity( + pos.getBlockPos() + ); + return be ? BlockEntityClass::newBlockEntity(be, pos.dim) : Local(); + } + CATCH("Fail in getBlockEntity!"); +} + +Local BlockClass::removeBlockEntity(const Arguments& args) { + try { + ll::service::getLevel()->getDimension(pos.dim)->getBlockSourceFromMainChunkSource().removeBlockEntity( + pos.getBlockPos() + ); //==========??? + return Boolean::newBoolean(true); + } + CATCH("Fail in removeBlockEntity!"); } #include "mc/world/level/ChunkBlockPos.h" #include "mc/world/level/chunk/LevelChunk.h" // public API -Local McClass::getBlock(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - - try { - IntVec4 pos; - if (args.size() == 1) { - // IntPos - if (IsInstanceOf(args[0])) { - // IntPos - IntPos *posObj = IntPos::extractPos(args[0]); - if (posObj->dim < 0) - return Boolean::newBoolean(false); - else { - pos = *posObj; +Local McClass::getBlock(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + + try { + IntVec4 pos; + if (args.size() == 1) { + // IntPos + if (IsInstanceOf(args[0])) { + // IntPos + IntPos* posObj = IntPos::extractPos(args[0]); + if (posObj->dim < 0) return Boolean::newBoolean(false); + else { + pos = *posObj; + } + } else if (IsInstanceOf(args[0])) { + // FloatPos + FloatPos* posObj = FloatPos::extractPos(args[0]); + if (posObj->dim < 0) return Boolean::newBoolean(false); + else { + pos = posObj->toIntVec4(); + } + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + } else if (args.size() == 4) { + // Number Pos + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + pos = {args[0].toInt(), args[1].toInt(), args[2].toInt(), args[3].toInt()}; + } else { + LOG_WRONG_ARGS_COUNT(); + return Local(); } - } else if (IsInstanceOf(args[0])) { - // FloatPos - FloatPos *posObj = FloatPos::extractPos(args[0]); - if (posObj->dim < 0) - return Boolean::newBoolean(false); - else { - pos = posObj->toIntVec4(); + + auto dimPtr = ll::service::getLevel()->getDimension(pos.dim).get(); + if (!dimPtr) { + return {}; } - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - } else if (args.size() == 4) { - // Number Pos - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - pos = {args[0].toInt(), args[1].toInt(), args[2].toInt(), - args[3].toInt()}; - } else { - LOG_WRONG_ARGS_COUNT(); - return Local(); - } - - auto dimPtr = ll::service::getLevel()->getDimension(pos.dim).get(); - if (!dimPtr) { - return {}; - } - BlockSource &bs = dimPtr->getBlockSourceFromMainChunkSource(); - auto lc = bs.getChunkAt(pos.getBlockPos()); - if (!lc) - return {}; - short minHeight = dimPtr->getMinHeight(); - if (pos.y < minHeight || pos.y > dimPtr->getHeight()) - return {}; - ChunkBlockPos cbpos = ChunkBlockPos(pos.getBlockPos(), minHeight); - auto block = const_cast(&lc->getBlock(cbpos)); - if (!block) { - // LOG_WRONG_ARG_TYPE(); - return {}; - } - BlockPos bp{pos.x, pos.y, pos.z}; - return BlockClass::newBlock(block, &bp, pos.dim); - } - CATCH("Fail in GetBlock!") -} - -Local McClass::setBlock(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - - try { - IntVec4 pos; - Local block; - unsigned short tileData = 0; - if (args.size() == 2 || args.size() == 3) { - if (args.size() == 3) { - CHECK_ARG_TYPE(args[1], ValueKind::kString); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - tileData = args[2].toInt(); - } - if (IsInstanceOf(args[0])) { - // IntPos - IntPos *posObj = IntPos::extractPos(args[0]); - if (posObj->dim < 0) - return Boolean::newBoolean(false); - else { - pos = *posObj; - block = args[1]; + BlockSource& bs = dimPtr->getBlockSourceFromMainChunkSource(); + auto lc = bs.getChunkAt(pos.getBlockPos()); + if (!lc) return {}; + short minHeight = dimPtr->getMinHeight(); + if (pos.y < minHeight || pos.y > dimPtr->getHeight()) return {}; + ChunkBlockPos cbpos = ChunkBlockPos(pos.getBlockPos(), minHeight); + auto block = const_cast(&lc->getBlock(cbpos)); + if (!block) { + // LOG_WRONG_ARG_TYPE(); + return {}; } - } else if (IsInstanceOf(args[0])) { - // FloatPos - FloatPos *posObj = FloatPos::extractPos(args[0]); - if (posObj->dim < 0) - return Boolean::newBoolean(false); - else { - pos = posObj->toIntVec4(); - block = args[1]; + BlockPos bp{pos.x, pos.y, pos.z}; + return BlockClass::newBlock(block, &bp, pos.dim); + } + CATCH("Fail in GetBlock!") +} + +Local McClass::setBlock(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + + try { + IntVec4 pos; + Local block; + unsigned short tileData = 0; + if (args.size() == 2 || args.size() == 3) { + if (args.size() == 3) { + CHECK_ARG_TYPE(args[1], ValueKind::kString); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + tileData = args[2].toInt(); + } + if (IsInstanceOf(args[0])) { + // IntPos + IntPos* posObj = IntPos::extractPos(args[0]); + if (posObj->dim < 0) return Boolean::newBoolean(false); + else { + pos = *posObj; + block = args[1]; + } + } else if (IsInstanceOf(args[0])) { + // FloatPos + FloatPos* posObj = FloatPos::extractPos(args[0]); + if (posObj->dim < 0) return Boolean::newBoolean(false); + else { + pos = posObj->toIntVec4(); + block = args[1]; + } + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + } else if (args.size() == 5 || args.size() == 6) { + // Number Pos + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + pos = {args[0].toInt(), args[1].toInt(), args[2].toInt(), args[3].toInt()}; + block = args[4]; + if (args.size() == 6) { + CHECK_ARG_TYPE(args[4], ValueKind::kString); + CHECK_ARG_TYPE(args[5], ValueKind::kNumber); + tileData = args[5].toInt(); + } + } else { + LOG_WRONG_ARGS_COUNT(); + return Local(); } - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - } else if (args.size() == 5 || args.size() == 6) { - // Number Pos - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - pos = {args[0].toInt(), args[1].toInt(), args[2].toInt(), - args[3].toInt()}; - block = args[4]; - if (args.size() == 6) { - CHECK_ARG_TYPE(args[4], ValueKind::kString); - CHECK_ARG_TYPE(args[5], ValueKind::kNumber); - tileData = args[5].toInt(); - } - } else { - LOG_WRONG_ARGS_COUNT(); - return Local(); - } - - if (block.isString()) { - optional_ref bl = - Block::tryGetFromRegistry(block.asString().toString(), tileData); - if (!bl.has_value()) { - return Boolean::newBoolean(false); - } - BlockSource &bs = ll::service::getLevel() - ->getDimension(pos.dim) - ->getBlockSourceFromMainChunkSource(); - return Boolean::newBoolean( - bs.setBlock(pos.getBlockPos(), bl, 3, nullptr, nullptr)); - } else if (IsInstanceOf(block)) { - // Nbt - CompoundTag *nbt = NbtCompoundClass::extract(block); - optional_ref bl = Block::tryGetFromRegistry(*nbt); - if (!bl.has_value()) { - return Boolean::newBoolean(false); - } - BlockSource &bs = ll::service::getLevel() - ->getDimension(pos.dim) - ->getBlockSourceFromMainChunkSource(); - return Boolean::newBoolean( - bs.setBlock(pos.getBlockPos(), bl, 3, nullptr, nullptr)); - } else { - // other block object - Block *bl = BlockClass::extract(block); - if (!bl) { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - BlockSource &bs = ll::service::getLevel() - ->getDimension(pos.dim) - ->getBlockSourceFromMainChunkSource(); - return Boolean::newBoolean( - bs.setBlock(pos.getBlockPos(), *bl, 3, nullptr, nullptr)); - } - } - CATCH("Fail in SetBlock!") -} - -Local McClass::spawnParticle(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2) - - try { - FloatVec4 pos; - Local type; - - if (args.size() == 2) { - // IntPos - CHECK_ARG_TYPE(args[1], ValueKind::kString); - - if (IsInstanceOf(args[0])) { - // IntPos - IntPos *posObj = IntPos::extractPos(args[0]); - if (posObj->dim < 0) - return Boolean::newBoolean(false); - else { - pos.x = posObj->x; - pos.y = posObj->y; - pos.z = posObj->z; - pos.dim = posObj->dim; - type = args[1]; + + if (block.isString()) { + optional_ref bl = Block::tryGetFromRegistry(block.asString().toString(), tileData); + if (!bl.has_value()) { + return Boolean::newBoolean(false); + } + BlockSource& bs = ll::service::getLevel()->getDimension(pos.dim)->getBlockSourceFromMainChunkSource(); + return Boolean::newBoolean(bs.setBlock(pos.getBlockPos(), bl, 3, nullptr, nullptr)); + } else if (IsInstanceOf(block)) { + // Nbt + CompoundTag* nbt = NbtCompoundClass::extract(block); + optional_ref bl = Block::tryGetFromRegistry(*nbt); + if (!bl.has_value()) { + return Boolean::newBoolean(false); + } + BlockSource& bs = ll::service::getLevel()->getDimension(pos.dim)->getBlockSourceFromMainChunkSource(); + return Boolean::newBoolean(bs.setBlock(pos.getBlockPos(), bl, 3, nullptr, nullptr)); + } else { + // other block object + Block* bl = BlockClass::extract(block); + if (!bl) { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + BlockSource& bs = ll::service::getLevel()->getDimension(pos.dim)->getBlockSourceFromMainChunkSource(); + return Boolean::newBoolean(bs.setBlock(pos.getBlockPos(), *bl, 3, nullptr, nullptr)); } - } else if (IsInstanceOf(args[0])) { - // FloatPos - FloatPos *posObj = FloatPos::extractPos(args[0]); - if (posObj->dim < 0) - return Boolean::newBoolean(false); - else { - pos = *posObj; - type = args[1]; + } + CATCH("Fail in SetBlock!") +} + +Local McClass::spawnParticle(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2) + + try { + FloatVec4 pos; + Local type; + + if (args.size() == 2) { + // IntPos + CHECK_ARG_TYPE(args[1], ValueKind::kString); + + if (IsInstanceOf(args[0])) { + // IntPos + IntPos* posObj = IntPos::extractPos(args[0]); + if (posObj->dim < 0) return Boolean::newBoolean(false); + else { + pos.x = posObj->x; + pos.y = posObj->y; + pos.z = posObj->z; + pos.dim = posObj->dim; + type = args[1]; + } + } else if (IsInstanceOf(args[0])) { + // FloatPos + FloatPos* posObj = FloatPos::extractPos(args[0]); + if (posObj->dim < 0) return Boolean::newBoolean(false); + else { + pos = *posObj; + type = args[1]; + } + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + } else if (args.size() == 5) { + // Number Pos + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + CHECK_ARG_TYPE(args[4], ValueKind::kString); + + pos = { + args[0].asNumber().toFloat(), + args[1].asNumber().toFloat(), + args[2].asNumber().toFloat(), + args[3].toInt()}; + type = args[4]; + } else { + LOG_WRONG_ARGS_COUNT(); + return Local(); } - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - } else if (args.size() == 5) { - // Number Pos - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - CHECK_ARG_TYPE(args[4], ValueKind::kString); - - pos = {args[0].asNumber().toFloat(), args[1].asNumber().toFloat(), - args[2].asNumber().toFloat(), args[3].toInt()}; - type = args[4]; - } else { - LOG_WRONG_ARGS_COUNT(); - return Local(); - } - - ll::service::getLevel()->spawnParticleEffect( - type.toStr(), pos.getVec3(), - ll::service::getLevel()->getDimension(pos.dim).get()); - return Boolean::newBoolean(true); - } - CATCH("Fail in SpawnParticle!") + + ll::service::getLevel() + ->spawnParticleEffect(type.toStr(), pos.getVec3(), ll::service::getLevel()->getDimension(pos.dim).get()); + return Boolean::newBoolean(true); + } + CATCH("Fail in SpawnParticle!") } diff --git a/src/api/BlockAPI.h b/src/api/BlockAPI.h index bdea613e..730c0d9e 100644 --- a/src/api/BlockAPI.h +++ b/src/api/BlockAPI.h @@ -1,66 +1,65 @@ #pragma once #include "api/APIHelp.h" -#include "main/Global.hpp" +#include "main/Global.h" #include //////////////////// Classes //////////////////// class Block; class BlockClass : public ScriptClass { private: - Block *block; + Block* block; - // Pre data - std::string name, type; - int id; - IntVec4 pos; + // Pre data + std::string name, type; + int id; + IntVec4 pos; public: - explicit BlockClass(Block const *p); - BlockClass(Block const *p, BlockPos bp, int dim); + explicit BlockClass(Block const* p); + BlockClass(Block const* p, BlockPos bp, int dim); - void preloadData(BlockPos bp, int dim); - Block *get() { return block; } + void preloadData(BlockPos bp, int dim); + Block* get() { return block; } - static Local newBlock(Block const *p, BlockPos const *pos, int dim); - static Local newBlock(BlockPos const *pos, int dim); - static Local newBlock(const BlockPos &pos, int dim); - static Local newBlock(Block const *p, BlockPos const *pos, - BlockSource const *bs); - static Local newBlock(IntVec4 pos); - static Block *extract(Local v); - Local asPointer(const Arguments &args); + static Local newBlock(Block const* p, BlockPos const* pos, int dim); + static Local newBlock(BlockPos const* pos, int dim); + static Local newBlock(const BlockPos& pos, int dim); + static Local newBlock(Block const* p, BlockPos const* pos, BlockSource const* bs); + static Local newBlock(IntVec4 pos); + static Block* extract(Local v); + Local asPointer(const Arguments& args); - Local getName(); - Local getType(); - Local getId(); - Local getPos(); - Local getTileData(); - Local getVariant(); - Local getTranslucency(); - Local getThickness(); + Local getName(); + Local getType(); + Local getId(); + Local getPos(); + Local getTileData(); + Local getVariant(); + Local getTranslucency(); + Local getThickness(); - Local isAir(); - Local isBounceBlock(); - Local isButtonBlock(); - Local isCropBlock(); - Local isDoorBlock(); - Local isFenceBlock(); - Local isFenceGateBlock(); - Local isThinFenceBlock(); - Local isHeavyBlock(); - Local isStemBlock(); - Local isSlabBlock(); - Local isUnbreakable(); - Local isWaterBlockingBlock(); + Local isAir(); + Local isBounceBlock(); + Local isButtonBlock(); + Local isCropBlock(); + Local isDoorBlock(); + Local isFenceBlock(); + Local isFenceGateBlock(); + Local isThinFenceBlock(); + Local isHeavyBlock(); + Local isStemBlock(); + Local isSlabBlock(); + Local isUnbreakable(); + Local isWaterBlockingBlock(); - Local getNbt(const Arguments &args); - Local setNbt(const Arguments &args); - Local getBlockState(const Arguments &args); - Local hasContainer(const Arguments &args); - Local getContainer(const Arguments &args); - Local hasBlockEntity(const Arguments &args); - Local getBlockEntity(const Arguments &args); - Local removeBlockEntity(const Arguments &args); - Local destroyBlock(const Arguments &args); + Local getNbt(const Arguments& args); + Local setNbt(const Arguments& args); + Local getBlockState(const Arguments& args); + Local hasContainer(const Arguments& args); + Local getContainer(const Arguments& args); + Local hasBlockEntity(const Arguments& args); + Local getBlockEntity(const Arguments& args); + Local removeBlockEntity(const Arguments& args); + Local destroyBlock(const Arguments& args); }; -extern ClassDefine BlockClassBuilder; \ No newline at end of file +extern ClassDefine BlockClassBuilder; diff --git a/src/api/BlockEntityAPI.cpp b/src/api/BlockEntityAPI.cpp index e80080ad..d363947f 100644 --- a/src/api/BlockEntityAPI.cpp +++ b/src/api/BlockEntityAPI.cpp @@ -6,7 +6,7 @@ #include "api/NbtAPI.h" #include "ll/api/memory/Memory.h" #include "ll/api/service/Bedrock.h" -#include "main/Global.hpp" +#include "main/Global.h" #include "mc/dataloadhelper/DataLoadHelper.h" #include "mc/dataloadhelper/DefaultDataLoadHelper.h" #include "mc/nbt/CompoundTag.h" @@ -17,102 +17,94 @@ //////////////////// Class Definition //////////////////// -ClassDefine BlockEntityClassBuilder = - defineClass("LLSE_BlockEntity") - .constructor(nullptr) - .instanceFunction("asPointer", &BlockEntityClass::asPointer) +ClassDefine BlockEntityClassBuilder = defineClass("LLSE_BlockEntity") + .constructor(nullptr) + .instanceFunction("asPointer", &BlockEntityClass::asPointer) - .instanceProperty("name", &BlockEntityClass::getName) - .instanceProperty("pos", &BlockEntityClass::getPos) - .instanceProperty("type", &BlockEntityClass::getType) + .instanceProperty("name", &BlockEntityClass::getName) + .instanceProperty("pos", &BlockEntityClass::getPos) + .instanceProperty("type", &BlockEntityClass::getType) - .instanceFunction("setNbt", &BlockEntityClass::setNbt) - .instanceFunction("getNbt", &BlockEntityClass::getNbt) - .instanceFunction("getBlock", &BlockEntityClass::getBlock) - .build(); + .instanceFunction("setNbt", &BlockEntityClass::setNbt) + .instanceFunction("getNbt", &BlockEntityClass::getNbt) + .instanceFunction("getBlock", &BlockEntityClass::getBlock) + .build(); //////////////////// Classes //////////////////// -BlockEntityClass::BlockEntityClass(BlockActor *be, int dim) - : ScriptClass(ScriptClass::ConstructFromCpp{}), - blockEntity(be), dim(dim) {} +BlockEntityClass::BlockEntityClass(BlockActor* be, int dim) +: ScriptClass(ScriptClass::ConstructFromCpp{}), + blockEntity(be), + dim(dim) {} -Local BlockEntityClass::newBlockEntity(BlockActor *be, int dim) { - auto newp = new BlockEntityClass(be, dim); - return newp->getScriptObject(); +Local BlockEntityClass::newBlockEntity(BlockActor* be, int dim) { + auto newp = new BlockEntityClass(be, dim); + return newp->getScriptObject(); } // 生成函数 -BlockActor *BlockEntityClass::extract(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine() - ->getNativeInstance(v) - ->get(); - else - return nullptr; +BlockActor* BlockEntityClass::extract(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v)->get(); + else return nullptr; } // 成员函数 -Local BlockEntityClass::asPointer(const Arguments &args) { - try { - return NativePointer::newNativePointer(blockEntity); - } - CATCH("Fail in asPointer!") +Local BlockEntityClass::asPointer(const Arguments& args) { + try { + return NativePointer::newNativePointer(blockEntity); + } + CATCH("Fail in asPointer!") } Local BlockEntityClass::getPos() { - try { - return IntPos::newPos(blockEntity->getPosition(), dim); - } - CATCH("Fail in getBlockEntityPos!") + try { + return IntPos::newPos(blockEntity->getPosition(), dim); + } + CATCH("Fail in getBlockEntityPos!") } Local BlockEntityClass::getName() { - try { - return String::newString(blockEntity->getName()); - } - CATCH("Fail in getName!") + try { + return String::newString(blockEntity->getName()); + } + CATCH("Fail in getName!") } Local BlockEntityClass::getType() { - try { - return Number::newNumber((int)blockEntity->getType()); - } - CATCH("Fail in getBlockEntityType!") + try { + return Number::newNumber((int)blockEntity->getType()); + } + CATCH("Fail in getBlockEntityType!") } -Local BlockEntityClass::getNbt(const Arguments &args) { - try { - CompoundTag tag; - blockEntity->save(tag); - return NbtCompoundClass::pack( - &tag); // Not sure is that will get right value - } - CATCH("Fail in getNbt!") +Local BlockEntityClass::getNbt(const Arguments& args) { + try { + CompoundTag tag; + blockEntity->save(tag); + return NbtCompoundClass::pack(&tag); // Not sure is that will get right value + } + CATCH("Fail in getNbt!") } -Local BlockEntityClass::setNbt(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - - try { - auto nbt = NbtCompoundClass::extract(args[0]); - if (!nbt) - return Local(); // Null - void *helper = LL_RESOLVE_SYMBOL("??_7DefaultDataLoadHelper@@6B@"); - blockEntity->load(*ll::service::getLevel(), *nbt, (DataLoadHelper &)helper); - return Boolean::newBoolean(true); - } - CATCH("Fail in setNbt!") +Local BlockEntityClass::setNbt(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + + try { + auto nbt = NbtCompoundClass::extract(args[0]); + if (!nbt) return Local(); // Null + void* helper = LL_RESOLVE_SYMBOL("??_7DefaultDataLoadHelper@@6B@"); + blockEntity->load(*ll::service::getLevel(), *nbt, (DataLoadHelper&)helper); + return Boolean::newBoolean(true); + } + CATCH("Fail in setNbt!") } -Local BlockEntityClass::getBlock(const Arguments &args) { - try { - BlockPos bp = blockEntity->getPosition(); - Block bl = ll::service::getLevel() - ->getDimension(dim) - ->getBlockSourceFromMainChunkSource() - .getBlock(bp); - return BlockClass::newBlock(&bl, &bp, dim); - } - CATCH("Fail in getBlock!") -} \ No newline at end of file +Local BlockEntityClass::getBlock(const Arguments& args) { + try { + BlockPos bp = blockEntity->getPosition(); + Block bl = ll::service::getLevel()->getDimension(dim)->getBlockSourceFromMainChunkSource().getBlock(bp); + return BlockClass::newBlock(&bl, &bp, dim); + } + CATCH("Fail in getBlock!") +} diff --git a/src/api/BlockEntityAPI.h b/src/api/BlockEntityAPI.h index f1fbc327..cba8afde 100644 --- a/src/api/BlockEntityAPI.h +++ b/src/api/BlockEntityAPI.h @@ -8,18 +8,16 @@ class BlockActor; class BlockEntityClass : public ScriptClass { private: BlockActor* blockEntity; - int dim; + int dim; public: explicit BlockEntityClass(BlockActor* be, int dim); - BlockActor* get() { - return blockEntity; - } + BlockActor* get() { return blockEntity; } static Local newBlockEntity(BlockActor* be, int dim); - static BlockActor* extract(Local v); - Local asPointer(const Arguments& args); + static BlockActor* extract(Local v); + Local asPointer(const Arguments& args); Local getName(); Local getPos(); diff --git a/src/api/CommandAPI.cpp b/src/api/CommandAPI.cpp index 026820ed..225f3ee3 100644 --- a/src/api/CommandAPI.cpp +++ b/src/api/CommandAPI.cpp @@ -38,12 +38,9 @@ //////////////////// Class Definition //////////////////// -ClassDefine PermissionStaticBuilder = - EnumDefineBuilder::build("PermType"); -ClassDefine ParamTypeStaticBuilder = - EnumDefineBuilder::build("ParamType"); -ClassDefine ParamOptionStaticBuilder = - EnumDefineBuilder::build("ParamOption"); +ClassDefine PermissionStaticBuilder = EnumDefineBuilder::build("PermType"); +ClassDefine ParamTypeStaticBuilder = EnumDefineBuilder::build("ParamType"); +ClassDefine ParamOptionStaticBuilder = EnumDefineBuilder::build("ParamOption"); ClassDefine CommandClassBuilder = defineClass("LLSE_Command") @@ -58,8 +55,7 @@ ClassDefine CommandClassBuilder = .instanceFunction("optional", &CommandClass::optional) .instanceFunction("setSoftEnum", &CommandClass::setSoftEnum) .instanceFunction("addSoftEnumValues", &CommandClass::addSoftEnumValues) - .instanceFunction("removeSoftEnumValues", - &CommandClass::removeSoftEnumValues) + .instanceFunction("removeSoftEnumValues", &CommandClass::removeSoftEnumValues) .instanceFunction("getSoftEnumValues", &CommandClass::getSoftEnumValues) .instanceFunction("getSoftEnumNames", &CommandClass::getSoftEnumNames) .instanceFunction("overload", &CommandClass::addOverload) @@ -70,545 +66,500 @@ ClassDefine CommandClassBuilder = //////////////////// Helper //////////////////// -bool LLSERemoveCmdCallback(script::ScriptEngine *engine) { - erase_if(localShareData->commandCallbacks, - [&engine](auto &data) { return data.second.fromEngine == engine; }); - return true; +bool LLSERemoveCmdCallback(script::ScriptEngine* engine) { + erase_if(localShareData->commandCallbacks, [&engine](auto& data) { return data.second.fromEngine == engine; }); + return true; } -Local convertResult(DynamicCommand::Result const &result) { - if (!result.isSet) - return Local(); // null - switch (result.type) { - case DynamicCommand::ParameterType::Bool: - return Boolean::newBoolean(result.getRaw()); - case DynamicCommand::ParameterType::Int: - return Number::newNumber(result.getRaw()); - case DynamicCommand::ParameterType::Float: - return Number::newNumber(result.getRaw()); - case DynamicCommand::ParameterType::String: - return String::newString(result.getRaw()); - case DynamicCommand::ParameterType::Actor: { - auto arr = Array::newArray(); - for (auto i : result.get>()) { - arr.add(EntityClass::newEntity(i)); +Local convertResult(DynamicCommand::Result const& result) { + if (!result.isSet) return Local(); // null + switch (result.type) { + case DynamicCommand::ParameterType::Bool: + return Boolean::newBoolean(result.getRaw()); + case DynamicCommand::ParameterType::Int: + return Number::newNumber(result.getRaw()); + case DynamicCommand::ParameterType::Float: + return Number::newNumber(result.getRaw()); + case DynamicCommand::ParameterType::String: + return String::newString(result.getRaw()); + case DynamicCommand::ParameterType::Actor: { + auto arr = Array::newArray(); + for (auto i : result.get>()) { + arr.add(EntityClass::newEntity(i)); + } + return arr; + } + case DynamicCommand::ParameterType::Player: { + auto arr = Array::newArray(); + for (auto i : result.get>()) { + arr.add(PlayerClass::newPlayer(i)); + } + return arr; + } + case DynamicCommand::ParameterType::BlockPos: { + auto dim = result.origin->getDimension(); + return IntPos::newPos(result.get(), dim ? (int)dim->getDimensionId() : -1); + } + case DynamicCommand::ParameterType::Vec3: { + auto dim = result.origin->getDimension(); + return FloatPos::newPos(result.get(), dim ? (int)dim->getDimensionId() : -1); } - return arr; - } - case DynamicCommand::ParameterType::Player: { - auto arr = Array::newArray(); - for (auto i : result.get>()) { - arr.add(PlayerClass::newPlayer(i)); + case DynamicCommand::ParameterType::Message: + return String::newString(result.getRaw().getMessage(*result.origin)); + case DynamicCommand::ParameterType::RawText: + return String::newString(result.getRaw()); + case DynamicCommand::ParameterType::JsonValue: + return String::newString(JsonHelpers::serialize(result.getRaw())); + case DynamicCommand::ParameterType::Item: + return ItemClass::newItem( + new ItemStack(result.getRaw() + .createInstance(1, 1, *new CommandOutput(CommandOutputType::None), true) + .value_or(ItemInstance::EMPTY_ITEM)) + ); + case DynamicCommand::ParameterType::Block: + return BlockClass::newBlock( + const_cast(result.getRaw().resolveBlock(0).getBlock()), + const_cast(&BlockPos::MIN), + -1 + ); + case DynamicCommand::ParameterType::Effect: + return String::newString(result.getRaw()->getResourceName()); + case DynamicCommand::ParameterType::Enum: + return String::newString(result.getRaw()); + case DynamicCommand::ParameterType::SoftEnum: + return String::newString(result.getRaw()); + case DynamicCommand::ParameterType::Command: + return String::newString(result.getRaw>()->getCommandName()); + case DynamicCommand::ParameterType::ActorType: + return String::newString(result.getRaw()->getCanonicalName()); + default: + return Local(); // null + break; } - return arr; - } - case DynamicCommand::ParameterType::BlockPos: { - auto dim = result.origin->getDimension(); - return IntPos::newPos(result.get(), - dim ? (int)dim->getDimensionId() : -1); - } - case DynamicCommand::ParameterType::Vec3: { - auto dim = result.origin->getDimension(); - return FloatPos::newPos(result.get(), - dim ? (int)dim->getDimensionId() : -1); - } - case DynamicCommand::ParameterType::Message: - return String::newString( - result.getRaw().getMessage(*result.origin)); - case DynamicCommand::ParameterType::RawText: - return String::newString(result.getRaw()); - case DynamicCommand::ParameterType::JsonValue: - return String::newString( - JsonHelpers::serialize(result.getRaw())); - case DynamicCommand::ParameterType::Item: - return ItemClass::newItem(new ItemStack( - result.getRaw() - .createInstance(1, 1, *new CommandOutput(CommandOutputType::None), - true) - .value_or(ItemInstance::EMPTY_ITEM))); - case DynamicCommand::ParameterType::Block: - return BlockClass::newBlock( - const_cast( - result.getRaw().resolveBlock(0).getBlock()), - const_cast(&BlockPos::MIN), -1); - case DynamicCommand::ParameterType::Effect: - return String::newString( - result.getRaw()->getResourceName()); - case DynamicCommand::ParameterType::Enum: - return String::newString(result.getRaw()); - case DynamicCommand::ParameterType::SoftEnum: - return String::newString(result.getRaw()); - case DynamicCommand::ParameterType::Command: - return String::newString( - result.getRaw>()->getCommandName()); - case DynamicCommand::ParameterType::ActorType: - return String::newString( - result.getRaw()->getCanonicalName()); - default: - return Local(); // null - break; - } } template -std::enable_if_t, T> parseEnum(Local const &value) { - if (value.isString()) { - auto tmp = magic_enum::enum_cast(value.toStr()); - if (!tmp.has_value()) - throw std::runtime_error("Unable to parse Enum value"); - return tmp.value(); - } else if (value.isNumber()) { - return (T)value.toInt(); - } - throw std::runtime_error("Unable to parse Enum value"); +std::enable_if_t, T> parseEnum(Local const& value) { + if (value.isString()) { + auto tmp = magic_enum::enum_cast(value.toStr()); + if (!tmp.has_value()) throw std::runtime_error("Unable to parse Enum value"); + return tmp.value(); + } else if (value.isNumber()) { + return (T)value.toInt(); + } + throw std::runtime_error("Unable to parse Enum value"); } //////////////////// MC APIs //////////////////// -Local McClass::runcmd(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - CHECK_ARG_TYPE(args[0], ValueKind::kString) - CommandContext context = - CommandContext(args[0].asString().toString(), - std::make_unique(ServerCommandOrigin( - "Server", ll::service::getLevel()->asServer(), - CommandPermissionLevel::Internal, 0))); - try { - return Boolean::newBoolean( - ll::service::getMinecraft()->getCommands().executeCommand(context, - true)); - } - CATCH("Fail in RunCmd!") +Local McClass::runcmd(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + CHECK_ARG_TYPE(args[0], ValueKind::kString) + CommandContext context = CommandContext( + args[0].asString().toString(), + std::make_unique( + ServerCommandOrigin("Server", ll::service::getLevel()->asServer(), CommandPermissionLevel::Internal, 0) + ) + ); + try { + return Boolean::newBoolean(ll::service::getMinecraft()->getCommands().executeCommand(context, true)); + } + CATCH("Fail in RunCmd!") } -Local McClass::runcmdEx(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - CHECK_ARG_TYPE(args[0], ValueKind::kString) - CommandContext context = - CommandContext(args[0].asString().toString(), - std::make_unique(ServerCommandOrigin( - "Server", ll::service::getLevel()->asServer(), - CommandPermissionLevel::Internal, 0))); - try { - MCRESULT result = ll::service::getMinecraft()->getCommands().executeCommand( - context, false); - Local resObj = Object::newObject(); - resObj.set("success", result.isSuccess()); - resObj.set("output", {}); - return resObj; - } - CATCH("Fail in RunCmdEx!") +Local McClass::runcmdEx(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + CHECK_ARG_TYPE(args[0], ValueKind::kString) + CommandContext context = CommandContext( + args[0].asString().toString(), + std::make_unique( + ServerCommandOrigin("Server", ll::service::getLevel()->asServer(), CommandPermissionLevel::Internal, 0) + ) + ); + try { + MCRESULT result = ll::service::getMinecraft()->getCommands().executeCommand(context, false); + Local resObj = Object::newObject(); + resObj.set("success", result.isSuccess()); + resObj.set("output", {}); + return resObj; + } + CATCH("Fail in RunCmdEx!") } // name, description, permission, flag, alias -Local McClass::newCommand(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - - try { - auto name = args[0].toStr(); - auto instance = DynamicCommand::getInstance(name); - if (instance) { - logger.info("Dynamic command {} already exists, changes will not be " - "applied except for setOverload!", - name); - return CommandClass::newCommand( - const_cast>>>( - instance)); - } +Local McClass::newCommand(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + + try { + auto name = args[0].toStr(); + auto instance = DynamicCommand::getInstance(name); + if (instance) { + logger.info( + "Dynamic command {} already exists, changes will not be " + "applied except for setOverload!", + name + ); + return CommandClass::newCommand( + const_cast>>>(instance) + ); + } - auto desc = args[1].toStr(); - CommandPermissionLevel permission = CommandPermissionLevel::Admin; - CommandFlag flag = {(CommandFlagValue)0x80}; - std::string alias = ""; - if (args.size() > 2) { - permission = parseEnum(args[2]); - if (args.size() > 3) { - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - flag = {(CommandFlagValue)args[3].toInt()}; - if (args.size() > 4) { - CHECK_ARG_TYPE(args[4], ValueKind::kString); - alias = args[4].toStr(); + auto desc = args[1].toStr(); + CommandPermissionLevel permission = CommandPermissionLevel::Admin; + CommandFlag flag = {(CommandFlagValue)0x80}; + std::string alias = ""; + if (args.size() > 2) { + permission = parseEnum(args[2]); + if (args.size() > 3) { + CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + flag = {(CommandFlagValue)args[3].toInt()}; + if (args.size() > 4) { + CHECK_ARG_TYPE(args[4], ValueKind::kString); + alias = args[4].toStr(); + } + } + } + auto command = DynamicCommand::createCommand(ll::service::getCommandRegistry(), name, desc, permission, flag); + if (command) { + if (!alias.empty()) command->setAlias(alias); + return CommandClass::newCommand(std::move(command)); + } else { + return Boolean::newBoolean(false); } - } - } - auto command = DynamicCommand::createCommand( - ll::service::getCommandRegistry(), name, desc, permission, flag); - if (command) { - if (!alias.empty()) - command->setAlias(alias); - return CommandClass::newCommand(std::move(command)); - } else { - return Boolean::newBoolean(false); } - } - CATCH("Fail in newCommand!") + CATCH("Fail in newCommand!") } //////////////////// Command APIs //////////////////// -CommandClass::CommandClass(std::unique_ptr &&p) - : ScriptClass(ScriptClass::ConstructFromCpp{}), - uptr(std::move(p)), ptr(uptr.get()), registered(false){}; - -CommandClass::CommandClass(DynamicCommandInstance *p) - : ScriptClass(ScriptClass::ConstructFromCpp{}), uptr(), - ptr(p), registered(true){}; - -Local -CommandClass::newCommand(std::unique_ptr &&p) { - auto newp = new CommandClass(std::move(p)); - return newp->getScriptObject(); +CommandClass::CommandClass(std::unique_ptr&& p) +: ScriptClass(ScriptClass::ConstructFromCpp{}), + uptr(std::move(p)), + ptr(uptr.get()), + registered(false){}; + +CommandClass::CommandClass(DynamicCommandInstance* p) +: ScriptClass(ScriptClass::ConstructFromCpp{}), + uptr(), + ptr(p), + registered(true){}; + +Local CommandClass::newCommand(std::unique_ptr&& p) { + auto newp = new CommandClass(std::move(p)); + return newp->getScriptObject(); } -Local CommandClass::newCommand(DynamicCommandInstance *p) { - auto newp = new CommandClass(p); - return newp->getScriptObject(); +Local CommandClass::newCommand(DynamicCommandInstance* p) { + auto newp = new CommandClass(p); + return newp->getScriptObject(); } Local CommandClass::getName() { - try { - return String::newString(get()->getCommandName()); - } - CATCH("Fail in getCommandName!") + try { + return String::newString(get()->getCommandName()); + } + CATCH("Fail in getCommandName!") } -Local CommandClass::setAlias(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - CHECK_ARG_TYPE(args[0], ValueKind::kString) - try { - if (registered) - return Boolean::newBoolean(true); // TODO - return Boolean::newBoolean(get()->setAlias(args[0].toStr())); - } - CATCH("Fail in setAlias!") +Local CommandClass::setAlias(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + CHECK_ARG_TYPE(args[0], ValueKind::kString) + try { + if (registered) return Boolean::newBoolean(true); // TODO + return Boolean::newBoolean(get()->setAlias(args[0].toStr())); + } + CATCH("Fail in setAlias!") } // string, vector -Local CommandClass::setEnum(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2) - CHECK_ARG_TYPE(args[0], ValueKind::kString) - CHECK_ARG_TYPE(args[1], ValueKind::kArray) - try { - if (registered) - return Local(); // TODO - auto enumName = args[0].toStr(); - auto enumArr = args[1].asArray(); - if (enumArr.size() == 0 || !enumArr.get(0).isString()) - return Local(); - vector enumValues; - for (int i = 0; i < enumArr.size(); ++i) { - enumValues.push_back(enumArr.get(i).toStr()); +Local CommandClass::setEnum(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2) + CHECK_ARG_TYPE(args[0], ValueKind::kString) + CHECK_ARG_TYPE(args[1], ValueKind::kArray) + try { + if (registered) return Local(); // TODO + auto enumName = args[0].toStr(); + auto enumArr = args[1].asArray(); + if (enumArr.size() == 0 || !enumArr.get(0).isString()) return Local(); + vector enumValues; + for (int i = 0; i < enumArr.size(); ++i) { + enumValues.push_back(enumArr.get(i).toStr()); + } + return String::newString(get()->setEnum(enumName, std::move(enumValues))); } - return String::newString(get()->setEnum(enumName, std::move(enumValues))); - } - CATCH("Fail in setEnum!") + CATCH("Fail in setEnum!") } // name, type, optional, description, identifier, option // name, type, description, identifier, option // name, type, optional, description, option // name, type, description, option -Local CommandClass::newParameter(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - if (registered) - return Boolean::newBoolean(true); // TODO - auto name = args[0].toStr(); - DynamicCommand::ParameterType type = - parseEnum(args[1]); - std::string description = ""; - bool optional = false; - std::string identifier = ""; - size_t index = 2; - CommandParameterOption option = (CommandParameterOption)0; - if (args.size() > index && args[index].isBoolean()) - optional = args[index++].asBoolean().value(); - if (args.size() > index && args[index].isString()) - description = args[index++].toStr(); - if (args.size() > index && args[index].isString()) - identifier = args[index++].toStr(); - if (args.size() > index && args[index].isNumber()) - option = (CommandParameterOption)args[index++].toInt(); - if (index != args.size()) - throw std::runtime_error("Error Argument in newParameter"); - return Number::newNumber((int64_t)get() - ->newParameter(name, type, optional, - description, identifier, option) - .index); - } - CATCH("Fail in newParameter!") +Local CommandClass::newParameter(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + try { + if (registered) return Boolean::newBoolean(true); // TODO + auto name = args[0].toStr(); + DynamicCommand::ParameterType type = parseEnum(args[1]); + std::string description = ""; + bool optional = false; + std::string identifier = ""; + size_t index = 2; + CommandParameterOption option = (CommandParameterOption)0; + if (args.size() > index && args[index].isBoolean()) optional = args[index++].asBoolean().value(); + if (args.size() > index && args[index].isString()) description = args[index++].toStr(); + if (args.size() > index && args[index].isString()) identifier = args[index++].toStr(); + if (args.size() > index && args[index].isNumber()) option = (CommandParameterOption)args[index++].toInt(); + if (index != args.size()) throw std::runtime_error("Error Argument in newParameter"); + return Number::newNumber( + (int64_t)get()->newParameter(name, type, optional, description, identifier, option).index + ); + } + CATCH("Fail in newParameter!") } // name, type, description, identifier, option // name, type, description, option -Local CommandClass::mandatory(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - if (registered) - return Boolean::newBoolean(true); // TODO - auto name = args[0].toStr(); - DynamicCommand::ParameterType type = - parseEnum(args[1]); - std::string description = ""; - bool optional = false; - std::string identifier = ""; - size_t index = 2; - CommandParameterOption option = (CommandParameterOption)0; - if (args.size() > index && args[index].isString()) - description = args[index++].toStr(); - if (args.size() > index && args[index].isString()) - identifier = args[index++].toStr(); - if (args.size() > index && args[index].isNumber()) - option = (CommandParameterOption)args[index++].toInt(); - if (index != args.size()) - throw std::runtime_error("Error Argument in newParameter"); - return Number::newNumber((int64_t)get() - ->newParameter(name, type, optional, - description, identifier, option) - .index); - } - CATCH("Fail in newParameter!") +Local CommandClass::mandatory(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + try { + if (registered) return Boolean::newBoolean(true); // TODO + auto name = args[0].toStr(); + DynamicCommand::ParameterType type = parseEnum(args[1]); + std::string description = ""; + bool optional = false; + std::string identifier = ""; + size_t index = 2; + CommandParameterOption option = (CommandParameterOption)0; + if (args.size() > index && args[index].isString()) description = args[index++].toStr(); + if (args.size() > index && args[index].isString()) identifier = args[index++].toStr(); + if (args.size() > index && args[index].isNumber()) option = (CommandParameterOption)args[index++].toInt(); + if (index != args.size()) throw std::runtime_error("Error Argument in newParameter"); + return Number::newNumber( + (int64_t)get()->newParameter(name, type, optional, description, identifier, option).index + ); + } + CATCH("Fail in newParameter!") } // name, type, description, identifier, option // name, type, description, option -Local CommandClass::optional(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - if (registered) - return Boolean::newBoolean(true); // TODO - auto name = args[0].toStr(); - DynamicCommand::ParameterType type = - parseEnum(args[1]); - std::string description = ""; - bool optional = true; - std::string identifier = ""; - size_t index = 2; - CommandParameterOption option = (CommandParameterOption)0; - if (args.size() > index && args[index].isString()) - description = args[index++].toStr(); - if (args.size() > index && args[index].isString()) - identifier = args[index++].toStr(); - if (args.size() > index && args[index].isNumber()) - option = (CommandParameterOption)args[index++].toInt(); - if (index != args.size()) - throw std::runtime_error("Error Argument in newParameter"); - return Number::newNumber((int64_t)get() - ->newParameter(name, type, optional, - description, identifier, option) - .index); - } - CATCH("Fail in newParameter!") +Local CommandClass::optional(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + try { + if (registered) return Boolean::newBoolean(true); // TODO + auto name = args[0].toStr(); + DynamicCommand::ParameterType type = parseEnum(args[1]); + std::string description = ""; + bool optional = true; + std::string identifier = ""; + size_t index = 2; + CommandParameterOption option = (CommandParameterOption)0; + if (args.size() > index && args[index].isString()) description = args[index++].toStr(); + if (args.size() > index && args[index].isString()) identifier = args[index++].toStr(); + if (args.size() > index && args[index].isNumber()) option = (CommandParameterOption)args[index++].toInt(); + if (index != args.size()) throw std::runtime_error("Error Argument in newParameter"); + return Number::newNumber( + (int64_t)get()->newParameter(name, type, optional, description, identifier, option).index + ); + } + CATCH("Fail in newParameter!") } // vector // vector -Local CommandClass::addOverload(const Arguments &args) { - try { - if (registered) - return Boolean::newBoolean(true); // TODO - auto command = get(); - if (args.size() == 0) - return Boolean::newBoolean(command->addOverload( - std::vector{})); - if (args[0].isNumber()) { - std::vector params; - for (int i = 0; i < args.size(); ++i) { - CHECK_ARG_TYPE(args[i], ValueKind::kNumber); - params.emplace_back(command, (size_t)args[i].asNumber().toInt64()); - } - return Boolean::newBoolean(command->addOverload(std::move(params))); - } else if (args[0].isString()) { - std::vector params; - for (int i = 0; i < args.size(); ++i) { - CHECK_ARG_TYPE(args[i], ValueKind::kString); - params.emplace_back(args[i].toStr()); - } - return Boolean::newBoolean(command->addOverload(std::move(params))); - } else if (args[0].isArray()) { - auto arr = args[0].asArray(); - if (arr.size() == 0) - return Boolean::newBoolean(command->addOverload( - std::vector{})); - if (arr.get(0).isNumber()) { - std::vector params; - for (int i = 0; i < arr.size(); ++i) { - CHECK_ARG_TYPE(arr.get(i), ValueKind::kNumber); - params.emplace_back(command, (size_t)arr.get(i).asNumber().toInt64()); +Local CommandClass::addOverload(const Arguments& args) { + try { + if (registered) return Boolean::newBoolean(true); // TODO + auto command = get(); + if (args.size() == 0) + return Boolean::newBoolean(command->addOverload(std::vector{})); + if (args[0].isNumber()) { + std::vector params; + for (int i = 0; i < args.size(); ++i) { + CHECK_ARG_TYPE(args[i], ValueKind::kNumber); + params.emplace_back(command, (size_t)args[i].asNumber().toInt64()); + } + return Boolean::newBoolean(command->addOverload(std::move(params))); + } else if (args[0].isString()) { + std::vector params; + for (int i = 0; i < args.size(); ++i) { + CHECK_ARG_TYPE(args[i], ValueKind::kString); + params.emplace_back(args[i].toStr()); + } + return Boolean::newBoolean(command->addOverload(std::move(params))); + } else if (args[0].isArray()) { + auto arr = args[0].asArray(); + if (arr.size() == 0) + return Boolean::newBoolean(command->addOverload(std::vector{})); + if (arr.get(0).isNumber()) { + std::vector params; + for (int i = 0; i < arr.size(); ++i) { + CHECK_ARG_TYPE(arr.get(i), ValueKind::kNumber); + params.emplace_back(command, (size_t)arr.get(i).asNumber().toInt64()); + } + return Boolean::newBoolean(command->addOverload(std::move(params))); + } else if (arr.get(0).isString()) { + std::vector params; + for (int i = 0; i < arr.size(); ++i) { + CHECK_ARG_TYPE(arr.get(i), ValueKind::kString); + params.emplace_back(arr.get(i).toStr()); + } + return Boolean::newBoolean(command->addOverload(std::move(params))); + } } - return Boolean::newBoolean(command->addOverload(std::move(params))); - } else if (arr.get(0).isString()) { - std::vector params; - for (int i = 0; i < arr.size(); ++i) { - CHECK_ARG_TYPE(arr.get(i), ValueKind::kString); - params.emplace_back(arr.get(i).toStr()); - } - return Boolean::newBoolean(command->addOverload(std::move(params))); - } + LOG_WRONG_ARG_TYPE(); + return Local(); } - LOG_WRONG_ARG_TYPE(); - return Local(); - } - CATCH("Fail in addOverload!") + CATCH("Fail in addOverload!") } void onExecute( - DynamicCommand const &command, CommandOrigin const &origin, - CommandOutput &output, - std::unordered_map &results) { - auto instance = command.getInstance(); - auto &commandName = instance->getCommandName(); - if (localShareData->commandCallbacks.find(commandName) == - localShareData->commandCallbacks.end()) { - logger.warn("Command {} failed to execute, is the plugin unloaded?", - commandName); - return; - } - EngineScope enter(localShareData->commandCallbacks[commandName].fromEngine); - try { - Local args = Object::newObject(); - auto cmd = CommandClass::newCommand( - const_cast(instance)); - auto ori = CommandOriginClass::newCommandOrigin(&origin); - auto outp = CommandOutputClass::newCommandOutput(&output); - for (auto &[name, param] : results) - args.set(name, convertResult(param)); - localShareData->commandCallbacks[commandName].func.get().call({}, cmd, ori, - outp, args); - } - CATCH_WITHOUT_RETURN("Fail in executing command \"" + commandName + "\"!") + DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results +) { + auto instance = command.getInstance(); + auto& commandName = instance->getCommandName(); + if (localShareData->commandCallbacks.find(commandName) == localShareData->commandCallbacks.end()) { + logger.warn("Command {} failed to execute, is the plugin unloaded?", commandName); + return; + } + EngineScope enter(localShareData->commandCallbacks[commandName].fromEngine); + try { + Local args = Object::newObject(); + auto cmd = CommandClass::newCommand(const_cast(instance)); + auto ori = CommandOriginClass::newCommandOrigin(&origin); + auto outp = CommandOutputClass::newCommandOutput(&output); + for (auto& [name, param] : results) args.set(name, convertResult(param)); + localShareData->commandCallbacks[commandName].func.get().call({}, cmd, ori, outp, args); + } + CATCH_WITHOUT_RETURN("Fail in executing command \"" + commandName + "\"!") } // not complete void onExecute2( - DynamicCommand const &command, CommandOrigin const &origin, - CommandOutput &output, - std::unordered_map &results) { - auto instance = command.getInstance(); - auto &commandName = instance->getCommandName(); - if (localShareData->commandCallbacks.find(commandName) == - localShareData->commandCallbacks.end()) { - logger.warn("Command {} failed to execute, is the plugin unloaded?", - commandName); - return; - } - EngineScope enter(localShareData->commandCallbacks[commandName].fromEngine); - try { - // auto ctx = CommandContextClass::newCommandContext(&command, &origin, - // &output, &results); Local args = Object::newObject(); for (auto& - // [name, param] : results) - // args.set(name, convertResult(param)); - // localShareData->commandCallbacks[commandName].func.get().call({}, ctx, - // args); - } - CATCH_WITHOUT_RETURN("Fail in executing command \"" + commandName + "\"!") + DynamicCommand const& command, + CommandOrigin const& origin, + CommandOutput& output, + std::unordered_map& results +) { + auto instance = command.getInstance(); + auto& commandName = instance->getCommandName(); + if (localShareData->commandCallbacks.find(commandName) == localShareData->commandCallbacks.end()) { + logger.warn("Command {} failed to execute, is the plugin unloaded?", commandName); + return; + } + EngineScope enter(localShareData->commandCallbacks[commandName].fromEngine); + try { + // auto ctx = CommandContextClass::newCommandContext(&command, &origin, + // &output, &results); Local args = Object::newObject(); for (auto& + // [name, param] : results) + // args.set(name, convertResult(param)); + // localShareData->commandCallbacks[commandName].func.get().call({}, ctx, + // args); + } + CATCH_WITHOUT_RETURN("Fail in executing command \"" + commandName + "\"!") } // function (command, origin, output, results){} -Local CommandClass::setCallback(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kFunction); - try { - auto func = args[0].asFunction(); - DynamicCommandInstance *command = get(); - auto &commandName = command->getCommandName(); - localShareData->commandCallbacks[commandName] = { - EngineScope::currentEngine(), 0, script::Global(func)}; - if (registered) - return Boolean::newBoolean(true); - get()->setCallback(onExecute); - return Boolean::newBoolean(true); - } - CATCH("Fail in setCallback!") +Local CommandClass::setCallback(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kFunction); + try { + auto func = args[0].asFunction(); + DynamicCommandInstance* command = get(); + auto& commandName = command->getCommandName(); + localShareData->commandCallbacks[commandName] = { + EngineScope::currentEngine(), + 0, + script::Global(func)}; + if (registered) return Boolean::newBoolean(true); + get()->setCallback(onExecute); + return Boolean::newBoolean(true); + } + CATCH("Fail in setCallback!") } // setup(Function>) -Local CommandClass::setup(const Arguments &args) { - try { - if (args.size() > 0) { - setCallback(args); +Local CommandClass::setup(const Arguments& args) { + try { + if (args.size() > 0) { + setCallback(args); + } + if (registered) return Boolean::newBoolean(true); + return Boolean::newBoolean(DynamicCommand::setup(ll::service::getCommandRegistry(), std::move(uptr))); } - if (registered) - return Boolean::newBoolean(true); - return Boolean::newBoolean(DynamicCommand::setup( - ll::service::getCommandRegistry(), std::move(uptr))); - } - CATCH("Fail in setup!") + CATCH("Fail in setup!") } -Local CommandClass::isRegistered() { - return Boolean::newBoolean(registered); -} +Local CommandClass::isRegistered() { return Boolean::newBoolean(registered); } -Local CommandClass::toString(const Arguments &args) { - try { - return String::newString( - fmt::format("", get()->getCommandName())); - } - CATCH("Fail in toString!"); +Local CommandClass::toString(const Arguments& args) { + try { + return String::newString(fmt::format("", get()->getCommandName())); + } + CATCH("Fail in toString!"); } -Local CommandClass::setSoftEnum(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kArray); - try { - auto name = args[0].toStr(); - auto enums = parseStringList(args[1].asArray()); - return String::newString(get()->setSoftEnum(name, std::move(enums))); - } - CATCH("Fail in setSoftEnum!"); +Local CommandClass::setSoftEnum(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kArray); + try { + auto name = args[0].toStr(); + auto enums = parseStringList(args[1].asArray()); + return String::newString(get()->setSoftEnum(name, std::move(enums))); + } + CATCH("Fail in setSoftEnum!"); } -Local CommandClass::addSoftEnumValues(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kArray); - try { - auto name = args[0].toStr(); - auto enums = parseStringList(args[1].asArray()); - return Boolean::newBoolean( - get()->addSoftEnumValues(name, std::move(enums))); - } - CATCH("Fail in addSoftEnumValues!"); +Local CommandClass::addSoftEnumValues(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kArray); + try { + auto name = args[0].toStr(); + auto enums = parseStringList(args[1].asArray()); + return Boolean::newBoolean(get()->addSoftEnumValues(name, std::move(enums))); + } + CATCH("Fail in addSoftEnumValues!"); } -Local CommandClass::removeSoftEnumValues(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kArray); - try { - auto name = args[0].toStr(); - auto enums = parseStringList(args[1].asArray()); - return Boolean::newBoolean( - get()->removeSoftEnumValues(name, std::move(enums))); - } - CATCH("Fail in removeSoftEnumValues!"); +Local CommandClass::removeSoftEnumValues(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kArray); + try { + auto name = args[0].toStr(); + auto enums = parseStringList(args[1].asArray()); + return Boolean::newBoolean(get()->removeSoftEnumValues(name, std::move(enums))); + } + CATCH("Fail in removeSoftEnumValues!"); } -Local CommandClass::getSoftEnumValues(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - auto name = args[0].toStr(); - return getStringArray(get()->softEnums[name]); - } - CATCH("Fail in getSoftEnumValues"); +Local CommandClass::getSoftEnumValues(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + try { + auto name = args[0].toStr(); + return getStringArray(get()->softEnums[name]); + } + CATCH("Fail in getSoftEnumValues"); } -Local CommandClass::getSoftEnumNames(const Arguments &args) { - try { - std::vector stringArray; - for (auto &i : get()->softEnums) { - stringArray.push_back(i.first); +Local CommandClass::getSoftEnumNames(const Arguments& args) { + try { + std::vector stringArray; + for (auto& i : get()->softEnums) { + stringArray.push_back(i.first); + } + return getStringArray(stringArray); } - return getStringArray(stringArray); - } - CATCH("Fail in getSoftEnumNames"); + CATCH("Fail in getSoftEnumNames"); } diff --git a/src/api/CommandAPI.h b/src/api/CommandAPI.h index 9c475496..cf8b3d34 100644 --- a/src/api/CommandAPI.h +++ b/src/api/CommandAPI.h @@ -6,51 +6,50 @@ extern ClassDefine ParamTypeStaticBuilder; extern ClassDefine PermissionStaticBuilder; extern ClassDefine ParamOptionStaticBuilder; -bool LLSERemoveCmdCallback(script::ScriptEngine *engine); +bool LLSERemoveCmdCallback(script::ScriptEngine* engine); class CommandClass : public ScriptClass { - std::unique_ptr uptr; - DynamicCommandInstance *ptr; - bool registered = false; - inline DynamicCommandInstance *get() { return ptr; } - inline std::vector parseStringList(Local arr) { - if (arr.size() == 0 || !arr.get(0).isString()) - return {}; - std::vector strs; - for (size_t i = 0; i < arr.size(); ++i) { - strs.push_back(arr.get(i).toStr()); + std::unique_ptr uptr; + DynamicCommandInstance* ptr; + bool registered = false; + inline DynamicCommandInstance* get() { return ptr; } + inline std::vector parseStringList(Local arr) { + if (arr.size() == 0 || !arr.get(0).isString()) return {}; + std::vector strs; + for (size_t i = 0; i < arr.size(); ++i) { + strs.push_back(arr.get(i).toStr()); + } + return std::move(strs); } - return std::move(strs); - } - inline Local getStringArray(std::vector values) { - Local arr = Array::newArray(values.size()); - for (auto &str : values) { - arr.add(String::newString(str)); + inline Local getStringArray(std::vector values) { + Local arr = Array::newArray(values.size()); + for (auto& str : values) { + arr.add(String::newString(str)); + } + return arr; } - return arr; - } public: - CommandClass(std::unique_ptr &&p); - CommandClass(DynamicCommandInstance *p); - static Local newCommand(std::unique_ptr &&p); - static Local newCommand(DynamicCommandInstance *p); - Local getName(); - Local setAlias(const Arguments &args); - Local setEnum(const Arguments &args); - Local newParameter(const Arguments &args); - Local mandatory(const Arguments &args); - Local optional(const Arguments &args); - Local addOverload(const Arguments &args); - Local setCallback(const Arguments &args); - Local setup(const Arguments &args); - Local isRegistered(); - Local toString(const Arguments &args); - Local setSoftEnum(const Arguments &args); - Local addSoftEnumValues(const Arguments &args); - Local removeSoftEnumValues(const Arguments &args); - Local getSoftEnumValues(const Arguments &args); - Local getSoftEnumNames(const Arguments &args); + CommandClass(std::unique_ptr&& p); + CommandClass(DynamicCommandInstance* p); + static Local newCommand(std::unique_ptr&& p); + static Local newCommand(DynamicCommandInstance* p); + Local getName(); + Local setAlias(const Arguments& args); + Local setEnum(const Arguments& args); + Local newParameter(const Arguments& args); + Local mandatory(const Arguments& args); + Local optional(const Arguments& args); + Local addOverload(const Arguments& args); + Local setCallback(const Arguments& args); + Local setup(const Arguments& args); + Local isRegistered(); + Local toString(const Arguments& args); + Local setSoftEnum(const Arguments& args); + Local addSoftEnumValues(const Arguments& args); + Local removeSoftEnumValues(const Arguments& args); + Local getSoftEnumValues(const Arguments& args); + Local getSoftEnumNames(const Arguments& args); }; extern ClassDefine CommandClassBuilder; diff --git a/src/api/CommandCompatibleAPI.cpp b/src/api/CommandCompatibleAPI.cpp index 0cb6c19b..881af184 100644 --- a/src/api/CommandCompatibleAPI.cpp +++ b/src/api/CommandCompatibleAPI.cpp @@ -11,7 +11,7 @@ #include "ll/api/memory/Memory.h" #include "ll/api/service/Bedrock.h" #include "main/Configs.h" -#include "main/Global.hpp" +#include "main/Global.h" #include "utils/Utils.h" #include #include @@ -20,184 +20,169 @@ //////////////////// Helper //////////////////// -void RegisterCmd(const string &cmd, const string &describe, int cmdLevel) { - ll::event::EventBus::getInstance() - .emplaceListener( - [&](ll::event::ServerStartedEvent &ev) { - auto ®istry = ll::service::getCommandRegistry().get(); +void RegisterCmd(const string& cmd, const string& describe, int cmdLevel) { + ll::event::EventBus::getInstance().emplaceListener( + [&](ll::event::ServerStartedEvent& ev) { + auto& registry = ll::service::getCommandRegistry().get(); registry.registerCommand( - cmd, describe.c_str(), (CommandPermissionLevel)cmdLevel, - {(CommandFlagValue)0}, {(CommandFlagValue)0x80}); - }); + cmd, + describe.c_str(), + (CommandPermissionLevel)cmdLevel, + {(CommandFlagValue)0}, + {(CommandFlagValue)0x80} + ); + } + ); } // Helper -void LLSERegisterNewCmd(bool isPlayerCmd, string cmd, const string &describe, - int level, Local func) { - if (cmd[0] == '/') - cmd = cmd.erase(0, 1); - - if (isPlayerCmd) { - localShareData->playerCmdCallbacks[cmd] = { - EngineScope::currentEngine(), level, script::Global(func)}; - globalShareData->playerRegisteredCmd[cmd] = LLSE_BACKEND_TYPE; - } else { - localShareData->consoleCmdCallbacks[cmd] = { - EngineScope::currentEngine(), level, script::Global(func)}; - globalShareData->consoleRegisteredCmd[cmd] = LLSE_BACKEND_TYPE; - } - - // 延迟注册 - if (isCmdRegisterEnabled) - RegisterCmd(cmd, describe, level); - else - toRegCmdQueue.push_back({cmd, describe, level}); +void LLSERegisterNewCmd(bool isPlayerCmd, string cmd, const string& describe, int level, Local func) { + if (cmd[0] == '/') cmd = cmd.erase(0, 1); + + if (isPlayerCmd) { + localShareData->playerCmdCallbacks[cmd] = {EngineScope::currentEngine(), level, script::Global(func)}; + globalShareData->playerRegisteredCmd[cmd] = LLSE_BACKEND_TYPE; + } else { + localShareData + ->consoleCmdCallbacks[cmd] = {EngineScope::currentEngine(), level, script::Global(func)}; + globalShareData->consoleRegisteredCmd[cmd] = LLSE_BACKEND_TYPE; + } + + // 延迟注册 + if (isCmdRegisterEnabled) RegisterCmd(cmd, describe, level); + else toRegCmdQueue.push_back({cmd, describe, level}); } -bool LLSERemoveCmdRegister(ScriptEngine *engine) { - erase_if(localShareData->playerCmdCallbacks, - [&engine](auto &data) { return data.second.fromEngine == engine; }); - erase_if(localShareData->consoleCmdCallbacks, - [&engine](auto &data) { return data.second.fromEngine == engine; }); - return true; +bool LLSERemoveCmdRegister(ScriptEngine* engine) { + erase_if(localShareData->playerCmdCallbacks, [&engine](auto& data) { return data.second.fromEngine == engine; }); + erase_if(localShareData->consoleCmdCallbacks, [&engine](auto& data) { return data.second.fromEngine == engine; }); + return true; } // Helper -Local McClass::regPlayerCmd(const Arguments &args) { - CHECK_ARGS_COUNT(args, 3); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - CHECK_ARG_TYPE(args[2], ValueKind::kFunction); - if (args.size() >= 4) - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - - try { - string cmd = args[0].asString().toString(); - string describe = args[1].asString().toString(); - int level = 0; - - if (args.size() >= 4) { - int newLevel = args[3].asNumber().toInt32(); - if (newLevel >= 0 && newLevel <= 3) - level = newLevel; +Local McClass::regPlayerCmd(const Arguments& args) { + CHECK_ARGS_COUNT(args, 3); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + CHECK_ARG_TYPE(args[2], ValueKind::kFunction); + if (args.size() >= 4) CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + + try { + string cmd = args[0].asString().toString(); + string describe = args[1].asString().toString(); + int level = 0; + + if (args.size() >= 4) { + int newLevel = args[3].asNumber().toInt32(); + if (newLevel >= 0 && newLevel <= 3) level = newLevel; + } + + LLSERegisterNewCmd(true, cmd, describe, level, args[2].asFunction()); + return Boolean::newBoolean(true); } - - LLSERegisterNewCmd(true, cmd, describe, level, args[2].asFunction()); - return Boolean::newBoolean(true); - } - CATCH("Fail in RegisterPlayerCmd!"); + CATCH("Fail in RegisterPlayerCmd!"); } -Local McClass::regConsoleCmd(const Arguments &args) { - CHECK_ARGS_COUNT(args, 3); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - CHECK_ARG_TYPE(args[2], ValueKind::kFunction); +Local McClass::regConsoleCmd(const Arguments& args) { + CHECK_ARGS_COUNT(args, 3); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + CHECK_ARG_TYPE(args[2], ValueKind::kFunction); - try { - string cmd = args[0].asString().toString(); - string describe = args[1].asString().toString(); + try { + string cmd = args[0].asString().toString(); + string describe = args[1].asString().toString(); - LLSERegisterNewCmd(false, cmd, describe, 4, args[2].asFunction()); - return Boolean::newBoolean(true); - } - CATCH("Fail in RegisterConsoleCmd!"); + LLSERegisterNewCmd(false, cmd, describe, 4, args[2].asFunction()); + return Boolean::newBoolean(true); + } + CATCH("Fail in RegisterConsoleCmd!"); } // Helper -bool SendCmdOutput(const std::string &output) { - logger.info(output); - return true; +bool SendCmdOutput(const std::string& output) { + logger.info(output); + return true; } // Helper -Local McClass::sendCmdOutput(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local McClass::sendCmdOutput(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - return Boolean::newBoolean(SendCmdOutput(args[0].toStr())); - } - CATCH("Fail in SendCmdOutput!"); + try { + return Boolean::newBoolean(SendCmdOutput(args[0].toStr())); + } + CATCH("Fail in SendCmdOutput!"); } void ProcessRegCmdQueue() { - for (auto &cmdData : toRegCmdQueue) { - RegisterCmd(cmdData.cmd, cmdData.describe, cmdData.level); - } - toRegCmdQueue.clear(); + for (auto& cmdData : toRegCmdQueue) { + RegisterCmd(cmdData.cmd, cmdData.describe, cmdData.level); + } + toRegCmdQueue.clear(); } -string LLSEFindCmdReg(bool isPlayerCmd, const string &cmd, - vector &receiveParas, bool *fromOtherEngine) { - std::unordered_map ®isteredMap = - isPlayerCmd ? globalShareData->playerRegisteredCmd - : globalShareData->consoleRegisteredCmd; - for (auto &[prefix, fromEngine] : registeredMap) { - if (cmd == prefix || (cmd.find(prefix) == 0 && cmd[prefix.size()] == ' ')) - // 如果命令与注册前缀全匹配,或者目标前缀后面为空格 - { - // Matched - if (fromEngine != LLSE_BACKEND_TYPE) { - *fromOtherEngine = true; - return string(); - } +string LLSEFindCmdReg(bool isPlayerCmd, const string& cmd, vector& receiveParas, bool* fromOtherEngine) { + std::unordered_map& registeredMap = + isPlayerCmd ? globalShareData->playerRegisteredCmd : globalShareData->consoleRegisteredCmd; + for (auto& [prefix, fromEngine] : registeredMap) { + if (cmd == prefix || (cmd.find(prefix) == 0 && cmd[prefix.size()] == ' ')) + // 如果命令与注册前缀全匹配,或者目标前缀后面为空格 + { + // Matched + if (fromEngine != LLSE_BACKEND_TYPE) { + *fromOtherEngine = true; + return string(); + } + } } - } - - std::map &cmdMap = - isPlayerCmd ? localShareData->playerCmdCallbacks - : localShareData->consoleCmdCallbacks; - - for (auto &cmdData : cmdMap) { - string prefix = cmdData.first; - if (cmd == prefix || (cmd.find(prefix) == 0 && cmd[prefix.size()] == ' ')) - // 如果命令与注册前缀全匹配,或者目标前缀后面为空格 - { - // Matched - if (cmd.size() > prefix.size()) { - // 除了注册前缀之外还有额外参数 - receiveParas = SplitCmdLine(cmd.substr(prefix.size() + 1)); - } else - receiveParas = vector(); - - return prefix; + + std::map& cmdMap = + isPlayerCmd ? localShareData->playerCmdCallbacks : localShareData->consoleCmdCallbacks; + + for (auto& cmdData : cmdMap) { + string prefix = cmdData.first; + if (cmd == prefix || (cmd.find(prefix) == 0 && cmd[prefix.size()] == ' ')) + // 如果命令与注册前缀全匹配,或者目标前缀后面为空格 + { + // Matched + if (cmd.size() > prefix.size()) { + // 除了注册前缀之外还有额外参数 + receiveParas = SplitCmdLine(cmd.substr(prefix.size() + 1)); + } else receiveParas = vector(); + + return prefix; + } } - } - return string(); + return string(); } -bool CallPlayerCmdCallback(Player *player, const string &cmdPrefix, - const vector ¶s) { - EngineScope enter(localShareData->playerCmdCallbacks[cmdPrefix].fromEngine); - auto cmdData = localShareData->playerCmdCallbacks[cmdPrefix]; - Local res{}; - try { - Local args = Array::newArray(); - for (auto ¶ : paras) - args.add(String::newString(para)); - res = cmdData.func.get().call({}, PlayerClass::newPlayer(player), args); - } - CATCH_IN_CALLBACK("PlayerCmd"); - if (res.isNull() || (res.isBoolean() && res.asBoolean().value() == false)) - return false; - - return true; +bool CallPlayerCmdCallback(Player* player, const string& cmdPrefix, const vector& paras) { + EngineScope enter(localShareData->playerCmdCallbacks[cmdPrefix].fromEngine); + auto cmdData = localShareData->playerCmdCallbacks[cmdPrefix]; + Local res{}; + try { + Local args = Array::newArray(); + for (auto& para : paras) args.add(String::newString(para)); + res = cmdData.func.get().call({}, PlayerClass::newPlayer(player), args); + } + CATCH_IN_CALLBACK("PlayerCmd"); + if (res.isNull() || (res.isBoolean() && res.asBoolean().value() == false)) return false; + + return true; } -bool CallServerCmdCallback(const string &cmdPrefix, - const vector ¶s) { - EngineScope enter(localShareData->consoleCmdCallbacks[cmdPrefix].fromEngine); - auto cmdData = localShareData->consoleCmdCallbacks[cmdPrefix]; - Local res{}; - try { - Local args = Array::newArray(); - for (auto ¶ : paras) - args.add(String::newString(para)); - res = cmdData.func.get().call({}, args); - } - CATCH_IN_CALLBACK("ServerCmd"); - if (res.isNull() || (res.isBoolean() && res.asBoolean().value() == false)) - return false; - - return true; -} \ No newline at end of file +bool CallServerCmdCallback(const string& cmdPrefix, const vector& paras) { + EngineScope enter(localShareData->consoleCmdCallbacks[cmdPrefix].fromEngine); + auto cmdData = localShareData->consoleCmdCallbacks[cmdPrefix]; + Local res{}; + try { + Local args = Array::newArray(); + for (auto& para : paras) args.add(String::newString(para)); + res = cmdData.func.get().call({}, args); + } + CATCH_IN_CALLBACK("ServerCmd"); + if (res.isNull() || (res.isBoolean() && res.asBoolean().value() == false)) return false; + + return true; +} diff --git a/src/api/CommandCompatibleAPI.h b/src/api/CommandCompatibleAPI.h index 46569b4d..5f6ea1b8 100644 --- a/src/api/CommandCompatibleAPI.h +++ b/src/api/CommandCompatibleAPI.h @@ -7,21 +7,18 @@ class Player; // helper -std::vector SplitCmdLine(const std::string ¶s); +std::vector SplitCmdLine(const std::string& paras); // 命令回调查询 -std::string LLSEFindCmdReg(bool isPlayerCmd, const std::string &cmd, - std::vector &receiveParas, - bool *fromOtherEngine); +std::string +LLSEFindCmdReg(bool isPlayerCmd, const std::string& cmd, std::vector& receiveParas, bool* fromOtherEngine); // 删除指定引擎的所有命令 -bool LLSERemoveCmdRegister(script::ScriptEngine *engine); +bool LLSERemoveCmdRegister(script::ScriptEngine* engine); // 处理命令延迟注册 void ProcessRegCmdQueue(); // 玩家自定义命令注册回调 -bool CallPlayerCmdCallback(Player *player, const std::string &cmdPrefix, - const std::vector ¶s); +bool CallPlayerCmdCallback(Player* player, const std::string& cmdPrefix, const std::vector& paras); // 控制台自定义命令注册回调 -bool CallServerCmdCallback(const std::string &cmdPrefix, - const std::vector ¶s); \ No newline at end of file +bool CallServerCmdCallback(const std::string& cmdPrefix, const std::vector& paras); \ No newline at end of file diff --git a/src/api/CommandOriginAPI.cpp b/src/api/CommandOriginAPI.cpp index 4a15a2d5..f7d541e0 100644 --- a/src/api/CommandOriginAPI.cpp +++ b/src/api/CommandOriginAPI.cpp @@ -20,8 +20,7 @@ #include "mc/world/level/dimension/Dimension.h" //////////////////// Class Definition //////////////////// -ClassDefine OriginTypeStaticBuilder = - EnumDefineBuilder::build("CommandOriginType"); +ClassDefine OriginTypeStaticBuilder = EnumDefineBuilder::build("CommandOriginType"); ClassDefine CommandOriginClassBuilder = defineClass("LLSE_CommandOrigin") @@ -41,86 +40,80 @@ ClassDefine CommandOriginClassBuilder = //////////////////// APIs //////////////////// -CommandOriginClass::CommandOriginClass(CommandOrigin const *p) - : ScriptClass(ScriptClass::ConstructFromCpp{}), - ptr(p){}; +CommandOriginClass::CommandOriginClass(CommandOrigin const* p) +: ScriptClass(ScriptClass::ConstructFromCpp{}), + ptr(p){}; -Local CommandOriginClass::newCommandOrigin(CommandOrigin const *p) { - auto newp = new CommandOriginClass(p); - return newp->getScriptObject(); +Local CommandOriginClass::newCommandOrigin(CommandOrigin const* p) { + auto newp = new CommandOriginClass(p); + return newp->getScriptObject(); } Local CommandOriginClass::getOriginType() { - try { - return Number::newNumber((int)get()->getOriginType()); - } - CATCH("Fail in getOriginType!"); + try { + return Number::newNumber((int)get()->getOriginType()); + } + CATCH("Fail in getOriginType!"); } Local CommandOriginClass::getOriginTypeName() { - try { - return String::newString( - magic_enum::enum_name((CommandOriginType)get()->getOriginType())); - } - CATCH("Fail in getOriginTypeName!"); + try { + return String::newString(magic_enum::enum_name((CommandOriginType)get()->getOriginType())); + } + CATCH("Fail in getOriginTypeName!"); } Local CommandOriginClass::getOriginName() { - try { - return String::newString(get()->getName()); - } - CATCH("Fail in getOriginName!"); + try { + return String::newString(get()->getName()); + } + CATCH("Fail in getOriginName!"); } Local CommandOriginClass::getBlockPosition() { - try { - auto dim = get()->getDimension(); - return IntPos::newPos(get()->getBlockPosition(), - dim ? (int)dim->getDimensionId() : 0); - } - CATCH("Fail in getBlockPosition!"); + try { + auto dim = get()->getDimension(); + return IntPos::newPos(get()->getBlockPosition(), dim ? (int)dim->getDimensionId() : 0); + } + CATCH("Fail in getBlockPosition!"); } Local CommandOriginClass::getPosition() { - try { - auto dim = get()->getDimension(); - return FloatPos::newPos(get()->getWorldPosition(), - dim ? (int)dim->getDimensionId() : 0); - } - CATCH("Fail in getPosition!"); + try { + auto dim = get()->getDimension(); + return FloatPos::newPos(get()->getWorldPosition(), dim ? (int)dim->getDimensionId() : 0); + } + CATCH("Fail in getPosition!"); } Local CommandOriginClass::getEntity() { - try { - auto entity = get()->getEntity(); - if (!entity) - return Local(); - return EntityClass::newEntity(entity); - } - CATCH("Fail in getEntity!"); + try { + auto entity = get()->getEntity(); + if (!entity) return Local(); + return EntityClass::newEntity(entity); + } + CATCH("Fail in getEntity!"); } Local CommandOriginClass::getPlayer() { - try { - auto player = get()->getEntity(); - if (!player) - return Local(); - return PlayerClass::newPlayer((Player *)player); - } - CATCH("Fail in getPlayer!"); + try { + auto player = get()->getEntity(); + if (!player) return Local(); + return PlayerClass::newPlayer((Player*)player); + } + CATCH("Fail in getPlayer!"); } -Local CommandOriginClass::getNbt(const Arguments &args) { - try { - return NbtCompoundClass::pack( - std::make_unique(get()->serialize())); - } - CATCH("Fail in getNbt!"); +Local CommandOriginClass::getNbt(const Arguments& args) { + try { + return NbtCompoundClass::pack(std::make_unique(get()->serialize())); + } + CATCH("Fail in getNbt!"); } Local CommandOriginClass::toString() { - try { - return String::newString(""); - } - CATCH("Fail in toString!"); + try { + return String::newString(""); + } + CATCH("Fail in toString!"); } diff --git a/src/api/CommandOriginAPI.h b/src/api/CommandOriginAPI.h index c744041f..acb4ed99 100644 --- a/src/api/CommandOriginAPI.h +++ b/src/api/CommandOriginAPI.h @@ -3,23 +3,23 @@ #include "mc/server/commands/CommandOrigin.h" class CommandOriginClass; -extern ClassDefine OriginTypeStaticBuilder; +extern ClassDefine OriginTypeStaticBuilder; extern ClassDefine CommandOriginClassBuilder; class CommandOriginClass : public ScriptClass { - CommandOrigin const *ptr; - inline CommandOrigin const *get() { return ptr; } + CommandOrigin const* ptr; + inline CommandOrigin const* get() { return ptr; } public: - CommandOriginClass(CommandOrigin const *p); - static Local newCommandOrigin(CommandOrigin const *p); - Local getOriginType(); - Local getOriginTypeName(); - Local getOriginName(); - Local getBlockPosition(); - Local getPosition(); - Local getEntity(); - Local getPlayer(); - Local getNbt(const Arguments &args); - Local toString(); + CommandOriginClass(CommandOrigin const* p); + static Local newCommandOrigin(CommandOrigin const* p); + Local getOriginType(); + Local getOriginTypeName(); + Local getOriginName(); + Local getBlockPosition(); + Local getPosition(); + Local getEntity(); + Local getPlayer(); + Local getNbt(const Arguments& args); + Local toString(); }; diff --git a/src/api/CommandOutputAPI.cpp b/src/api/CommandOutputAPI.cpp index 0a285bcd..254dfcf0 100644 --- a/src/api/CommandOutputAPI.cpp +++ b/src/api/CommandOutputAPI.cpp @@ -19,29 +19,29 @@ ClassDefine CommandOutputClassBuilder = //////////////////// APIs //////////////////// -CommandOutputClass::CommandOutputClass(CommandOutput *p) - : ScriptClass(ScriptClass::ConstructFromCpp{}), - ptr(p){}; +CommandOutputClass::CommandOutputClass(CommandOutput* p) +: ScriptClass(ScriptClass::ConstructFromCpp{}), + ptr(p){}; -Local CommandOutputClass::newCommandOutput(CommandOutput *p) { - auto newp = new CommandOutputClass(p); - return newp->getScriptObject(); +Local CommandOutputClass::newCommandOutput(CommandOutput* p) { + auto newp = new CommandOutputClass(p); + return newp->getScriptObject(); } // MCAPI bool empty() const; Local CommandOutputClass::empty() { - try { - return Boolean::newBoolean(get()->hasErrorMessage()); - } - CATCH("Fail in empty!"); + try { + return Boolean::newBoolean(get()->hasErrorMessage()); + } + CATCH("Fail in empty!"); } // MCAPI int getSuccessCount() const; Local CommandOutputClass::getSuccessCount() { - try { - return Number::newNumber(get()->getSuccessCount()); - } - CATCH("Fail in getSuccessCount!"); + try { + return Number::newNumber(get()->getSuccessCount()); + } + CATCH("Fail in getSuccessCount!"); }; // MCAPI enum CommandOutputType getType() const; @@ -56,82 +56,81 @@ Local CommandOutputClass::getSuccessCount() { // MCAPI void success(std::string const&, std::vector const&); MCAPI void success(); -Local CommandOutputClass::success(const Arguments &args) { - try { - if (args.size() == 0) { - get()->success(); - return Boolean::newBoolean(true); - } - CHECK_ARG_TYPE(args[0], ValueKind::kString); - auto msg = args[0].toStr(); - if (args.size() >= 2) { - CHECK_ARG_TYPE(args[1], ValueKind::kArray); - std::vector param{}; - auto paramArr = args[1].asArray(); - for (int i = 0; i < paramArr.size(); ++i) { - param.push_back(CommandOutputParameter(paramArr.get(i).toStr())); - } - get()->success(msg, param); - return Boolean::newBoolean(true); +Local CommandOutputClass::success(const Arguments& args) { + try { + if (args.size() == 0) { + get()->success(); + return Boolean::newBoolean(true); + } + CHECK_ARG_TYPE(args[0], ValueKind::kString); + auto msg = args[0].toStr(); + if (args.size() >= 2) { + CHECK_ARG_TYPE(args[1], ValueKind::kArray); + std::vector param{}; + auto paramArr = args[1].asArray(); + for (int i = 0; i < paramArr.size(); ++i) { + param.push_back(CommandOutputParameter(paramArr.get(i).toStr())); + } + get()->success(msg, param); + return Boolean::newBoolean(true); + } + get()->success(msg); + return Boolean::newBoolean(true); } - get()->success(msg); - return Boolean::newBoolean(true); - } - CATCH("Fail in success!"); + CATCH("Fail in success!"); }; -Local CommandOutputClass::addMessage(const Arguments &args) { - try { - CHECK_ARG_TYPE(args[0], ValueKind::kString); - auto msg = args[0].toStr(); - if (args.size() >= 2) { - CHECK_ARG_TYPE(args[1], ValueKind::kArray); - std::vector param{}; - auto paramArr = args[1].asArray(); - for (int i = 0; i < paramArr.size(); ++i) { - param.push_back(CommandOutputParameter(paramArr.get(i).toStr())); - } - if (args.size() >= 3) { - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - get()->addMessage(msg, param, - (CommandOutputMessageType)args[2].toInt()); +Local CommandOutputClass::addMessage(const Arguments& args) { + try { + CHECK_ARG_TYPE(args[0], ValueKind::kString); + auto msg = args[0].toStr(); + if (args.size() >= 2) { + CHECK_ARG_TYPE(args[1], ValueKind::kArray); + std::vector param{}; + auto paramArr = args[1].asArray(); + for (int i = 0; i < paramArr.size(); ++i) { + param.push_back(CommandOutputParameter(paramArr.get(i).toStr())); + } + if (args.size() >= 3) { + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + get()->addMessage(msg, param, (CommandOutputMessageType)args[2].toInt()); + return Boolean::newBoolean(true); + } + get()->addMessage(msg, param, (CommandOutputMessageType)0); + return Boolean::newBoolean(true); + } + get()->addMessage(msg, {}, CommandOutputMessageType::Success); return Boolean::newBoolean(true); - } - get()->addMessage(msg, param, (CommandOutputMessageType)0); - return Boolean::newBoolean(true); } - get()->addMessage(msg, {}, CommandOutputMessageType::Success); - return Boolean::newBoolean(true); - } - CATCH("Fail in addMessage!"); + CATCH("Fail in addMessage!"); }; // MCAPI void error(std::string const&, std::vector const&); -Local CommandOutputClass::error(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - auto msg = args[0].toStr(); - if (args.size() >= 2) { - CHECK_ARG_TYPE(args[1], ValueKind::kArray); - std::vector param{}; - auto paramArr = args[1].asArray(); - for (int i = 0; i < paramArr.size(); ++i) { - param.push_back(CommandOutputParameter(paramArr.get(i).toStr())); - } - get()->error(msg, param); - return Boolean::newBoolean(true); +Local CommandOutputClass::error(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + try { + auto msg = args[0].toStr(); + if (args.size() >= 2) { + CHECK_ARG_TYPE(args[1], ValueKind::kArray); + std::vector param{}; + auto paramArr = args[1].asArray(); + for (int i = 0; i < paramArr.size(); ++i) { + param.push_back(CommandOutputParameter(paramArr.get(i).toStr())); + } + get()->error(msg, param); + return Boolean::newBoolean(true); + } + get()->error(msg); + return Boolean::newBoolean(true); } - get()->error(msg); - return Boolean::newBoolean(true); - } - CATCH("Fail in error!"); + CATCH("Fail in error!"); }; -Local CommandOutputClass::toString(const Arguments &args) { - try { - return String::newString(""); - } - CATCH("Fail in toString!"); +Local CommandOutputClass::toString(const Arguments& args) { + try { + return String::newString(""); + } + CATCH("Fail in toString!"); }; diff --git a/src/api/CommandOutputAPI.h b/src/api/CommandOutputAPI.h index d70be86e..00f30834 100644 --- a/src/api/CommandOutputAPI.h +++ b/src/api/CommandOutputAPI.h @@ -6,10 +6,8 @@ class CommandOutputClass; extern ClassDefine CommandOutputClassBuilder; class CommandOutputClass : public ScriptClass { - CommandOutput* ptr; - inline CommandOutput* get() { - return ptr; - } + CommandOutput* ptr; + inline CommandOutput* get() { return ptr; } public: CommandOutputClass(CommandOutput* p); @@ -61,8 +59,8 @@ class CommandOutputClass : public ScriptClass { // Local getData() const; // MCAPI std::vector const& getMessages() const; // Local getMessages() const; - // MCAPI void load(enum CommandOutputType, int, std::vector&&, std::unique_ptr&&); - // Local load(const Arguments& args); + // MCAPI void load(enum CommandOutputType, int, std::vector&&, std::unique_ptr&&); Local load(const Arguments& args); Local toString(const Arguments& args); }; diff --git a/src/api/ContainerAPI.cpp b/src/api/ContainerAPI.cpp index 5e273364..0dffb9a9 100644 --- a/src/api/ContainerAPI.cpp +++ b/src/api/ContainerAPI.cpp @@ -17,8 +17,7 @@ ClassDefine ContainerClassBuilder = .instanceProperty("type", &ContainerClass::getType) .instanceFunction("addItem", &ContainerClass::addItem) - .instanceFunction("addItemToFirstEmptySlot", - &ContainerClass::addItemToFirstEmptySlot) + .instanceFunction("addItemToFirstEmptySlot", &ContainerClass::addItemToFirstEmptySlot) .instanceFunction("hasRoomFor", &ContainerClass::hasRoomFor) .instanceFunction("removeItem", &ContainerClass::removeItem) .instanceFunction("getItem", &ContainerClass::getItem) @@ -34,170 +33,166 @@ ClassDefine ContainerClassBuilder = //////////////////// Classes //////////////////// -ContainerClass::ContainerClass(Container *p) - : ScriptClass(ScriptClass::ConstructFromCpp{}), - container(p) {} +ContainerClass::ContainerClass(Container* p) +: ScriptClass(ScriptClass::ConstructFromCpp{}), + container(p) {} // 生成函数 -Local ContainerClass::newContainer(Container *p) { - auto newp = new ContainerClass(p); - return newp->getScriptObject(); +Local ContainerClass::newContainer(Container* p) { + auto newp = new ContainerClass(p); + return newp->getScriptObject(); } -Container *ContainerClass::extract(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine() - ->getNativeInstance(v) - ->get(); - else - return nullptr; +Container* ContainerClass::extract(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v)->get(); + else return nullptr; } // 成员函数 Local ContainerClass::getSize() { - try { - return Number::newNumber(container->getContainerSize()); - } - CATCH("Fail in getSize!") + try { + return Number::newNumber(container->getContainerSize()); + } + CATCH("Fail in getSize!") } Local ContainerClass::getType() { - try { - return String::newString(container->getTypeName()); - } - CATCH("Fail in getType!") + try { + return String::newString(container->getTypeName()); + } + CATCH("Fail in getType!") } -Local ContainerClass::asPointer(const Arguments &args) { - try { - return NativePointer::newNativePointer(container); - } - CATCH("Fail in asPointer!") +Local ContainerClass::asPointer(const Arguments& args) { + try { + return NativePointer::newNativePointer(container); + } + CATCH("Fail in asPointer!") } -Local ContainerClass::addItem(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); +Local ContainerClass::addItem(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); - try { - ItemStack *item = ItemClass::extract(args[0]); - if (!item) { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - if (args.size() >= 2) { - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - for (unsigned short i = 0; i < args[1].toInt(); ++i) { - if (container->addItem(*item)) { - return Boolean::newBoolean(false); + try { + ItemStack* item = ItemClass::extract(args[0]); + if (!item) { + LOG_WRONG_ARG_TYPE(); + return Local(); } - } - return Boolean::newBoolean(true); + if (args.size() >= 2) { + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + for (unsigned short i = 0; i < args[1].toInt(); ++i) { + if (container->addItem(*item)) { + return Boolean::newBoolean(false); + } + } + return Boolean::newBoolean(true); + } + return Boolean::newBoolean(container->addItem(*item)); } - return Boolean::newBoolean(container->addItem(*item)); - } - CATCH("Fail in addItem!"); + CATCH("Fail in addItem!"); } -Local ContainerClass::addItemToFirstEmptySlot(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); +Local ContainerClass::addItemToFirstEmptySlot(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); - try { - ItemStack *item = ItemClass::extract(args[0]); - if (!item) { - LOG_WRONG_ARG_TYPE(); - return Local(); + try { + ItemStack* item = ItemClass::extract(args[0]); + if (!item) { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + return Boolean::newBoolean(container->addItemToFirstEmptySlot(*item)); } - return Boolean::newBoolean(container->addItemToFirstEmptySlot(*item)); - } - CATCH("Fail in addItemToFirstEmptySlot!"); + CATCH("Fail in addItemToFirstEmptySlot!"); } -Local ContainerClass::hasRoomFor(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); +Local ContainerClass::hasRoomFor(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); - try { - ItemStack *item = ItemClass::extract(args[0]); - if (!item) { - LOG_WRONG_ARG_TYPE(); - return Local(); + try { + ItemStack* item = ItemClass::extract(args[0]); + if (!item) { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + return Boolean::newBoolean(container->hasRoomForItem(*item)); } - return Boolean::newBoolean(container->hasRoomForItem(*item)); - } - CATCH("Fail in hasRoomFor!"); + CATCH("Fail in hasRoomFor!"); } -Local ContainerClass::removeItem(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); +Local ContainerClass::removeItem(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - try { - container->removeItem(args[0].toInt(), args[1].toInt()); - return Boolean::newBoolean(true); - } - CATCH("Fail in removeItem!"); + try { + container->removeItem(args[0].toInt(), args[1].toInt()); + return Boolean::newBoolean(true); + } + CATCH("Fail in removeItem!"); } -Local ContainerClass::getItem(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local ContainerClass::getItem(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - ItemStack *item = (ItemStack *)&container->getItem(args[0].toInt()); - if (!item) { - LOG_ERROR_WITH_SCRIPT_INFO("Fail to get slot from container!"); - return Local(); + try { + ItemStack* item = (ItemStack*)&container->getItem(args[0].toInt()); + if (!item) { + LOG_ERROR_WITH_SCRIPT_INFO("Fail to get slot from container!"); + return Local(); + } + return ItemClass::newItem(item); } - return ItemClass::newItem(item); - } - CATCH("Fail in getItem!"); + CATCH("Fail in getItem!"); } -Local ContainerClass::setItem(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local ContainerClass::setItem(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - ItemStack *item = ItemClass::extract(args[1]); - if (!item) { - LOG_WRONG_ARG_TYPE(); - return Local(); - } + try { + ItemStack* item = ItemClass::extract(args[1]); + if (!item) { + LOG_WRONG_ARG_TYPE(); + return Local(); + } - ItemStack *itemOld = (ItemStack *)&container->getItem(args[0].toInt()); - if (!itemOld) - return Boolean::newBoolean(false); + ItemStack* itemOld = (ItemStack*)&container->getItem(args[0].toInt()); + if (!itemOld) return Boolean::newBoolean(false); - auto tag = itemOld->save(); - item->fromTag(*tag); - return Boolean::newBoolean(true); - } - CATCH("Fail in getItem!"); + auto tag = itemOld->save(); + item->fromTag(*tag); + return Boolean::newBoolean(true); + } + CATCH("Fail in getItem!"); } -Local ContainerClass::getAllItems(const Arguments &args) { - try { - auto list = container->getSlots(); +Local ContainerClass::getAllItems(const Arguments& args) { + try { + auto list = container->getSlots(); - Local res = Array::newArray(); - for (auto &item : list) { - res.add(ItemClass::newItem((ItemStack *)item)); + Local res = Array::newArray(); + for (auto& item : list) { + res.add(ItemClass::newItem((ItemStack*)item)); + } + return res; } - return res; - } - CATCH("Fail in getAllItems!"); + CATCH("Fail in getAllItems!"); } -Local ContainerClass::removeAllItems(const Arguments &args) { - try { - container->removeAllItems(); - return Boolean::newBoolean(true); - } - CATCH("Fail in removeAllItems!"); +Local ContainerClass::removeAllItems(const Arguments& args) { + try { + container->removeAllItems(); + return Boolean::newBoolean(true); + } + CATCH("Fail in removeAllItems!"); } -Local ContainerClass::isEmpty(const Arguments &args) { - try { - return Boolean::newBoolean(container->isEmpty()); - } - CATCH("Fail in isEmpty!"); +Local ContainerClass::isEmpty(const Arguments& args) { + try { + return Boolean::newBoolean(container->isEmpty()); + } + CATCH("Fail in isEmpty!"); } \ No newline at end of file diff --git a/src/api/ContainerAPI.h b/src/api/ContainerAPI.h index a7b7db9e..c447ae47 100644 --- a/src/api/ContainerAPI.h +++ b/src/api/ContainerAPI.h @@ -7,28 +7,28 @@ class Container; class ContainerClass : public ScriptClass { private: - Container *container; + Container* container; public: - explicit ContainerClass(Container *p); + explicit ContainerClass(Container* p); - Container *get() { return container; } + Container* get() { return container; } - static Local newContainer(Container *p); - static Container *extract(Local v); - Local asPointer(const Arguments &args); + static Local newContainer(Container* p); + static Container* extract(Local v); + Local asPointer(const Arguments& args); - Local getSize(); - Local getType(); + Local getSize(); + Local getType(); - Local addItem(const Arguments &args); - Local addItemToFirstEmptySlot(const Arguments &args); - Local hasRoomFor(const Arguments &args); - Local removeItem(const Arguments &args); - Local getItem(const Arguments &args); - Local setItem(const Arguments &args); - Local getAllItems(const Arguments &args); - Local removeAllItems(const Arguments &args); - Local isEmpty(const Arguments &args); + Local addItem(const Arguments& args); + Local addItemToFirstEmptySlot(const Arguments& args); + Local hasRoomFor(const Arguments& args); + Local removeItem(const Arguments& args); + Local getItem(const Arguments& args); + Local setItem(const Arguments& args); + Local getAllItems(const Arguments& args); + Local removeAllItems(const Arguments& args); + Local isEmpty(const Arguments& args); }; extern ClassDefine ContainerClassBuilder; \ No newline at end of file diff --git a/src/api/DataAPI.cpp b/src/api/DataAPI.cpp index a61df79c..e39c4b25 100644 --- a/src/api/DataAPI.cpp +++ b/src/api/DataAPI.cpp @@ -6,7 +6,7 @@ #include // #include -#include "legacyapi/Base64.hpp" +#include "legacyapi/Base64.h" #include "legacyapi/utils/FileHelper.h" #include "ll/api/service/PlayerInfo.h" #include "ll/api/utils/CryptoUtils.h" @@ -16,35 +16,33 @@ //////////////////// Class Definition //////////////////// -ClassDefine DataClassBuilder = - defineClass("data") - .function("xuid2name", &DataClass::xuid2name) - .function("name2xuid", &DataClass::name2xuid) - .function("xuid2uuid", &DataClass::xuid2uuid) - .function("name2uuid", &DataClass::name2uuid) - // .function("getAllPlayerInfo", &DataClass::getAllPlayerInfo) - .function("parseJson", &DataClass::parseJson) - .function("toJson", &DataClass::toJson) - .function("toMD5", &DataClass::toMD5) - .function("toSHA1", &DataClass::toSHA1) - .function("toBase64", &DataClass::toBase64) - .function("fromBase64", &DataClass::fromBase64) - - // For Compatibility - .function("openDB", &DataClass::openDB) - .function("openConfig", &DataClass::openConfig) - .build(); - -ClassDefine MoneyClassBuilder = - defineClass("money") - .function("set", &MoneyClass::set) - .function("get", &MoneyClass::get) - .function("add", &MoneyClass::add) - .function("reduce", &MoneyClass::reduce) - .function("trans", &MoneyClass::trans) - .function("getHistory", &MoneyClass::getHistory) - .function("clearHistory", &MoneyClass::clearHistory) - .build(); +ClassDefine DataClassBuilder = defineClass("data") + .function("xuid2name", &DataClass::xuid2name) + .function("name2xuid", &DataClass::name2xuid) + .function("xuid2uuid", &DataClass::xuid2uuid) + .function("name2uuid", &DataClass::name2uuid) + // .function("getAllPlayerInfo", &DataClass::getAllPlayerInfo) + .function("parseJson", &DataClass::parseJson) + .function("toJson", &DataClass::toJson) + .function("toMD5", &DataClass::toMD5) + .function("toSHA1", &DataClass::toSHA1) + .function("toBase64", &DataClass::toBase64) + .function("fromBase64", &DataClass::fromBase64) + + // For Compatibility + .function("openDB", &DataClass::openDB) + .function("openConfig", &DataClass::openConfig) + .build(); + +ClassDefine MoneyClassBuilder = defineClass("money") + .function("set", &MoneyClass::set) + .function("get", &MoneyClass::get) + .function("add", &MoneyClass::add) + .function("reduce", &MoneyClass::reduce) + .function("trans", &MoneyClass::trans) + .function("getHistory", &MoneyClass::getHistory) + .function("clearHistory", &MoneyClass::clearHistory) + .build(); ClassDefine ConfJsonClassBuilder = defineClass("JsonConfigFile") @@ -53,12 +51,14 @@ ClassDefine ConfJsonClassBuilder = .instanceFunction("get", &ConfJsonClass::get) .instanceFunction("set", &ConfJsonClass::set) .instanceFunction("delete", &ConfJsonClass::del) - .instanceFunction("reload", - selectOverloadedFunc (ConfJsonClass::*)( - const Arguments &)>(&ConfJsonClass::reload)) - .instanceFunction("close", - selectOverloadedFunc (ConfJsonClass::*)( - const Arguments &)>(&ConfJsonClass::close)) + .instanceFunction( + "reload", + selectOverloadedFunc (ConfJsonClass::*)(const Arguments&)>(&ConfJsonClass::reload) + ) + .instanceFunction( + "close", + selectOverloadedFunc (ConfJsonClass::*)(const Arguments&)>(&ConfJsonClass::close) + ) .instanceFunction("getPath", &ConfJsonClass::getPath) .instanceFunction("read", &ConfJsonClass::read) .instanceFunction("write", &ConfJsonClass::write) @@ -74,12 +74,14 @@ ClassDefine ConfIniClassBuilder = .instanceFunction("getFloat", &ConfIniClass::getFloat) .instanceFunction("getBool", &ConfIniClass::getBool) .instanceFunction("delete", &ConfIniClass::del) - .instanceFunction("reload", - selectOverloadedFunc (ConfIniClass::*)( - const Arguments &)>(&ConfIniClass::reload)) - .instanceFunction("close", - selectOverloadedFunc (ConfIniClass::*)( - const Arguments &)>(&ConfIniClass::close)) + .instanceFunction( + "reload", + selectOverloadedFunc (ConfIniClass::*)(const Arguments&)>(&ConfIniClass::reload) + ) + .instanceFunction( + "close", + selectOverloadedFunc (ConfIniClass::*)(const Arguments&)>(&ConfIniClass::close) + ) .instanceFunction("getPath", &ConfIniClass::getPath) .instanceFunction("read", &ConfIniClass::read) .instanceFunction("write", &ConfIniClass::write) @@ -87,692 +89,649 @@ ClassDefine ConfIniClassBuilder = //////////////////// Classes ConfBase //////////////////// -ConfBaseClass::ConfBaseClass(const string &dir) : confPath(dir) {} +ConfBaseClass::ConfBaseClass(const string& dir) : confPath(dir) {} -Local ConfBaseClass::getPath(const Arguments &args) { - try { - return String::newString(confPath); - } - CATCH("Fail in confGetPath!") +Local ConfBaseClass::getPath(const Arguments& args) { + try { + return String::newString(confPath); + } + CATCH("Fail in confGetPath!") } -Local ConfBaseClass::read(const Arguments &args) { - try { - auto content = ReadAllFile(confPath); - if (!content) - return Local(); - else - return String::newString(*content); - } - CATCH("Fail in confRead!") +Local ConfBaseClass::read(const Arguments& args) { + try { + auto content = ReadAllFile(confPath); + if (!content) return Local(); + else return String::newString(*content); + } + CATCH("Fail in confRead!") } //////////////////// Classes ConfJson //////////////////// // 生成函数 -ConfJsonClass::ConfJsonClass(const Local &scriptObj, const string &path, - const string &defContent) - : ScriptClass(scriptObj), ConfBaseClass(path) { - jsonConf = CreateJson(path, defContent); +ConfJsonClass::ConfJsonClass(const Local& scriptObj, const string& path, const string& defContent) +: ScriptClass(scriptObj), + ConfBaseClass(path) { + jsonConf = CreateJson(path, defContent); } -ConfJsonClass::ConfJsonClass(const string &path, const string &defContent) - : ScriptClass(ScriptClass::ConstructFromCpp{}), - ConfBaseClass(path) { - jsonConf = CreateJson(path, defContent); +ConfJsonClass::ConfJsonClass(const string& path, const string& defContent) +: ScriptClass(ScriptClass::ConstructFromCpp{}), + ConfBaseClass(path) { + jsonConf = CreateJson(path, defContent); } ConfJsonClass::~ConfJsonClass() { close(); } -ConfJsonClass *ConfJsonClass::constructor(const Arguments &args) { - CHECK_ARGS_COUNT_C(args, 1); - CHECK_ARG_TYPE_C(args[0], ValueKind::kString); - if (args.size() >= 2) - CHECK_ARG_TYPE_C(args[1], ValueKind::kString); - - try { - string path = args[0].toStr(); - if (path.empty()) - return nullptr; - - if (args.size() >= 2) - return new ConfJsonClass(args.thiz(), path, args[1].toStr()); - else - return new ConfJsonClass(args.thiz(), path, "{}"); - } - CATCH_C("Fail in Open JsonConfigFile!"); -} - -Local ConfJsonClass::init(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - return JsonToValue(jsonConf.at(args[0].toStr())); - } catch (const std::out_of_range &e) { - jsonConf[args[0].toStr()] = ordered_json::parse(ValueToJson(args[1])); - flush(); - return args[1]; - } catch (const ordered_json::exception &e) { - jsonConf[args[0].toStr()] = ordered_json::parse(ValueToJson(args[1])); - flush(); - return args[1]; - } - CATCH("Fail in confJsonSet!"); -} - -Local ConfJsonClass::get(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - return JsonToValue(jsonConf.at(args[0].toStr())); - } catch (const std::out_of_range &e) { - return args.size() >= 2 ? args[1] : Local(); - } catch (const ordered_json::exception &e) { - return args.size() >= 2 ? args[1] : Local(); - } - CATCH("Fail in confJsonGet!") -} - -Local ConfJsonClass::set(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - jsonConf[args[0].toStr()] = ordered_json::parse(ValueToJson(args[1])); - return Boolean::newBoolean(flush()); - } catch (const ordered_json::exception &e) { - return Boolean::newBoolean(false); - } - CATCH("Fail in confJsonSet!"); -} - -Local ConfJsonClass::del(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - if (jsonConf.erase(args[0].toStr()) <= 0) - return Boolean::newBoolean(false); - - return Boolean::newBoolean(flush()); - } catch (const ordered_json::exception &e) { - return Boolean::newBoolean(false); - } - CATCH("Fail in confJsonDelete!"); -} - -Local ConfJsonClass::reload(const Arguments &args) { - try { - return Boolean::newBoolean(reload()); - } catch (const ordered_json::exception &e) { - logger.error("Fail to parse json content in file!"); - logger.error(ll::string_utils::tou8str(e.what())); - PrintScriptStackTrace(); - return Boolean::newBoolean(false); - } - CATCH("Fail in confJsonReload!"); -} - -Local ConfJsonClass::close(const Arguments &args) { - try { - return Boolean::newBoolean(close()); - } - CATCH("Fail in confJsonClose!"); -} - -Local ConfJsonClass::write(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - bool res = WriteAllFile(confPath, args[0].toStr(), false); - reload(); - return Boolean::newBoolean(res); - } - CATCH("Fail in confJsonWrite!"); +ConfJsonClass* ConfJsonClass::constructor(const Arguments& args) { + CHECK_ARGS_COUNT_C(args, 1); + CHECK_ARG_TYPE_C(args[0], ValueKind::kString); + if (args.size() >= 2) CHECK_ARG_TYPE_C(args[1], ValueKind::kString); + + try { + string path = args[0].toStr(); + if (path.empty()) return nullptr; + + if (args.size() >= 2) return new ConfJsonClass(args.thiz(), path, args[1].toStr()); + else return new ConfJsonClass(args.thiz(), path, "{}"); + } + CATCH_C("Fail in Open JsonConfigFile!"); +} + +Local ConfJsonClass::init(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + return JsonToValue(jsonConf.at(args[0].toStr())); + } catch (const std::out_of_range& e) { + jsonConf[args[0].toStr()] = ordered_json::parse(ValueToJson(args[1])); + flush(); + return args[1]; + } catch (const ordered_json::exception& e) { + jsonConf[args[0].toStr()] = ordered_json::parse(ValueToJson(args[1])); + flush(); + return args[1]; + } + CATCH("Fail in confJsonSet!"); +} + +Local ConfJsonClass::get(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + return JsonToValue(jsonConf.at(args[0].toStr())); + } catch (const std::out_of_range& e) { + return args.size() >= 2 ? args[1] : Local(); + } catch (const ordered_json::exception& e) { + return args.size() >= 2 ? args[1] : Local(); + } + CATCH("Fail in confJsonGet!") +} + +Local ConfJsonClass::set(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + jsonConf[args[0].toStr()] = ordered_json::parse(ValueToJson(args[1])); + return Boolean::newBoolean(flush()); + } catch (const ordered_json::exception& e) { + return Boolean::newBoolean(false); + } + CATCH("Fail in confJsonSet!"); +} + +Local ConfJsonClass::del(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + if (jsonConf.erase(args[0].toStr()) <= 0) return Boolean::newBoolean(false); + + return Boolean::newBoolean(flush()); + } catch (const ordered_json::exception& e) { + return Boolean::newBoolean(false); + } + CATCH("Fail in confJsonDelete!"); +} + +Local ConfJsonClass::reload(const Arguments& args) { + try { + return Boolean::newBoolean(reload()); + } catch (const ordered_json::exception& e) { + logger.error("Fail to parse json content in file!"); + logger.error(ll::string_utils::tou8str(e.what())); + PrintScriptStackTrace(); + return Boolean::newBoolean(false); + } + CATCH("Fail in confJsonReload!"); +} + +Local ConfJsonClass::close(const Arguments& args) { + try { + return Boolean::newBoolean(close()); + } + CATCH("Fail in confJsonClose!"); +} + +Local ConfJsonClass::write(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + bool res = WriteAllFile(confPath, args[0].toStr(), false); + reload(); + return Boolean::newBoolean(res); + } + CATCH("Fail in confJsonWrite!"); } bool ConfJsonClass::flush() { - std::ofstream jsonFile(confPath); - if (jsonFile.is_open()) { - jsonFile << jsonConf.dump(4); - jsonFile.close(); - return true; - } else - return false; + std::ofstream jsonFile(confPath); + if (jsonFile.is_open()) { + jsonFile << jsonConf.dump(4); + jsonFile.close(); + return true; + } else return false; } bool ConfJsonClass::close() { - reload(); - return true; + reload(); + return true; } bool ConfJsonClass::reload() { - auto jsonTexts = ReadAllFile(confPath); - if (!jsonTexts) - return false; + auto jsonTexts = ReadAllFile(confPath); + if (!jsonTexts) return false; - try { - jsonConf = ordered_json::parse(*jsonTexts, nullptr, true, true); - } catch (...) { - logger.error("Fail in confJsonReload!"); - PrintScriptStackTrace(); - } + try { + jsonConf = ordered_json::parse(*jsonTexts, nullptr, true, true); + } catch (...) { + logger.error("Fail in confJsonReload!"); + PrintScriptStackTrace(); + } - return true; + return true; } //////////////////// Classes ConfIni //////////////////// // 生成函数 -ConfIniClass::ConfIniClass(const Local &scriptObj, const string &path, - const string &defContent) - : ScriptClass(scriptObj), ConfBaseClass(path) { - iniConf = SimpleIni::create(path, defContent); +ConfIniClass::ConfIniClass(const Local& scriptObj, const string& path, const string& defContent) +: ScriptClass(scriptObj), + ConfBaseClass(path) { + iniConf = SimpleIni::create(path, defContent); } -ConfIniClass::ConfIniClass(const string &path, const string &defContent) - : ScriptClass(ScriptClass::ConstructFromCpp{}), - ConfBaseClass(path) { - iniConf = SimpleIni::create(path, defContent); +ConfIniClass::ConfIniClass(const string& path, const string& defContent) +: ScriptClass(ScriptClass::ConstructFromCpp{}), + ConfBaseClass(path) { + iniConf = SimpleIni::create(path, defContent); } ConfIniClass::~ConfIniClass() { close(); } -ConfIniClass *ConfIniClass::constructor(const Arguments &args) { - CHECK_ARGS_COUNT_C(args, 1); - CHECK_ARG_TYPE_C(args[0], ValueKind::kString); - if (args.size() >= 2) - CHECK_ARG_TYPE_C(args[1], ValueKind::kString); +ConfIniClass* ConfIniClass::constructor(const Arguments& args) { + CHECK_ARGS_COUNT_C(args, 1); + CHECK_ARG_TYPE_C(args[0], ValueKind::kString); + if (args.size() >= 2) CHECK_ARG_TYPE_C(args[1], ValueKind::kString); - try { - string path = args[0].toStr(); - if (path.empty()) - return nullptr; + try { + string path = args[0].toStr(); + if (path.empty()) return nullptr; - if (args.size() >= 2) - return new ConfIniClass(args.thiz(), path, args[1].toStr()); - else - return new ConfIniClass(args.thiz(), path, ""); - } - CATCH_C("Fail in Open JsonConfigFile!"); + if (args.size() >= 2) return new ConfIniClass(args.thiz(), path, args[1].toStr()); + else return new ConfIniClass(args.thiz(), path, ""); + } + CATCH_C("Fail in Open JsonConfigFile!"); } -bool ConfIniClass::flush() { - return iniConf->SaveFile(iniConf->filePath.c_str(), true); -} +bool ConfIniClass::flush() { return iniConf->SaveFile(iniConf->filePath.c_str(), true); } bool ConfIniClass::close() { - if (isValid()) { - reload(); - delete iniConf; - iniConf = nullptr; - } - return true; + if (isValid()) { + reload(); + delete iniConf; + iniConf = nullptr; + } + return true; } bool ConfIniClass::reload() { - if (!isValid()) - return false; + if (!isValid()) return false; - delete iniConf; - iniConf = SimpleIni::create(confPath, ""); - return true; + delete iniConf; + iniConf = SimpleIni::create(confPath, ""); + return true; } -Local ConfIniClass::init(const Arguments &args) { - CHECK_ARGS_COUNT(args, 3); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); +Local ConfIniClass::init(const Arguments& args) { + CHECK_ARGS_COUNT(args, 3); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); - try { - if (!isValid()) - return Local(); + try { + if (!isValid()) return Local(); + + string section = args[0].toStr(); + string key = args[1].toStr(); + Local res; + + switch (args[2].getKind()) { + case ValueKind::kString: { + string def = args[2].toStr(); + string data = iniConf->getString(section, key, def); + if (data == def) { + iniConf->setString(section, key, def); + flush(); + } + res = String::newString(data); + break; + } + case ValueKind::kNumber: { + if (CheckIsFloat(args[2])) { + // Float + float def = args[2].asNumber().toFloat(); + float data = iniConf->getFloat(section, key, def); + if (data == def) { + iniConf->setFloat(section, key, def); + flush(); + } + res = Number::newNumber(data); + } else { + // Int + int def = args[2].toInt(); + int data = iniConf->getInt(section, key, def); + if (data == def) { + iniConf->setInt(section, key, def); + flush(); + } + res = Number::newNumber(data); + } + break; + } + case ValueKind::kBoolean: { + bool def = args[2].asBoolean().value(); + bool data = iniConf->getBool(section, key, def); + if (data == def) { + iniConf->setBool(section, key, def); + flush(); + } + res = Boolean::newBoolean(data); + break; + } + default: + LOG_ERROR_WITH_SCRIPT_INFO("Ini file don't support this type of data!"); + return Local(); + break; + } + return res; + } + CATCH("Fail in confIniInit!") +} - string section = args[0].toStr(); - string key = args[1].toStr(); - Local res; +Local ConfIniClass::set(const Arguments& args) { + CHECK_ARGS_COUNT(args, 3); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); - switch (args[2].getKind()) { - case ValueKind::kString: { - string def = args[2].toStr(); - string data = iniConf->getString(section, key, def); - if (data == def) { - iniConf->setString(section, key, def); - flush(); - } - res = String::newString(data); - break; - } - case ValueKind::kNumber: { - if (CheckIsFloat(args[2])) { - // Float - float def = args[2].asNumber().toFloat(); - float data = iniConf->getFloat(section, key, def); - if (data == def) { - iniConf->setFloat(section, key, def); - flush(); - } - res = Number::newNumber(data); - } else { - // Int - int def = args[2].toInt(); - int data = iniConf->getInt(section, key, def); - if (data == def) { - iniConf->setInt(section, key, def); - flush(); + try { + if (!isValid()) return Local(); + + string section = args[0].toStr(); + string key = args[1].toStr(); + switch (args[2].getKind()) { + case ValueKind::kString: + iniConf->setString(section, key, args[2].toStr()); + break; + case ValueKind::kNumber: + if (CheckIsFloat(args[2])) iniConf->setFloat(section, key, args[2].asNumber().toFloat()); + else iniConf->setInt(section, key, args[2].toInt()); + break; + case ValueKind::kBoolean: + iniConf->setBool(section, key, args[2].asBoolean().value()); + break; + default: + LOG_ERROR_WITH_SCRIPT_INFO("Ini file don't support this type of data!"); + return Local(); + break; } - res = Number::newNumber(data); - } - break; - } - case ValueKind::kBoolean: { - bool def = args[2].asBoolean().value(); - bool data = iniConf->getBool(section, key, def); - if (data == def) { - iniConf->setBool(section, key, def); flush(); - } - res = Boolean::newBoolean(data); - break; - } - default: - LOG_ERROR_WITH_SCRIPT_INFO("Ini file don't support this type of data!"); - return Local(); - break; - } - return res; - } - CATCH("Fail in confIniInit!") -} - -Local ConfIniClass::set(const Arguments &args) { - CHECK_ARGS_COUNT(args, 3); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - - try { - if (!isValid()) - return Local(); - - string section = args[0].toStr(); - string key = args[1].toStr(); - switch (args[2].getKind()) { - case ValueKind::kString: - iniConf->setString(section, key, args[2].toStr()); - break; - case ValueKind::kNumber: - if (CheckIsFloat(args[2])) - iniConf->setFloat(section, key, args[2].asNumber().toFloat()); - else - iniConf->setInt(section, key, args[2].toInt()); - break; - case ValueKind::kBoolean: - iniConf->setBool(section, key, args[2].asBoolean().value()); - break; - default: - LOG_ERROR_WITH_SCRIPT_INFO("Ini file don't support this type of data!"); - return Local(); - break; - } - flush(); - return Boolean::newBoolean(true); - } - CATCH("Fail in confIniSet!") -} - -Local ConfIniClass::getStr(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - if (args.size() >= 3) - CHECK_ARG_TYPE(args[2], ValueKind::kString) - - try { - if (!isValid()) - return Local(); - - return String::newString( - iniConf->getString(args[0].toStr(), args[1].toStr(), - args.size() >= 3 ? args[2].toStr() : "")); - } - CATCH("Fail in confIniGetStr!") -} - -Local ConfIniClass::getInt(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - if (args.size() >= 3) - CHECK_ARG_TYPE(args[2], ValueKind::kNumber) - - try { - if (!isValid()) - return Local(); - - return Number::newNumber( - iniConf->getInt(args[0].toStr(), args[1].toStr(), - args.size() >= 3 ? args[2].asNumber().toInt32() : 0)); - } - CATCH("Fail in ConfIniGetInt!"); -} - -Local ConfIniClass::getFloat(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - if (args.size() >= 3) - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + return Boolean::newBoolean(true); + } + CATCH("Fail in confIniSet!") +} - try { - if (!isValid()) - return Local(); +Local ConfIniClass::getStr(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + if (args.size() >= 3) CHECK_ARG_TYPE(args[2], ValueKind::kString) - return Number::newNumber(iniConf->getFloat( - args[0].toStr(), args[1].toStr(), - args.size() >= 3 ? (float)args[2].asNumber().toDouble() : 0.0)); - } - CATCH("Fail in ConfIniGetFloat!"); + try { + if (!isValid()) return Local(); + + return String::newString( + iniConf->getString(args[0].toStr(), args[1].toStr(), args.size() >= 3 ? args[2].toStr() : "") + ); + } + CATCH("Fail in confIniGetStr!") } -Local ConfIniClass::getBool(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - if (args.size() >= 3) - CHECK_ARG_TYPE(args[2], ValueKind::kBoolean); +Local ConfIniClass::getInt(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + if (args.size() >= 3) CHECK_ARG_TYPE(args[2], ValueKind::kNumber) - try { - if (!isValid()) - return Local(); + try { + if (!isValid()) return Local(); - return Boolean::newBoolean(iniConf->getBool( - args[0].toStr(), args[1].toStr(), - args.size() >= 3 ? args[2].asBoolean().value() : false)); - } - CATCH("Fail in ConfIniGetBool"); + return Number::newNumber( + iniConf->getInt(args[0].toStr(), args[1].toStr(), args.size() >= 3 ? args[2].asNumber().toInt32() : 0) + ); + } + CATCH("Fail in ConfIniGetInt!"); } -Local ConfIniClass::del(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); +Local ConfIniClass::getFloat(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + if (args.size() >= 3) CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - try { - if (!isValid()) - return Local(); + try { + if (!isValid()) return Local(); - bool res = iniConf->deleteKey(args[0].toStr(), args[1].toStr()); - flush(); - return Boolean::newBoolean(res); - } - CATCH("Fail in confIniDelete!"); + return Number::newNumber(iniConf->getFloat( + args[0].toStr(), + args[1].toStr(), + args.size() >= 3 ? (float)args[2].asNumber().toDouble() : 0.0 + )); + } + CATCH("Fail in ConfIniGetFloat!"); } -Local ConfIniClass::reload(const Arguments &args) { - try { - return Boolean::newBoolean(reload()); - } - CATCH("Fail in confReload!"); +Local ConfIniClass::getBool(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + if (args.size() >= 3) CHECK_ARG_TYPE(args[2], ValueKind::kBoolean); + + try { + if (!isValid()) return Local(); + + return Boolean::newBoolean( + iniConf->getBool(args[0].toStr(), args[1].toStr(), args.size() >= 3 ? args[2].asBoolean().value() : false) + ); + } + CATCH("Fail in ConfIniGetBool"); } -Local ConfIniClass::write(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local ConfIniClass::del(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); - try { - bool res = WriteAllFile(confPath, args[0].toStr(), false); - reload(); - return Boolean::newBoolean(res); - } - CATCH("Fail in confIniWrite!"); + try { + if (!isValid()) return Local(); + + bool res = iniConf->deleteKey(args[0].toStr(), args[1].toStr()); + flush(); + return Boolean::newBoolean(res); + } + CATCH("Fail in confIniDelete!"); } -Local ConfIniClass::close(const Arguments &args) { - try { - return Boolean::newBoolean(close()); - } - CATCH("Fail in confClose!"); +Local ConfIniClass::reload(const Arguments& args) { + try { + return Boolean::newBoolean(reload()); + } + CATCH("Fail in confReload!"); +} + +Local ConfIniClass::write(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + bool res = WriteAllFile(confPath, args[0].toStr(), false); + reload(); + return Boolean::newBoolean(res); + } + CATCH("Fail in confIniWrite!"); +} + +Local ConfIniClass::close(const Arguments& args) { + try { + return Boolean::newBoolean(close()); + } + CATCH("Fail in confClose!"); } //////////////////// APIs //////////////////// -Local MoneyClass::set(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - - try { - return Boolean::newBoolean( - EconomySystem::setMoney(args[0].toStr(), args[1].asNumber().toInt64())); - } catch (const std::invalid_argument &e) { - logger.error("Bad argument in MoneySet!"); - logger.error(ll::string_utils::tou8str(e.what())); - PrintScriptStackTrace(); - return Boolean::newBoolean(false); - } catch (const std::out_of_range &e) { - logger.error("Bad argument in MoneySet!"); - logger.error(ll::string_utils::tou8str(e.what())); - PrintScriptStackTrace(); - return Boolean::newBoolean(false); - } - CATCH("Fail in MoneySet!"); -} - -Local MoneyClass::get(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - return Number::newNumber(EconomySystem::getMoney(args[0].toStr())); - } catch (const std::invalid_argument &e) { - logger.error("Bad argument in MoneyGet!"); - logger.error(ll::string_utils::tou8str(e.what())); - PrintScriptStackTrace(); - return Number::newNumber(0); - } catch (const std::out_of_range &e) { - logger.error("Bad argument in MoneyGet!"); - logger.error(ll::string_utils::tou8str(e.what())); - PrintScriptStackTrace(); - return Number::newNumber(0); - } - CATCH("Fail in MoneyGet!"); -} - -Local MoneyClass::add(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - - try { - return Boolean::newBoolean( - EconomySystem::addMoney(args[0].toStr(), args[1].asNumber().toInt64())); - } catch (const std::invalid_argument &e) { - logger.error("Bad argument in MoneyAdd!"); - logger.error(ll::string_utils::tou8str(e.what())); - PrintScriptStackTrace(); - return Boolean::newBoolean(false); - } catch (const std::out_of_range &e) { - logger.error("Bad argument in MoneyAdd!"); - logger.error(ll::string_utils::tou8str(e.what())); - PrintScriptStackTrace(); - return Boolean::newBoolean(false); - } - CATCH("Fail in MoneyAdd!"); -} - -Local MoneyClass::reduce(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - - try { - return Boolean::newBoolean(EconomySystem::reduceMoney( - args[0].toStr(), args[1].asNumber().toInt64())); - } catch (const std::invalid_argument &e) { - logger.error("Bad argument in MoneyReduce!"); - logger.error(ll::string_utils::tou8str(e.what())); - PrintScriptStackTrace(); - return Boolean::newBoolean(false); - } catch (const std::out_of_range &e) { - logger.error("Bad argument in MoneyReduce!"); - logger.error(ll::string_utils::tou8str(e.what())); - PrintScriptStackTrace(); - return Boolean::newBoolean(false); - } - CATCH("Fail in MoneyReduce!"); -} - -Local MoneyClass::trans(const Arguments &args) { - CHECK_ARGS_COUNT(args, 3); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - - try { - string note = ""; - if (args.size() >= 4 && args[3].getKind() == ValueKind::kString) - note = args[3].toStr(); - return Boolean::newBoolean(EconomySystem::transMoney( - args[0].toStr(), args[1].toStr(), args[2].asNumber().toInt64(), note)); - } catch (const std::invalid_argument &e) { - logger.error("Bad argument in MoneyTrans!"); - logger.error(ll::string_utils::tou8str(e.what())); - PrintScriptStackTrace(); - return Boolean::newBoolean(false); - } catch (const std::out_of_range &e) { - logger.error("Bad argument in MoneyTrans!"); - logger.error(ll::string_utils::tou8str(e.what())); - PrintScriptStackTrace(); - return Boolean::newBoolean(false); - } - CATCH("Fail in MoneyTrans!"); -} - -Local objectificationMoneyHistory(const string &res) { - std::vector listV = - ll::string_utils::splitByPattern(res, "\n"); - std::vector list = - std::vector(listV.begin(), listV.end()); - // from -> to money time (note) - - Local arr = Array::newArray(); - - string from, to, time1, time2, note, tmp; - long long money; - for (auto &str : list) { - if (str.back() == '\n') - str.pop_back(); - - std::istringstream sin(str); - Local obj = Object::newObject(); - - note.clear(); - sin >> from >> tmp >> to >> money >> time1 >> time2; - sin.get(); - getline(sin, note); - if (note.front() == '(') - note.erase(0, 1); - if (note.back() == '\n') - note.pop_back(); - if (note.back() == ')') - note.pop_back(); - - time1 += " " + time2; - - obj.set("from", String::newString(from)); - obj.set("to", String::newString(to)); - obj.set("money", Number::newNumber(money)); - obj.set("time", String::newString(time1)); - obj.set("note", String::newString(note)); - arr.add(obj); - } - return arr; -} - -Local MoneyClass::getHistory(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - - try { - string res{EconomySystem::getMoneyHist(args[0].toStr(), - args[1].asNumber().toInt64())}; - return objectificationMoneyHistory(res); - } catch (const std::invalid_argument &e) { - logger.error("Bad argument in MoneyGetHintory!"); - logger.error(ll::string_utils::tou8str(e.what())); - PrintScriptStackTrace(); - return Local(); - } catch (const std::out_of_range &e) { - logger.error("Bad argument in MoneyGetHintory!"); - logger.error(ll::string_utils::tou8str(e.what())); - PrintScriptStackTrace(); - return Local(); - } - CATCH("Fail in MoneyGetHintory!"); -} - -Local MoneyClass::clearHistory(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - - try { - EconomySystem::clearMoneyHist(args[0].asNumber().toInt64()); - return Boolean::newBoolean(true); - } - CATCH("Fail in MoneyClearHistory!"); -} - -Local DataClass::xuid2name(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - auto playerInfo = ll::service::PlayerInfo::getInstance().fromXuid( - args[0].asString().toString()); - return String::newString(playerInfo ? playerInfo->name : std::string()); - } - CATCH("Fail in XuidToName!"); -} - -Local DataClass::name2xuid(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - auto playerInfo = ll::service::PlayerInfo::getInstance().fromName( - args[0].asString().toString()); - return String::newString(playerInfo ? playerInfo->xuid : std::string()); - } - CATCH("Fail in NameToXuid!"); -} - -Local DataClass::name2uuid(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - auto playerInfo = ll::service::PlayerInfo::getInstance().fromName( - args[0].asString().toString()); - return String::newString(playerInfo ? playerInfo->uuid.asString() - : std::string()); - } - CATCH("Fail in NameToUuid!"); -} - -Local DataClass::xuid2uuid(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - auto playerInfo = ll::service::PlayerInfo::getInstance().fromXuid( - args[0].asString().toString()); - return String::newString(playerInfo ? playerInfo->uuid.asString() - : std::string()); - } - CATCH("Fail in XuidToUuid!"); +Local MoneyClass::set(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + + try { + return Boolean::newBoolean(EconomySystem::setMoney(args[0].toStr(), args[1].asNumber().toInt64())); + } catch (const std::invalid_argument& e) { + logger.error("Bad argument in MoneySet!"); + logger.error(ll::string_utils::tou8str(e.what())); + PrintScriptStackTrace(); + return Boolean::newBoolean(false); + } catch (const std::out_of_range& e) { + logger.error("Bad argument in MoneySet!"); + logger.error(ll::string_utils::tou8str(e.what())); + PrintScriptStackTrace(); + return Boolean::newBoolean(false); + } + CATCH("Fail in MoneySet!"); +} + +Local MoneyClass::get(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + return Number::newNumber(EconomySystem::getMoney(args[0].toStr())); + } catch (const std::invalid_argument& e) { + logger.error("Bad argument in MoneyGet!"); + logger.error(ll::string_utils::tou8str(e.what())); + PrintScriptStackTrace(); + return Number::newNumber(0); + } catch (const std::out_of_range& e) { + logger.error("Bad argument in MoneyGet!"); + logger.error(ll::string_utils::tou8str(e.what())); + PrintScriptStackTrace(); + return Number::newNumber(0); + } + CATCH("Fail in MoneyGet!"); +} + +Local MoneyClass::add(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + + try { + return Boolean::newBoolean(EconomySystem::addMoney(args[0].toStr(), args[1].asNumber().toInt64())); + } catch (const std::invalid_argument& e) { + logger.error("Bad argument in MoneyAdd!"); + logger.error(ll::string_utils::tou8str(e.what())); + PrintScriptStackTrace(); + return Boolean::newBoolean(false); + } catch (const std::out_of_range& e) { + logger.error("Bad argument in MoneyAdd!"); + logger.error(ll::string_utils::tou8str(e.what())); + PrintScriptStackTrace(); + return Boolean::newBoolean(false); + } + CATCH("Fail in MoneyAdd!"); +} + +Local MoneyClass::reduce(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + + try { + return Boolean::newBoolean(EconomySystem::reduceMoney(args[0].toStr(), args[1].asNumber().toInt64())); + } catch (const std::invalid_argument& e) { + logger.error("Bad argument in MoneyReduce!"); + logger.error(ll::string_utils::tou8str(e.what())); + PrintScriptStackTrace(); + return Boolean::newBoolean(false); + } catch (const std::out_of_range& e) { + logger.error("Bad argument in MoneyReduce!"); + logger.error(ll::string_utils::tou8str(e.what())); + PrintScriptStackTrace(); + return Boolean::newBoolean(false); + } + CATCH("Fail in MoneyReduce!"); +} + +Local MoneyClass::trans(const Arguments& args) { + CHECK_ARGS_COUNT(args, 3); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + + try { + string note = ""; + if (args.size() >= 4 && args[3].getKind() == ValueKind::kString) note = args[3].toStr(); + return Boolean::newBoolean( + EconomySystem::transMoney(args[0].toStr(), args[1].toStr(), args[2].asNumber().toInt64(), note) + ); + } catch (const std::invalid_argument& e) { + logger.error("Bad argument in MoneyTrans!"); + logger.error(ll::string_utils::tou8str(e.what())); + PrintScriptStackTrace(); + return Boolean::newBoolean(false); + } catch (const std::out_of_range& e) { + logger.error("Bad argument in MoneyTrans!"); + logger.error(ll::string_utils::tou8str(e.what())); + PrintScriptStackTrace(); + return Boolean::newBoolean(false); + } + CATCH("Fail in MoneyTrans!"); +} + +Local objectificationMoneyHistory(const string& res) { + std::vector listV = ll::string_utils::splitByPattern(res, "\n"); + std::vector list = std::vector(listV.begin(), listV.end()); + // from -> to money time (note) + + Local arr = Array::newArray(); + + string from, to, time1, time2, note, tmp; + long long money; + for (auto& str : list) { + if (str.back() == '\n') str.pop_back(); + + std::istringstream sin(str); + Local obj = Object::newObject(); + + note.clear(); + sin >> from >> tmp >> to >> money >> time1 >> time2; + sin.get(); + getline(sin, note); + if (note.front() == '(') note.erase(0, 1); + if (note.back() == '\n') note.pop_back(); + if (note.back() == ')') note.pop_back(); + + time1 += " " + time2; + + obj.set("from", String::newString(from)); + obj.set("to", String::newString(to)); + obj.set("money", Number::newNumber(money)); + obj.set("time", String::newString(time1)); + obj.set("note", String::newString(note)); + arr.add(obj); + } + return arr; +} + +Local MoneyClass::getHistory(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + + try { + string res{EconomySystem::getMoneyHist(args[0].toStr(), args[1].asNumber().toInt64())}; + return objectificationMoneyHistory(res); + } catch (const std::invalid_argument& e) { + logger.error("Bad argument in MoneyGetHintory!"); + logger.error(ll::string_utils::tou8str(e.what())); + PrintScriptStackTrace(); + return Local(); + } catch (const std::out_of_range& e) { + logger.error("Bad argument in MoneyGetHintory!"); + logger.error(ll::string_utils::tou8str(e.what())); + PrintScriptStackTrace(); + return Local(); + } + CATCH("Fail in MoneyGetHintory!"); +} + +Local MoneyClass::clearHistory(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + + try { + EconomySystem::clearMoneyHist(args[0].asNumber().toInt64()); + return Boolean::newBoolean(true); + } + CATCH("Fail in MoneyClearHistory!"); +} + +Local DataClass::xuid2name(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + auto playerInfo = ll::service::PlayerInfo::getInstance().fromXuid(args[0].asString().toString()); + return String::newString(playerInfo ? playerInfo->name : std::string()); + } + CATCH("Fail in XuidToName!"); +} + +Local DataClass::name2xuid(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + auto playerInfo = ll::service::PlayerInfo::getInstance().fromName(args[0].asString().toString()); + return String::newString(playerInfo ? playerInfo->xuid : std::string()); + } + CATCH("Fail in NameToXuid!"); +} + +Local DataClass::name2uuid(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + auto playerInfo = ll::service::PlayerInfo::getInstance().fromName(args[0].asString().toString()); + return String::newString(playerInfo ? playerInfo->uuid.asString() : std::string()); + } + CATCH("Fail in NameToUuid!"); +} + +Local DataClass::xuid2uuid(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + auto playerInfo = ll::service::PlayerInfo::getInstance().fromXuid(args[0].asString().toString()); + return String::newString(playerInfo ? playerInfo->uuid.asString() : std::string()); + } + CATCH("Fail in XuidToUuid!"); } // Unsupported @@ -794,190 +753,172 @@ Local DataClass::xuid2uuid(const Arguments &args) { // CATCH("Fail in getAllPlayerInfo!"); // } -Local DataClass::toJson(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - if (args.size() >= 2) - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); +Local DataClass::toJson(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + if (args.size() >= 2) CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - try { - int spaces = -1; - if (args.size() >= 2) { - int newSpaces = args[1].toInt(); - if (newSpaces > 0) - spaces = newSpaces; + try { + int spaces = -1; + if (args.size() >= 2) { + int newSpaces = args[1].toInt(); + if (newSpaces > 0) spaces = newSpaces; + } + try { + return String::newString(ValueToJson(args[0], spaces)); + } catch (...) { + LOG_ERROR_WITH_SCRIPT_INFO("Failed to transform into Json."); + return Local(); + } } + CATCH("Fail in ToJson!"); +} + +Local DataClass::parseJson(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + try { - return String::newString(ValueToJson(args[0], spaces)); - } catch (...) { - LOG_ERROR_WITH_SCRIPT_INFO("Failed to transform into Json."); - return Local(); + try { + return JsonToValue(args[0].toStr()); + } catch (...) { + LOG_ERROR_WITH_SCRIPT_INFO("Failed to parse from Json."); + return Local(); + } } - } - CATCH("Fail in ToJson!"); + CATCH("Fail in ParseJson!"); } -Local DataClass::parseJson(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local DataClass::toMD5(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); - try { try { - return JsonToValue(args[0].toStr()); - } catch (...) { - LOG_ERROR_WITH_SCRIPT_INFO("Failed to parse from Json."); - return Local(); - } - } - CATCH("Fail in ParseJson!"); -} - -Local DataClass::toMD5(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - - try { - string data; - if (args[0].isString()) - data = args[0].toStr(); - else if (args[0].isByteBuffer()) { - Local buf = args[0].asByteBuffer(); - data = string((char *)buf.getRawBytes(), buf.byteLength()); - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - return String::newString(ll::crypto_utils::md5(data)); - } - CATCH("Fail in ToMD5!"); -} - -Local DataClass::toSHA1(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - - try { - string data; - if (args[0].isString()) - data = args[0].toStr(); - else if (args[0].isByteBuffer()) { - Local buf = args[0].asByteBuffer(); - data = string((char *)buf.getRawBytes(), buf.byteLength()); - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - return String::newString(ll::crypto_utils::sha1(data)); - } - CATCH("Fail in ToSHA1!"); -} - -Local DataClass::toBase64(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - - try { - string data; - if (args[0].isString()) - data = args[0].toStr(); - else if (args[0].isByteBuffer()) { - Local buf = args[0].asByteBuffer(); - data = string((char *)buf.getRawBytes(), buf.byteLength()); - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - return String::newString(Base64::Encode(data)); - } - CATCH("Fail in ToBase64!"); -} - -Local DataClass::fromBase64(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - bool isBinary = false; - if (args.size() > 1) { - CHECK_ARG_TYPE(args[1], ValueKind::kBoolean); - isBinary = args[1].asBoolean().value(); - } - auto data = Base64::Decode(args[0].toStr()); - if (isBinary) { - return ByteBuffer::newByteBuffer((void *)data.c_str(), data.size()); - } else { - return String::newString(data); - } - } - CATCH("Fail in FromBase64!"); + string data; + if (args[0].isString()) data = args[0].toStr(); + else if (args[0].isByteBuffer()) { + Local buf = args[0].asByteBuffer(); + data = string((char*)buf.getRawBytes(), buf.byteLength()); + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + return String::newString(ll::crypto_utils::md5(data)); + } + CATCH("Fail in ToMD5!"); } -// For Compability +Local DataClass::toSHA1(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); -Local KVDBClass::newDb(const string &dir) { - auto newp = new KVDBClass(dir); + try { + string data; + if (args[0].isString()) data = args[0].toStr(); + else if (args[0].isByteBuffer()) { + Local buf = args[0].asByteBuffer(); + data = string((char*)buf.getRawBytes(), buf.byteLength()); + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + return String::newString(ll::crypto_utils::sha1(data)); + } + CATCH("Fail in ToSHA1!"); +} - if (newp->isValid()) - return newp->getScriptObject(); - else { - delete newp; - return Local(); - } +Local DataClass::toBase64(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + + try { + string data; + if (args[0].isString()) data = args[0].toStr(); + else if (args[0].isByteBuffer()) { + Local buf = args[0].asByteBuffer(); + data = string((char*)buf.getRawBytes(), buf.byteLength()); + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + return String::newString(Base64::Encode(data)); + } + CATCH("Fail in ToBase64!"); } -Local ConfJsonClass::newConf(const string &path, - const string &defContent) { - auto newp = new ConfJsonClass(path, defContent); - return newp->getScriptObject(); +Local DataClass::fromBase64(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + bool isBinary = false; + if (args.size() > 1) { + CHECK_ARG_TYPE(args[1], ValueKind::kBoolean); + isBinary = args[1].asBoolean().value(); + } + auto data = Base64::Decode(args[0].toStr()); + if (isBinary) { + return ByteBuffer::newByteBuffer((void*)data.c_str(), data.size()); + } else { + return String::newString(data); + } + } + CATCH("Fail in FromBase64!"); } -Local ConfIniClass::newConf(const string &path, - const string &defContent) { - auto newp = new ConfIniClass(path, defContent); - if (newp) +// For Compability + +Local KVDBClass::newDb(const string& dir) { + auto newp = new KVDBClass(dir); + + if (newp->isValid()) return newp->getScriptObject(); + else { + delete newp; + return Local(); + } +} + +Local ConfJsonClass::newConf(const string& path, const string& defContent) { + auto newp = new ConfJsonClass(path, defContent); return newp->getScriptObject(); - else - return Local(); } -Local DataClass::openConfig(const Arguments &args) { - enum GlobalConfType { json, ini }; +Local ConfIniClass::newConf(const string& path, const string& defContent) { + auto newp = new ConfIniClass(path, defContent); + if (newp) return newp->getScriptObject(); + else return Local(); +} - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - if (args.size() >= 2) - CHECK_ARG_TYPE(args[1], ValueKind::kString); - if (args.size() >= 3) - CHECK_ARG_TYPE(args[2], ValueKind::kString); +Local DataClass::openConfig(const Arguments& args) { + enum GlobalConfType { json, ini }; - try { - string path = args[0].toStr(); - GlobalConfType confType = GlobalConfType::ini; + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + if (args.size() >= 2) CHECK_ARG_TYPE(args[1], ValueKind::kString); + if (args.size() >= 3) CHECK_ARG_TYPE(args[2], ValueKind::kString); - if (path.empty()) - return Boolean::newBoolean(false); + try { + string path = args[0].toStr(); + GlobalConfType confType = GlobalConfType::ini; - if (args.size() >= 2) { - string fileType = args[1].toStr(); - if (fileType == "json" || fileType == "Json") - confType = GlobalConfType::json; - } + if (path.empty()) return Boolean::newBoolean(false); - if (confType == GlobalConfType::ini) { - if (args.size() >= 3) - return ConfIniClass::newConf(path, args[2].toStr()); - else - return ConfIniClass::newConf(path); - } else // json - { - if (args.size() >= 3) - return ConfJsonClass::newConf(path, args[2].toStr()); - else - return ConfJsonClass::newConf(path, "{}"); + if (args.size() >= 2) { + string fileType = args[1].toStr(); + if (fileType == "json" || fileType == "Json") confType = GlobalConfType::json; + } + + if (confType == GlobalConfType::ini) { + if (args.size() >= 3) return ConfIniClass::newConf(path, args[2].toStr()); + else return ConfIniClass::newConf(path); + } else // json + { + if (args.size() >= 3) return ConfJsonClass::newConf(path, args[2].toStr()); + else return ConfJsonClass::newConf(path, "{}"); + } } - } - CATCH("Fail in OpenConfig!"); + CATCH("Fail in OpenConfig!"); } -Local DataClass::openDB(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local DataClass::openDB(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - return KVDBClass::newDb(args[0].toStr()); + return KVDBClass::newDb(args[0].toStr()); } diff --git a/src/api/DataAPI.h b/src/api/DataAPI.h index 3b8ced4d..11a43a04 100644 --- a/src/api/DataAPI.h +++ b/src/api/DataAPI.h @@ -50,18 +50,18 @@ extern ClassDefine MoneyClassBuilder; class ConfBaseClass { protected: - std::string confPath; - virtual bool flush() = 0; - virtual bool close() = 0; + std::string confPath; + virtual bool flush() = 0; + virtual bool close() = 0; virtual bool reload() = 0; public: explicit ConfBaseClass(const string& dir); virtual Local reload(const Arguments& args) = 0; - virtual Local close(const Arguments& args) = 0; - Local getPath(const Arguments& args); - Local read(const Arguments& args); + virtual Local close(const Arguments& args) = 0; + Local getPath(const Arguments& args); + Local read(const Arguments& args); virtual Local write(const Arguments& args) = 0; }; @@ -69,9 +69,9 @@ class ConfBaseClass { class ConfJsonClass : public ScriptClass, public ConfBaseClass { private: ordered_json jsonConf; - bool flush() override; - bool close() override; - bool reload() override; + bool flush() override; + bool close() override; + bool reload() override; public: explicit ConfJsonClass(const Local& scriptObj, const string& path, const string& defContent); @@ -79,10 +79,10 @@ class ConfJsonClass : public ScriptClass, public ConfBaseClass { ~ConfJsonClass(); static ConfJsonClass* constructor(const Arguments& args); - Local init(const Arguments& args); - Local get(const Arguments& args); - Local set(const Arguments& args); - Local del(const Arguments& args); + Local init(const Arguments& args); + Local get(const Arguments& args); + Local set(const Arguments& args); + Local del(const Arguments& args); virtual Local reload(const Arguments& args) override; virtual Local close(const Arguments& args) override; virtual Local write(const Arguments& args) override; @@ -96,9 +96,9 @@ extern ClassDefine ConfJsonClassBuilder; class ConfIniClass : public ScriptClass, public ConfBaseClass { private: SimpleIni* iniConf; - bool flush() override; - bool close() override; - bool reload() override; + bool flush() override; + bool close() override; + bool reload() override; public: explicit ConfIniClass(const Local& scriptObj, const string& path, const string& defContent); @@ -106,17 +106,15 @@ class ConfIniClass : public ScriptClass, public ConfBaseClass { ~ConfIniClass(); static ConfIniClass* constructor(const Arguments& args); - bool isValid() { - return iniConf != nullptr; - } - - Local init(const Arguments& args); - Local set(const Arguments& args); - Local getStr(const Arguments& args); - Local getInt(const Arguments& args); - Local getFloat(const Arguments& args); - Local getBool(const Arguments& args); - Local del(const Arguments& args); + bool isValid() { return iniConf != nullptr; } + + Local init(const Arguments& args); + Local set(const Arguments& args); + Local getStr(const Arguments& args); + Local getInt(const Arguments& args); + Local getFloat(const Arguments& args); + Local getBool(const Arguments& args); + Local del(const Arguments& args); virtual Local reload(const Arguments& args) override; virtual Local close(const Arguments& args) override; virtual Local write(const Arguments& args) override; diff --git a/src/api/DatabaseAPI.cpp b/src/api/DatabaseAPI.cpp index ffdca74a..059ff9ba 100644 --- a/src/api/DatabaseAPI.cpp +++ b/src/api/DatabaseAPI.cpp @@ -1,544 +1,517 @@ #include "api/DatabaseAPI.h" using namespace DB; -#define CATCH_AND_THROW(LOG) \ - catch (const Exception &e) { \ - logger.error(LOG##"\n"); \ - PrintException(e); \ - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); \ - return Local(); \ - } \ - catch (const std::exception &e) { \ - throw Exception(ll::string_utils::tou8str(e.what())); \ - } \ - catch (...) { \ - logger.error("Uncaught Exception Detected!"); \ - PrintScriptStackTrace(); \ - logger.error("In API: " __FUNCTION__); \ - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); \ - return Local(); \ - } +#define CATCH_AND_THROW(LOG) \ + catch (const Exception& e) { \ + logger.error(LOG##"\n"); \ + PrintException(e); \ + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); \ + return Local(); \ + } \ + catch (const std::exception& e) { \ + throw Exception(ll::string_utils::tou8str(e.what())); \ + } \ + catch (...) { \ + logger.error("Uncaught Exception Detected!"); \ + PrintScriptStackTrace(); \ + logger.error("In API: " __FUNCTION__); \ + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); \ + return Local(); \ + } //////////////////// Class Definition //////////////////// -ClassDefine KVDBClassBuilder = - defineClass("KVDatabase") - .constructor(&KVDBClass::constructor) - .instanceFunction("get", &KVDBClass::get) - .instanceFunction("set", &KVDBClass::set) - .instanceFunction("delete", &KVDBClass::del) - .instanceFunction("close", &KVDBClass::close) - .instanceFunction("listKey", &KVDBClass::listKey) - .build(); - -ClassDefine DBSessionClassBuilder = - defineClass("DBSession") - .constructor(&DBSessionClass::constructor) - .instanceFunction("query", &DBSessionClass::query) - .instanceFunction("exec", &DBSessionClass::exec) - .instanceFunction("execute", &DBSessionClass::exec) - .instanceFunction("prepare", &DBSessionClass::prepare) - .instanceFunction("close", &DBSessionClass::close) - .instanceFunction("isOpen", &DBSessionClass::isOpen) - .build(); - -ClassDefine DBStmtClassBuilder = - defineClass("DBStmt") - .constructor(nullptr) - .instanceProperty("affectedRows", &DBStmtClass::getAffectedRows) - .instanceProperty("insertId", &DBStmtClass::getInsertId) - - .instanceFunction("bind", &DBStmtClass::bind) - .instanceFunction("execute", &DBStmtClass::execute) - .instanceFunction("step", &DBStmtClass::step) - .instanceFunction("fetch", &DBStmtClass::fetch) - .instanceFunction("fetchAll", &DBStmtClass::fetchAll) - .instanceFunction("reset", &DBStmtClass::reset) - .instanceFunction("reexec", &DBStmtClass::reexec) - .instanceFunction("clear", &DBStmtClass::clear) - .build(); +ClassDefine KVDBClassBuilder = defineClass("KVDatabase") + .constructor(&KVDBClass::constructor) + .instanceFunction("get", &KVDBClass::get) + .instanceFunction("set", &KVDBClass::set) + .instanceFunction("delete", &KVDBClass::del) + .instanceFunction("close", &KVDBClass::close) + .instanceFunction("listKey", &KVDBClass::listKey) + .build(); + +ClassDefine DBSessionClassBuilder = defineClass("DBSession") + .constructor(&DBSessionClass::constructor) + .instanceFunction("query", &DBSessionClass::query) + .instanceFunction("exec", &DBSessionClass::exec) + .instanceFunction("execute", &DBSessionClass::exec) + .instanceFunction("prepare", &DBSessionClass::prepare) + .instanceFunction("close", &DBSessionClass::close) + .instanceFunction("isOpen", &DBSessionClass::isOpen) + .build(); + +ClassDefine DBStmtClassBuilder = defineClass("DBStmt") + .constructor(nullptr) + .instanceProperty("affectedRows", &DBStmtClass::getAffectedRows) + .instanceProperty("insertId", &DBStmtClass::getInsertId) + + .instanceFunction("bind", &DBStmtClass::bind) + .instanceFunction("execute", &DBStmtClass::execute) + .instanceFunction("step", &DBStmtClass::step) + .instanceFunction("fetch", &DBStmtClass::fetch) + .instanceFunction("fetchAll", &DBStmtClass::fetchAll) + .instanceFunction("reset", &DBStmtClass::reset) + .instanceFunction("reexec", &DBStmtClass::reexec) + .instanceFunction("clear", &DBStmtClass::clear) + .build(); //////////////////// Functions //////////////////// -Any LocalValueToAny(const Local &val) { - switch (val.getKind()) { - case ValueKind::kObject: - case ValueKind::kArray: - throw std::exception("Cannot convert script object(array) to Any"); - case ValueKind::kNull: - case ValueKind::kUnsupported: - return Any(); - case ValueKind::kBoolean: - return Any(val.asBoolean().value()); - case ValueKind::kNumber: - if (CheckIsFloat(val.asNumber())) - return Any(val.asNumber().toDouble()); - else - return Any(val.asNumber().toInt64()); - case ValueKind::kString: - return Any(val.asString().toString()); - case ValueKind::kByteBuffer: - switch (val.asByteBuffer().getType()) { - case ByteBuffer::Type::kInt8: - case ByteBuffer::Type::kUint8: { - auto buf = (uint8_t *)val.asByteBuffer().getRawBytes(); - return Any(ByteArray(buf, buf + val.asByteBuffer().elementCount())); - } +Any LocalValueToAny(const Local& val) { + switch (val.getKind()) { + case ValueKind::kObject: + case ValueKind::kArray: + throw std::exception("Cannot convert script object(array) to Any"); + case ValueKind::kNull: + case ValueKind::kUnsupported: + return Any(); + case ValueKind::kBoolean: + return Any(val.asBoolean().value()); + case ValueKind::kNumber: + if (CheckIsFloat(val.asNumber())) return Any(val.asNumber().toDouble()); + else return Any(val.asNumber().toInt64()); + case ValueKind::kString: + return Any(val.asString().toString()); + case ValueKind::kByteBuffer: + switch (val.asByteBuffer().getType()) { + case ByteBuffer::Type::kInt8: + case ByteBuffer::Type::kUint8: { + auto buf = (uint8_t*)val.asByteBuffer().getRawBytes(); + return Any(ByteArray(buf, buf + val.asByteBuffer().elementCount())); + } + default: + break; + } + break; default: - break; + break; } - break; - default: - break; - } - return Any(); + return Any(); } -template <> Local any_to(const Any &val) { - switch (val.type) { - case Any::Type::Null: +template <> +Local any_to(const Any& val) { + switch (val.type) { + case Any::Type::Null: + return Local(); + case Any::Type::Boolean: + return Boolean::newBoolean(val.value.boolean); + case Any::Type::Integer: + return Number::newNumber(val.value.integer); + case Any::Type::UInteger: + if (val.value.uinteger > LLONG_MAX) return Number::newNumber((double)val.value.uinteger); + return Number::newNumber((int64_t)val.value.uinteger); + case Any::Type::Floating: + return Number::newNumber(val.value.floating); + case Any::Type::String: + return String::newString(*val.value.string); + case Any::Type::Date: { + auto obj = Object::newObject(); + obj.set("Y", val.value.date->year); + obj.set("M", val.value.date->month); + obj.set("D", val.value.date->day); + return obj; + } + case Any::Type::Time: { + auto obj = Object::newObject(); + obj.set("h", val.value.time->hour); + obj.set("m", val.value.time->minute); + obj.set("s", val.value.time->second); + return obj; + } + case Any::Type::DateTime: { + auto obj = Object::newObject(); + obj.set("Y", val.value.datetime->date.year); + obj.set("M", val.value.datetime->date.month); + obj.set("D", val.value.datetime->date.day); + obj.set("h", val.value.datetime->time.hour); + obj.set("m", val.value.datetime->time.minute); + obj.set("s", val.value.datetime->time.second); + return obj; + } + case Any::Type::Blob: + return String::newString(val.get()); + default: + break; + } return Local(); - case Any::Type::Boolean: - return Boolean::newBoolean(val.value.boolean); - case Any::Type::Integer: - return Number::newNumber(val.value.integer); - case Any::Type::UInteger: - if (val.value.uinteger > LLONG_MAX) - return Number::newNumber((double)val.value.uinteger); - return Number::newNumber((int64_t)val.value.uinteger); - case Any::Type::Floating: - return Number::newNumber(val.value.floating); - case Any::Type::String: - return String::newString(*val.value.string); - case Any::Type::Date: { - auto obj = Object::newObject(); - obj.set("Y", val.value.date->year); - obj.set("M", val.value.date->month); - obj.set("D", val.value.date->day); - return obj; - } - case Any::Type::Time: { - auto obj = Object::newObject(); - obj.set("h", val.value.time->hour); - obj.set("m", val.value.time->minute); - obj.set("s", val.value.time->second); - return obj; - } - case Any::Type::DateTime: { - auto obj = Object::newObject(); - obj.set("Y", val.value.datetime->date.year); - obj.set("M", val.value.datetime->date.month); - obj.set("D", val.value.datetime->date.day); - obj.set("h", val.value.datetime->time.hour); - obj.set("m", val.value.datetime->time.minute); - obj.set("s", val.value.datetime->time.second); - return obj; - } - case Any::Type::Blob: - return String::newString(val.get()); - default: - break; - } - return Local(); } -Local RowSetToLocalValue(const RowSet &rows) { - if (rows.empty() || !rows.header) { - return Local(); - } - Local arr = Array::newArray(); - Local header = Array::newArray(); - for (auto &col : *rows.header) - header.add(String::newString(col)); - arr.add(header); - for (auto &row : rows) { - Local rowValues = Array::newArray(); - for (auto &col : row) - rowValues.add(col.get>()); - arr.add(rowValues); - } - return arr; +Local RowSetToLocalValue(const RowSet& rows) { + if (rows.empty() || !rows.header) { + return Local(); + } + Local arr = Array::newArray(); + Local header = Array::newArray(); + for (auto& col : *rows.header) header.add(String::newString(col)); + arr.add(header); + for (auto& row : rows) { + Local rowValues = Array::newArray(); + for (auto& col : row) rowValues.add(col.get>()); + arr.add(rowValues); + } + return arr; } -Local RowToLocalValue(const Row &row) { - auto result = Object::newObject(); - row.forEach([&](const std::string &key, const Any &value) { - result.set(key, value.get>()); - return true; - }); - return result; +Local RowToLocalValue(const Row& row) { + auto result = Object::newObject(); + row.forEach([&](const std::string& key, const Any& value) { + result.set(key, value.get>()); + return true; + }); + return result; } //////////////////// Classes KVDB //////////////////// // 生成函数 -KVDBClass::KVDBClass(const Local &scriptObj, const string &dir) - : ScriptClass(scriptObj) { - try{ - kvdb = std::make_unique(dir); - }catch(...){ - kvdb.reset(); - } +KVDBClass::KVDBClass(const Local& scriptObj, const string& dir) : ScriptClass(scriptObj) { + try { + kvdb = std::make_unique(dir); + } catch (...) { + kvdb.reset(); + } - unloadCallbackIndex = ENGINE_OWN_DATA()->addUnloadCallback( - [&](ScriptEngine *engine) { kvdb.reset(); }); + unloadCallbackIndex = ENGINE_OWN_DATA()->addUnloadCallback([&](ScriptEngine* engine) { kvdb.reset(); }); } -KVDBClass::KVDBClass(const string &dir) - : ScriptClass(script::ScriptClass::ConstructFromCpp{}) { try{ - kvdb = std::make_unique(dir); - }catch(...){ - kvdb.reset(); - } - unloadCallbackIndex = ENGINE_OWN_DATA()->addUnloadCallback( - [&](ScriptEngine *engine) { kvdb.reset(); }); +KVDBClass::KVDBClass(const string& dir) : ScriptClass(script::ScriptClass::ConstructFromCpp{}) { + try { + kvdb = std::make_unique(dir); + } catch (...) { + kvdb.reset(); + } + unloadCallbackIndex = ENGINE_OWN_DATA()->addUnloadCallback([&](ScriptEngine* engine) { kvdb.reset(); }); } KVDBClass::~KVDBClass() {} -KVDBClass *KVDBClass::constructor(const Arguments &args) { - CHECK_ARGS_COUNT_C(args, 1); - CHECK_ARG_TYPE_C(args[0], ValueKind::kString); - - try { - auto res = new KVDBClass(args.thiz(), args[0].toStr()); - if (res->isValid()) - return res; - else - return nullptr; - } - CATCH_C("Fail in Open Database!"); +KVDBClass* KVDBClass::constructor(const Arguments& args) { + CHECK_ARGS_COUNT_C(args, 1); + CHECK_ARG_TYPE_C(args[0], ValueKind::kString); + + try { + auto res = new KVDBClass(args.thiz(), args[0].toStr()); + if (res->isValid()) return res; + else return nullptr; + } + CATCH_C("Fail in Open Database!"); } -Local KVDBClass::get(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local KVDBClass::get(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - if (!isValid()) - return Local(); + try { + if (!isValid()) return Local(); - auto res = kvdb->get(args[0].asString().toString()); - if (!res) - return Local(); + auto res = kvdb->get(args[0].asString().toString()); + if (!res) return Local(); - return JsonToValue(*res); - } - CATCH_AND_THROW("Fail in DbGet!"); + return JsonToValue(*res); + } + CATCH_AND_THROW("Fail in DbGet!"); } -Local KVDBClass::set(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local KVDBClass::set(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - if (!isValid()) - return Local(); + try { + if (!isValid()) return Local(); - kvdb->set(args[0].asString().toString(), ValueToJson(args[1])); - return Boolean::newBoolean(true); - } - CATCH_AND_THROW("Fail in DbSet!"); + kvdb->set(args[0].asString().toString(), ValueToJson(args[1])); + return Boolean::newBoolean(true); + } + CATCH_AND_THROW("Fail in DbSet!"); } -Local KVDBClass::del(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local KVDBClass::del(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - if (!isValid()) - return Local(); + try { + if (!isValid()) return Local(); - return Boolean::newBoolean(kvdb->del(args[0].asString().toString())); - } - CATCH_AND_THROW("Fail in DbDel!"); + return Boolean::newBoolean(kvdb->del(args[0].asString().toString())); + } + CATCH_AND_THROW("Fail in DbDel!"); } -Local KVDBClass::close(const Arguments &args) { - ENGINE_OWN_DATA()->removeUnloadCallback(unloadCallbackIndex); - unloadCallbackIndex = -1; - try { - kvdb.reset(); - return Boolean::newBoolean(true); - } - CATCH_AND_THROW("Fail in DbClose!"); +Local KVDBClass::close(const Arguments& args) { + ENGINE_OWN_DATA()->removeUnloadCallback(unloadCallbackIndex); + unloadCallbackIndex = -1; + try { + kvdb.reset(); + return Boolean::newBoolean(true); + } + CATCH_AND_THROW("Fail in DbClose!"); } -Local KVDBClass::listKey(const Arguments &args) { - try { - if (!isValid()) - return Local(); +Local KVDBClass::listKey(const Arguments& args) { + try { + if (!isValid()) return Local(); - auto list = kvdb->getAllKeys(); - Local arr = Array::newArray(); - for (auto &key : list) { - arr.add(String::newString(key)); + auto list = kvdb->getAllKeys(); + Local arr = Array::newArray(); + for (auto& key : list) { + arr.add(String::newString(key)); + } + return arr; } - return arr; - } - CATCH_AND_THROW("Fail in DbListKey!"); + CATCH_AND_THROW("Fail in DbListKey!"); } //////////////////// Classes DBSession //////////////////// // 生成函数 -DBSessionClass::DBSessionClass(const Local &scriptObj, - const ConnParams ¶ms) - : ScriptClass(scriptObj), session(Session::create(params)) { - session->setDebugOutput(true); +DBSessionClass::DBSessionClass(const Local& scriptObj, const ConnParams& params) +: ScriptClass(scriptObj), + session(Session::create(params)) { + session->setDebugOutput(true); } -DBSessionClass::DBSessionClass(const ConnParams ¶ms) - : ScriptClass(script::ScriptClass::ConstructFromCpp{}), - session(Session::create(params)) { - session->setDebugOutput(true); +DBSessionClass::DBSessionClass(const ConnParams& params) +: ScriptClass(script::ScriptClass::ConstructFromCpp{}), + session(Session::create(params)) { + session->setDebugOutput(true); } DBSessionClass::~DBSessionClass() {} -DBSessionClass *DBSessionClass::constructor(const Arguments &args) { - try { - DBSessionClass *result = nullptr; - switch (args.size()) { - case 1: { - // When the first argument is a string, it is a url or file path. - if (args[0].isString()) { - result = new DBSessionClass(args.thiz(), - ConnParams(args[0].asString().toString())); - } else if (args[0].isObject()) { - auto obj = args[0].asObject(); - ConnParams params; - for (auto &key : obj.getKeys()) - params[key.toString()] = LocalValueToAny(obj.get(key)); - result = new DBSessionClass(args.thiz(), params); - } else { - LOG_WRONG_ARG_TYPE(); - } - break; - } - case 2: { - CHECK_ARG_TYPE_C(args[0], ValueKind::kString); - CHECK_ARG_TYPE_C(args[1], ValueKind::kObject); - auto obj = args[1].asObject(); - ConnParams params; - params["type"] = args[0].asString().toString(); - for (auto &key : obj.getKeys()) - params[key.toString()] = LocalValueToAny(obj.get(key)); - result = new DBSessionClass(args.thiz(), ConnParams(params)); - break; - } - default: - LOG_WRONG_ARG_TYPE(); - break; +DBSessionClass* DBSessionClass::constructor(const Arguments& args) { + try { + DBSessionClass* result = nullptr; + switch (args.size()) { + case 1: { + // When the first argument is a string, it is a url or file path. + if (args[0].isString()) { + result = new DBSessionClass(args.thiz(), ConnParams(args[0].asString().toString())); + } else if (args[0].isObject()) { + auto obj = args[0].asObject(); + ConnParams params; + for (auto& key : obj.getKeys()) params[key.toString()] = LocalValueToAny(obj.get(key)); + result = new DBSessionClass(args.thiz(), params); + } else { + LOG_WRONG_ARG_TYPE(); + } + break; + } + case 2: { + CHECK_ARG_TYPE_C(args[0], ValueKind::kString); + CHECK_ARG_TYPE_C(args[1], ValueKind::kObject); + auto obj = args[1].asObject(); + ConnParams params; + params["type"] = args[0].asString().toString(); + for (auto& key : obj.getKeys()) params[key.toString()] = LocalValueToAny(obj.get(key)); + result = new DBSessionClass(args.thiz(), ConnParams(params)); + break; + } + default: + LOG_WRONG_ARG_TYPE(); + break; + } + return result; } - return result; - } - CATCH_C("Fail in Open Database!"); + CATCH_C("Fail in Open Database!"); } -Local DBSessionClass::query(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local DBSessionClass::query(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - auto res = session->query(args[0].asString().toString()); - return RowSetToLocalValue(res); - } - CATCH_AND_THROW("Fail in query!"); + try { + auto res = session->query(args[0].asString().toString()); + return RowSetToLocalValue(res); + } + CATCH_AND_THROW("Fail in query!"); } -Local DBSessionClass::exec(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local DBSessionClass::exec(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - session->execute(args[0].asString().toString()); - return this->getScriptObject(); - } - CATCH_AND_THROW("Fail in exec!"); + try { + session->execute(args[0].asString().toString()); + return this->getScriptObject(); + } + CATCH_AND_THROW("Fail in exec!"); } -Local DBSessionClass::prepare(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local DBSessionClass::prepare(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - auto stmt = - new DBStmtClass(session->prepare(args[0].asString().toString())); - return stmt->getScriptObject(); - } - CATCH_AND_THROW("Fail in exec!"); + try { + auto stmt = new DBStmtClass(session->prepare(args[0].asString().toString())); + return stmt->getScriptObject(); + } + CATCH_AND_THROW("Fail in exec!"); } -Local DBSessionClass::close(const Arguments &args) { - CHECK_ARGS_COUNT(args, 0); +Local DBSessionClass::close(const Arguments& args) { + CHECK_ARGS_COUNT(args, 0); - try { - session->close(); - return Boolean::newBoolean(true); - } - CATCH_WITHOUT_RETURN("Fail in close!"); - return Boolean::newBoolean(false); + try { + session->close(); + return Boolean::newBoolean(true); + } + CATCH_WITHOUT_RETURN("Fail in close!"); + return Boolean::newBoolean(false); } -Local DBSessionClass::isOpen(const Arguments &args) { - CHECK_ARGS_COUNT(args, 0); +Local DBSessionClass::isOpen(const Arguments& args) { + CHECK_ARGS_COUNT(args, 0); - try { - return Boolean::newBoolean(session->isOpen()); - } - CATCH_AND_THROW("Fail in isOpen!"); + try { + return Boolean::newBoolean(session->isOpen()); + } + CATCH_AND_THROW("Fail in isOpen!"); } //////////////////// Classes DBStmt //////////////////// // 生成函数 -DBStmtClass::DBStmtClass(const Local &scriptObj, - const DB::SharedPointer &stmt) - : ScriptClass(scriptObj), stmt(stmt) {} +DBStmtClass::DBStmtClass(const Local& scriptObj, const DB::SharedPointer& stmt) +: ScriptClass(scriptObj), + stmt(stmt) {} -DBStmtClass::DBStmtClass(const DB::SharedPointer &stmt) - : ScriptClass(script::ScriptClass::ConstructFromCpp{}), - stmt(stmt) {} +DBStmtClass::DBStmtClass(const DB::SharedPointer& stmt) +: ScriptClass(script::ScriptClass::ConstructFromCpp{}), + stmt(stmt) {} DBStmtClass::~DBStmtClass() {} Local DBStmtClass::getAffectedRows() { - try { - auto res = stmt->getAffectedRows(); - if (res == (uint64_t)-1) - return Number::newNumber(-1); - if (res > LLONG_MAX) - return Number::newNumber((double)res); - return Number::newNumber((int64_t)res); - } - CATCH_AND_THROW("Fail in getAffectedRows!"); + try { + auto res = stmt->getAffectedRows(); + if (res == (uint64_t)-1) return Number::newNumber(-1); + if (res > LLONG_MAX) return Number::newNumber((double)res); + return Number::newNumber((int64_t)res); + } + CATCH_AND_THROW("Fail in getAffectedRows!"); } Local DBStmtClass::getInsertId() { - try { - auto res = stmt->getInsertId(); - if (res == (uint64_t)-1) - return Number::newNumber(-1); - if (res > LLONG_MAX) - return Number::newNumber((double)res); - return Number::newNumber((int64_t)res); - } - CATCH_AND_THROW("Fail in getInsertId!"); + try { + auto res = stmt->getInsertId(); + if (res == (uint64_t)-1) return Number::newNumber(-1); + if (res > LLONG_MAX) return Number::newNumber((double)res); + return Number::newNumber((int64_t)res); + } + CATCH_AND_THROW("Fail in getInsertId!"); } -Local DBStmtClass::bind(const Arguments &args) { - try { - switch (args.size()) { - case 1: { - switch (args[0].getKind()) { - case ValueKind::kArray: { - auto arr = args[0].asArray(); - for (size_t i = 0; i < arr.size(); ++i) - stmt->bind(LocalValueToAny(arr.get(i))); - break; - } - case ValueKind::kObject: { - auto obj = args[0].asObject(); - for (auto &key : obj.getKeys()) - stmt->bind(LocalValueToAny(obj.get(key)), key.toString()); - break; - } - default: - stmt->bind(LocalValueToAny(args[0])); - } - break; - } - case 2: { - if (args[1].isNumber()) { - stmt->bind(LocalValueToAny(args[0]), (int)args[1].asNumber().toInt64()); - } else if (args[1].isString()) { - stmt->bind(LocalValueToAny(args[0]), args[1].asString().toString()); - } else { - LOG_WRONG_ARG_TYPE(); - } - } - } - return this->getScriptObject(); - } - CATCH_AND_THROW("Fail in bind!"); +Local DBStmtClass::bind(const Arguments& args) { + try { + switch (args.size()) { + case 1: { + switch (args[0].getKind()) { + case ValueKind::kArray: { + auto arr = args[0].asArray(); + for (size_t i = 0; i < arr.size(); ++i) stmt->bind(LocalValueToAny(arr.get(i))); + break; + } + case ValueKind::kObject: { + auto obj = args[0].asObject(); + for (auto& key : obj.getKeys()) stmt->bind(LocalValueToAny(obj.get(key)), key.toString()); + break; + } + default: + stmt->bind(LocalValueToAny(args[0])); + } + break; + } + case 2: { + if (args[1].isNumber()) { + stmt->bind(LocalValueToAny(args[0]), (int)args[1].asNumber().toInt64()); + } else if (args[1].isString()) { + stmt->bind(LocalValueToAny(args[0]), args[1].asString().toString()); + } else { + LOG_WRONG_ARG_TYPE(); + } + } + } + return this->getScriptObject(); + } + CATCH_AND_THROW("Fail in bind!"); } -Local DBStmtClass::execute(const Arguments &args) { - CHECK_ARGS_COUNT(args, 0); +Local DBStmtClass::execute(const Arguments& args) { + CHECK_ARGS_COUNT(args, 0); - try { - stmt->execute(); - return this->getScriptObject(); - } - CATCH_AND_THROW("Fail in reset!"); + try { + stmt->execute(); + return this->getScriptObject(); + } + CATCH_AND_THROW("Fail in reset!"); } -Local DBStmtClass::step(const Arguments &args) { - CHECK_ARGS_COUNT(args, 0); +Local DBStmtClass::step(const Arguments& args) { + CHECK_ARGS_COUNT(args, 0); - try { - return Boolean::newBoolean(stmt->step()); - } - CATCH_WITHOUT_RETURN("Fail in step!"); - return Boolean::newBoolean(false); + try { + return Boolean::newBoolean(stmt->step()); + } + CATCH_WITHOUT_RETURN("Fail in step!"); + return Boolean::newBoolean(false); } -Local DBStmtClass::fetch(const Arguments &args) { - CHECK_ARGS_COUNT(args, 0); +Local DBStmtClass::fetch(const Arguments& args) { + CHECK_ARGS_COUNT(args, 0); - try { - return RowToLocalValue(stmt->fetch()); - } - CATCH_AND_THROW("Fail in fetch!"); + try { + return RowToLocalValue(stmt->fetch()); + } + CATCH_AND_THROW("Fail in fetch!"); } -Local DBStmtClass::fetchAll(const Arguments &args) { - try { - switch (args.size()) { - case 0: - return RowSetToLocalValue(stmt->fetchAll()); - case 1: { - CHECK_ARG_TYPE(args[0], ValueKind::kFunction); - auto func = args[0].asFunction(); - stmt->fetchAll([&](const Row &row) { - auto res = func.call({}, RowToLocalValue(row)); - if (res.isBoolean()) { - return res.asBoolean().value(); +Local DBStmtClass::fetchAll(const Arguments& args) { + try { + switch (args.size()) { + case 0: + return RowSetToLocalValue(stmt->fetchAll()); + case 1: { + CHECK_ARG_TYPE(args[0], ValueKind::kFunction); + auto func = args[0].asFunction(); + stmt->fetchAll([&](const Row& row) { + auto res = func.call({}, RowToLocalValue(row)); + if (res.isBoolean()) { + return res.asBoolean().value(); + } + return true; + }); } - return true; - }); - } + } + return this->getScriptObject(); } - return this->getScriptObject(); - } - CATCH_AND_THROW("Fail in fetchAll!"); + CATCH_AND_THROW("Fail in fetchAll!"); } -Local DBStmtClass::reset(const Arguments &args) { - CHECK_ARGS_COUNT(args, 0); +Local DBStmtClass::reset(const Arguments& args) { + CHECK_ARGS_COUNT(args, 0); - try { - stmt->reset(); - return this->getScriptObject(); - } - CATCH_AND_THROW("Fail in reset!"); + try { + stmt->reset(); + return this->getScriptObject(); + } + CATCH_AND_THROW("Fail in reset!"); } -Local DBStmtClass::reexec(const Arguments &args) { - CHECK_ARGS_COUNT(args, 0); +Local DBStmtClass::reexec(const Arguments& args) { + CHECK_ARGS_COUNT(args, 0); - try { - stmt->reexec(); - return this->getScriptObject(); - } - CATCH_AND_THROW("Fail in reexec!"); + try { + stmt->reexec(); + return this->getScriptObject(); + } + CATCH_AND_THROW("Fail in reexec!"); } -Local DBStmtClass::clear(const Arguments &args) { - CHECK_ARGS_COUNT(args, 0); +Local DBStmtClass::clear(const Arguments& args) { + CHECK_ARGS_COUNT(args, 0); - try { - stmt->clear(); - return this->getScriptObject(); - } - CATCH_AND_THROW("Fail in clear!"); + try { + stmt->clear(); + return this->getScriptObject(); + } + CATCH_AND_THROW("Fail in clear!"); } diff --git a/src/api/DatabaseAPI.h b/src/api/DatabaseAPI.h index 142bafed..8353642f 100644 --- a/src/api/DatabaseAPI.h +++ b/src/api/DatabaseAPI.h @@ -8,68 +8,66 @@ //// KVDB class KVDBClass : public ScriptClass { private: - std::unique_ptr kvdb; - int unloadCallbackIndex = -1; + std::unique_ptr kvdb; + int unloadCallbackIndex = -1; public: - explicit KVDBClass(const Local &scriptObj, const string &dir); - explicit KVDBClass(const string &dir); - ~KVDBClass(); - static KVDBClass *constructor(const Arguments &args); + explicit KVDBClass(const Local& scriptObj, const string& dir); + explicit KVDBClass(const string& dir); + ~KVDBClass(); + static KVDBClass* constructor(const Arguments& args); - bool isValid() { return kvdb.get(); } + bool isValid() { return kvdb.get(); } - Local get(const Arguments &args); - Local set(const Arguments &args); - Local del(const Arguments &args); - Local close(const Arguments &args); - Local listKey(const Arguments &args); + Local get(const Arguments& args); + Local set(const Arguments& args); + Local del(const Arguments& args); + Local close(const Arguments& args); + Local listKey(const Arguments& args); - // For Compatibility - static Local newDb(const string &dir); + // For Compatibility + static Local newDb(const string& dir); }; extern ClassDefine KVDBClassBuilder; //// SQLDB class DBSessionClass : public ScriptClass { private: - DB::SharedPointer session; + DB::SharedPointer session; public: - explicit DBSessionClass(const Local &scriptObj, - const DB::ConnParams ¶ms); - explicit DBSessionClass(const DB::ConnParams ¶ms); - ~DBSessionClass(); - static DBSessionClass *constructor(const Arguments &args); + explicit DBSessionClass(const Local& scriptObj, const DB::ConnParams& params); + explicit DBSessionClass(const DB::ConnParams& params); + ~DBSessionClass(); + static DBSessionClass* constructor(const Arguments& args); - Local query(const Arguments &args); - Local exec(const Arguments &args); - Local prepare(const Arguments &args); - Local close(const Arguments &args); - Local isOpen(const Arguments &args); + Local query(const Arguments& args); + Local exec(const Arguments& args); + Local prepare(const Arguments& args); + Local close(const Arguments& args); + Local isOpen(const Arguments& args); }; extern ClassDefine DBSessionClassBuilder; class DBStmtClass : public ScriptClass { private: - DB::SharedPointer stmt; + DB::SharedPointer stmt; public: - explicit DBStmtClass(const Local &scriptObj, - const DB::SharedPointer &stmt); - explicit DBStmtClass(const DB::SharedPointer &stmt); - ~DBStmtClass(); + explicit DBStmtClass(const Local& scriptObj, const DB::SharedPointer& stmt); + explicit DBStmtClass(const DB::SharedPointer& stmt); + ~DBStmtClass(); - Local getAffectedRows(); - Local getInsertId(); + Local getAffectedRows(); + Local getInsertId(); - Local bind(const Arguments &args); - Local execute(const Arguments &args); - Local step(const Arguments &args); - Local fetch(const Arguments &args); - Local fetchAll(const Arguments &args); - Local reset(const Arguments &args); - Local reexec(const Arguments &args); - Local clear(const Arguments &args); + Local bind(const Arguments& args); + Local execute(const Arguments& args); + Local step(const Arguments& args); + Local fetch(const Arguments& args); + Local fetchAll(const Arguments& args); + Local reset(const Arguments& args); + Local reexec(const Arguments& args); + Local clear(const Arguments& args); }; extern ClassDefine DBStmtClassBuilder; diff --git a/src/api/DeviceAPI.cpp b/src/api/DeviceAPI.cpp index 2094834c..f38aacb5 100644 --- a/src/api/DeviceAPI.cpp +++ b/src/api/DeviceAPI.cpp @@ -11,149 +11,139 @@ //////////////////// Class Definition //////////////////// -ClassDefine DeviceClassBuilder = - defineClass("LLSE_Device") - .constructor(nullptr) - .instanceProperty("ip", &DeviceClass::getIP) - .instanceProperty("avgPing", &DeviceClass::getAvgPing) - .instanceProperty("avgPacketLoss", &DeviceClass::getAvgPacketLoss) - .instanceProperty("lastPing", &DeviceClass::getLastPing) - .instanceProperty("lastPacketLoss", &DeviceClass::getLastPacketLoss) - .instanceProperty("os", &DeviceClass::getOs) - //.instanceProperty("inputMode", &DeviceClass::getInputMode) - //.instanceProperty("playMode", &DeviceClass::getPlayMode) - .instanceProperty("serverAddress", &DeviceClass::getServerAddress) - .instanceProperty("clientId", &DeviceClass::getClientId) - .build(); +ClassDefine DeviceClassBuilder = defineClass("LLSE_Device") + .constructor(nullptr) + .instanceProperty("ip", &DeviceClass::getIP) + .instanceProperty("avgPing", &DeviceClass::getAvgPing) + .instanceProperty("avgPacketLoss", &DeviceClass::getAvgPacketLoss) + .instanceProperty("lastPing", &DeviceClass::getLastPing) + .instanceProperty("lastPacketLoss", &DeviceClass::getLastPacketLoss) + .instanceProperty("os", &DeviceClass::getOs) + //.instanceProperty("inputMode", &DeviceClass::getInputMode) + //.instanceProperty("playMode", &DeviceClass::getPlayMode) + .instanceProperty("serverAddress", &DeviceClass::getServerAddress) + .instanceProperty("clientId", &DeviceClass::getClientId) + .build(); //////////////////// Classes //////////////////// // 生成函数 -Local DeviceClass::newDevice(Player *p) { - auto newp = new DeviceClass(p); - return newp->getScriptObject(); +Local DeviceClass::newDevice(Player* p) { + auto newp = new DeviceClass(p); + return newp->getScriptObject(); } // 成员函数 -void DeviceClass::setPlayer(Player *player) { - __try { - id = player->getOrCreateUniqueID(); - } __except (EXCEPTION_EXECUTE_HANDLER) { - isValid = false; - } +void DeviceClass::setPlayer(Player* player) { + __try { + id = player->getOrCreateUniqueID(); + } __except (EXCEPTION_EXECUTE_HANDLER) { + isValid = false; + } } -Player *DeviceClass::getPlayer() { - if (!isValid) - return nullptr; - else - return ll::service::getLevel()->getPlayer(id); +Player* DeviceClass::getPlayer() { + if (!isValid) return nullptr; + else return ll::service::getLevel()->getPlayer(id); } Local DeviceClass::getIP() { - try { - Player *player = getPlayer(); - if (!player) - return Local(); - - return String::newString(player->getNetworkIdentifier().getAddress()); - } - CATCH("Fail in GetIP!") + try { + Player* player = getPlayer(); + if (!player) return Local(); + + return String::newString(player->getNetworkIdentifier().getAddress()); + } + CATCH("Fail in GetIP!") } Local DeviceClass::getAvgPing() { - try { - Player *player = getPlayer(); - if (!player) - return Local(); - - return Number::newNumber(player->getNetworkStatus()->mAveragePing); - } - CATCH("Fail in getAvgPing!") + try { + Player* player = getPlayer(); + if (!player) return Local(); + + return Number::newNumber(player->getNetworkStatus()->mAveragePing); + } + CATCH("Fail in getAvgPing!") } Local DeviceClass::getAvgPacketLoss() { - try { - Player *player = getPlayer(); - if (!player) - return Local(); - - return Number::newNumber(player->getNetworkStatus()->mAveragePacketLoss); - } - CATCH("Fail in getAvgPacketLoss!") + try { + Player* player = getPlayer(); + if (!player) return Local(); + + return Number::newNumber(player->getNetworkStatus()->mAveragePacketLoss); + } + CATCH("Fail in getAvgPacketLoss!") } Local DeviceClass::getLastPing() { - try { - Player *player = getPlayer(); - if (!player) { - return Local(); - } + try { + Player* player = getPlayer(); + if (!player) { + return Local(); + } - return Number::newNumber(player->getNetworkStatus()->mCurrentPing); - } - CATCH("Fail in getLastPing!") + return Number::newNumber(player->getNetworkStatus()->mCurrentPing); + } + CATCH("Fail in getLastPing!") } Local DeviceClass::getLastPacketLoss() { - try { - Player *player = getPlayer(); - if (!player) { - return Local(); - } + try { + Player* player = getPlayer(); + if (!player) { + return Local(); + } - return Number::newNumber(player->getNetworkStatus()->mCurrentPacketLoss); - } - CATCH("Fail in getLastPacketLoss!") + return Number::newNumber(player->getNetworkStatus()->mCurrentPacketLoss); + } + CATCH("Fail in getLastPacketLoss!") } Local DeviceClass::getOs() { - try { - Player *player = getPlayer(); - if (!player) - return Local(); - - return String::newString(magic_enum::enum_name(player->getPlatform())); - } - CATCH("Fail in getOs!") + try { + Player* player = getPlayer(); + if (!player) return Local(); + + return String::newString(magic_enum::enum_name(player->getPlatform())); + } + CATCH("Fail in getOs!") } Local DeviceClass::getServerAddress() { - try { - Player *player = getPlayer(); - if (!player) { - return Local(); - } - if (player->isSimulatedPlayer()) - String::newString("unknown"); - auto map = ll::service::getServerNetworkHandler() - ->fetchConnectionRequest(player->getNetworkIdentifier()) - .mRawToken.get() - ->mDataInfo.value_.map_; - for (auto iter = map->begin(); iter != map->end(); ++iter) { - string s(iter->first.c_str()); - if (s.find("ServerAddress") != s.npos) { - auto ServerAddress = iter->second.value_.string_; - return String::newString(ServerAddress); - } + try { + Player* player = getPlayer(); + if (!player) { + return Local(); + } + if (player->isSimulatedPlayer()) String::newString("unknown"); + auto map = ll::service::getServerNetworkHandler() + ->fetchConnectionRequest(player->getNetworkIdentifier()) + .mRawToken.get() + ->mDataInfo.value_.map_; + for (auto iter = map->begin(); iter != map->end(); ++iter) { + string s(iter->first.c_str()); + if (s.find("ServerAddress") != s.npos) { + auto ServerAddress = iter->second.value_.string_; + return String::newString(ServerAddress); + } + } + return String::newString("unknown"); } - return String::newString("unknown"); - } - CATCH("Fail in getServerAddress!") + CATCH("Fail in getServerAddress!") } Local DeviceClass::getClientId() { - try { - Player *player = getPlayer(); - if (!player) - return Local(); - - return String::newString( - ll::service::getServerNetworkHandler() - ->fetchConnectionRequest(player->getNetworkIdentifier()) - .getDeviceId()); //=============??? - } - CATCH("Fail in getClientId!") + try { + Player* player = getPlayer(); + if (!player) return Local(); + + return String::newString( + ll::service::getServerNetworkHandler()->fetchConnectionRequest(player->getNetworkIdentifier()).getDeviceId() + ); //=============??? + } + CATCH("Fail in getClientId!") } // Local DeviceClass::getInputMode() { diff --git a/src/api/DeviceAPI.h b/src/api/DeviceAPI.h index 7f0ae593..e5ec9892 100644 --- a/src/api/DeviceAPI.h +++ b/src/api/DeviceAPI.h @@ -6,29 +6,26 @@ class Player; class DeviceClass : public ScriptClass { private: - ActorUniqueID id; - bool isValid = true; + ActorUniqueID id; + bool isValid = true; public: - explicit DeviceClass(Player *p) - : ScriptClass(ScriptClass::ConstructFromCpp{}) { - setPlayer(p); - } + explicit DeviceClass(Player* p) : ScriptClass(ScriptClass::ConstructFromCpp{}) { setPlayer(p); } - void setPlayer(Player *player); - Player *getPlayer(); + void setPlayer(Player* player); + Player* getPlayer(); - static Local newDevice(Player *p); + static Local newDevice(Player* p); - Local getIP(); - Local getAvgPing(); - Local getAvgPacketLoss(); - Local getLastPing(); - Local getLastPacketLoss(); - Local getOs(); - // Local getInputMode(); - // Local getPlayMode(); - Local getServerAddress(); - Local getClientId(); + Local getIP(); + Local getAvgPing(); + Local getAvgPacketLoss(); + Local getLastPing(); + Local getLastPacketLoss(); + Local getOs(); + // Local getInputMode(); + // Local getPlayMode(); + Local getServerAddress(); + Local getClientId(); }; extern ClassDefine DeviceClassBuilder; \ No newline at end of file diff --git a/src/api/EntityAPI.cpp b/src/api/EntityAPI.cpp index 1b1278bc..03822776 100644 --- a/src/api/EntityAPI.cpp +++ b/src/api/EntityAPI.cpp @@ -74,8 +74,7 @@ ClassDefine EntityClassBuilder = .instanceProperty("isInvisible", &EntityClass::isInvisible) .instanceProperty("isInsidePortal", &EntityClass::isInsidePortal) .instanceProperty("isTrusting", &EntityClass::isTrusting) - .instanceProperty("isTouchingDamageBlock", - &EntityClass::isTouchingDamageBlock) + .instanceProperty("isTouchingDamageBlock", &EntityClass::isTouchingDamageBlock) .instanceProperty("isOnFire", &EntityClass::isOnFire) .instanceProperty("isOnGround", &EntityClass::isOnGround) .instanceProperty("isOnHotBlock", &EntityClass::isOnHotBlock) @@ -97,17 +96,13 @@ ClassDefine EntityClassBuilder = .instanceFunction("setHealth", &EntityClass::setHealth) .instanceFunction("setAbsorption", &EntityClass::setAbsorption) .instanceFunction("setAttackDamage", &EntityClass::setAttackDamage) - .instanceFunction("setMaxAttackDamage", - &EntityClass::setMaxAttackDamage) + .instanceFunction("setMaxAttackDamage", &EntityClass::setMaxAttackDamage) .instanceFunction("setFollowRange", &EntityClass::setFollowRange) - .instanceFunction("setKnockbackResistance", - &EntityClass::setKnockbackResistance) + .instanceFunction("setKnockbackResistance", &EntityClass::setKnockbackResistance) .instanceFunction("setLuck", &EntityClass::setLuck) .instanceFunction("setMovementSpeed", &EntityClass::setMovementSpeed) - .instanceFunction("setUnderwaterMovementSpeed", - &EntityClass::setUnderwaterMovementSpeed) - .instanceFunction("setLavaMovementSpeed", - &EntityClass::setLavaMovementSpeed) + .instanceFunction("setUnderwaterMovementSpeed", &EntityClass::setUnderwaterMovementSpeed) + .instanceFunction("setLavaMovementSpeed", &EntityClass::setLavaMovementSpeed) .instanceFunction("setMaxHealth", &EntityClass::setMaxHealth) .instanceFunction("setFire", &EntityClass::setFire) .instanceFunction("stopFire", &EntityClass::stopFire) @@ -115,8 +110,7 @@ ClassDefine EntityClassBuilder = .instanceFunction("toPlayer", &EntityClass::toPlayer) .instanceFunction("isItemEntity", &EntityClass::isItemEntity) .instanceFunction("toItem", &EntityClass::toItem) - .instanceFunction("getBlockStandingOn", - &EntityClass::getBlockStandingOn) + .instanceFunction("getBlockStandingOn", &EntityClass::getBlockStandingOn) .instanceFunction("getArmor", &EntityClass::getArmor) .instanceFunction("distanceTo", &EntityClass::distanceTo) .instanceFunction("distanceToSqr", &EntityClass::distanceToSqr) @@ -130,14 +124,11 @@ ClassDefine EntityClassBuilder = .instanceFunction("removeTag", &EntityClass::removeTag) .instanceFunction("hasTag", &EntityClass::hasTag) .instanceFunction("getAllTags", &EntityClass::getAllTags) - .instanceFunction("getEntityFromViewVector", - &EntityClass::getEntityFromViewVector) - .instanceFunction("getBlockFromViewVector", - &EntityClass::getBlockFromViewVector) + .instanceFunction("getEntityFromViewVector", &EntityClass::getEntityFromViewVector) + .instanceFunction("getBlockFromViewVector", &EntityClass::getBlockFromViewVector) .instanceFunction("getBiomeName", &EntityClass::getBiomeName) .instanceFunction("getBiomeId", &EntityClass::getBiomeId) - .instanceFunction("quickEvalMolangScript", - &EntityClass::quickEvalMolangScript) + .instanceFunction("quickEvalMolangScript", &EntityClass::quickEvalMolangScript) .instanceFunction("getAllEffects", &EntityClass::getAllEffects) .instanceFunction("addEffect", &EntityClass::addEffect) @@ -190,1755 +181,1637 @@ ClassDefine ActorDamageCauseBuilder = // clang-format on // 生成函数 -Local EntityClass::newEntity(Actor *p) { - auto newp = new EntityClass(p); - return newp->getScriptObject(); +Local EntityClass::newEntity(Actor* p) { + auto newp = new EntityClass(p); + return newp->getScriptObject(); } -Actor *EntityClass::extract(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine() - ->getNativeInstance(v) - ->get(); - else - return nullptr; +Actor* EntityClass::extract(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v)->get(); + else return nullptr; } -std::optional EntityClass::tryExtractActor(Local v) { - if (IsInstanceOf(v)) - return EntityClass::extract(v); - if (IsInstanceOf(v)) - return PlayerClass::extract(v); - return std::nullopt; +std::optional EntityClass::tryExtractActor(Local v) { + if (IsInstanceOf(v)) return EntityClass::extract(v); + if (IsInstanceOf(v)) return PlayerClass::extract(v); + return std::nullopt; } // 成员函数 -void EntityClass::set(Actor *actor) { - __try { - id = actor->getOrCreateUniqueID(); - } __except (EXCEPTION_EXECUTE_HANDLER) { - isValid = false; - } +void EntityClass::set(Actor* actor) { + __try { + id = actor->getOrCreateUniqueID(); + } __except (EXCEPTION_EXECUTE_HANDLER) { + isValid = false; + } } -Actor *EntityClass::get() { - if (!isValid) - return nullptr; - else - return ll::service::getLevel()->fetchEntity(id); +Actor* EntityClass::get() { + if (!isValid) return nullptr; + else return ll::service::getLevel()->fetchEntity(id); } -Local EntityClass::asPointer(const Arguments &args) { - try { - Actor *entity = get(); - if (!entity) - return Local(); - else - return NativePointer::newNativePointer(entity); - } - CATCH("Fail in asPointer!") +Local EntityClass::asPointer(const Arguments& args) { + try { + Actor* entity = get(); + if (!entity) return Local(); + else return NativePointer::newNativePointer(entity); + } + CATCH("Fail in asPointer!") } Local EntityClass::getUniqueID() { - try { - Actor *entity = get(); - if (!entity) - return Local(); - else - return String::newString( - std::to_string(entity->getOrCreateUniqueID().id)); - } - CATCH("Fail in getUniqueID!") + try { + Actor* entity = get(); + if (!entity) return Local(); + else return String::newString(std::to_string(entity->getOrCreateUniqueID().id)); + } + CATCH("Fail in getUniqueID!") } Local EntityClass::isInvisible() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->isInvisible()); - } - CATCH("Fail in isInvisible!") + return Boolean::newBoolean(entity->isInvisible()); + } + CATCH("Fail in isInvisible!") } Local EntityClass::isInsidePortal() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->isInsidePortal()); - } - CATCH("Fail in isInsidePortal!") + return Boolean::newBoolean(entity->isInsidePortal()); + } + CATCH("Fail in isInsidePortal!") } Local EntityClass::isTrusting() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->isTrusting()); - } - CATCH("Fail in isTrusting!") + return Boolean::newBoolean(entity->isTrusting()); + } + CATCH("Fail in isTrusting!") } Local EntityClass::isTouchingDamageBlock() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->isTouchingDamageBlock()); - } - CATCH("Fail in isTouchingDamageBlock!") + return Boolean::newBoolean(entity->isTouchingDamageBlock()); + } + CATCH("Fail in isTouchingDamageBlock!") } Local EntityClass::isOnFire() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->isOnFire()); - } - CATCH("Fail in isOnFire!") + return Boolean::newBoolean(entity->isOnFire()); + } + CATCH("Fail in isOnFire!") } Local EntityClass::isOnGround() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->isOnGround()); - } - CATCH("Fail in isOnGround!") + return Boolean::newBoolean(entity->isOnGround()); + } + CATCH("Fail in isOnGround!") } Local EntityClass::isOnHotBlock() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->isOnHotBlock()); - } - CATCH("Fail in isOnHotBlock!") + return Boolean::newBoolean(entity->isOnHotBlock()); + } + CATCH("Fail in isOnHotBlock!") } Local EntityClass::isTrading() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->isTrading()); - } - CATCH("Fail in isTrading!") + return Boolean::newBoolean(entity->isTrading()); + } + CATCH("Fail in isTrading!") } Local EntityClass::isRiding() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->isRiding()); - } - CATCH("Fail in isRiding!") + return Boolean::newBoolean(entity->isRiding()); + } + CATCH("Fail in isRiding!") } Local EntityClass::isDancing() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->isDancing()); - } - CATCH("Fail in isDancing!") + return Boolean::newBoolean(entity->isDancing()); + } + CATCH("Fail in isDancing!") } Local EntityClass::isSleeping() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->isSleeping()); - } - CATCH("Fail in isSleeping!") + return Boolean::newBoolean(entity->isSleeping()); + } + CATCH("Fail in isSleeping!") } Local EntityClass::isAngry() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->isAngry()); - } - CATCH("Fail in isAngry!") + return Boolean::newBoolean(entity->isAngry()); + } + CATCH("Fail in isAngry!") } Local EntityClass::isBaby() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->isBaby()); - } - CATCH("Fail in isBaby!") + return Boolean::newBoolean(entity->isBaby()); + } + CATCH("Fail in isBaby!") } Local EntityClass::isMoving() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->isMoving()); - } - CATCH("Fail in isMoving!") + return Boolean::newBoolean(entity->isMoving()); + } + CATCH("Fail in isMoving!") } #include "mc/server/commands/CommandUtils.h" Local EntityClass::getName() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return String::newString(CommandUtils::getActorName(*entity)); - } - CATCH("Fail in getEntityName!") + return String::newString(CommandUtils::getActorName(*entity)); + } + CATCH("Fail in getEntityName!") } Local EntityClass::getType() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return String::newString(entity->getTypeName()); - } - CATCH("Fail in getEntityType!") + return String::newString(entity->getTypeName()); + } + CATCH("Fail in getEntityType!") } Local EntityClass::getId() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Number::newNumber(enum_integer(entity->getEntityTypeId())); - } - CATCH("Fail in getEntityId!") + return Number::newNumber(enum_integer(entity->getEntityTypeId())); + } + CATCH("Fail in getEntityId!") } Local EntityClass::getPos() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return FloatPos::newPos(entity->getPosition(), entity->getDimensionId()); - } - CATCH("Fail in GetEntityPos!") + return FloatPos::newPos(entity->getPosition(), entity->getDimensionId()); + } + CATCH("Fail in GetEntityPos!") } Local EntityClass::getPosDelta() { - try { - Actor *entity = get(); - if (!entity) - return Local(); - - return FloatPos::newPos(entity->getPosDelta(), entity->getDimensionId()); - } - CATCH("Fail in GetEntityPosDelta!") -} - -Local EntityClass::setPosDelta(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - - try { - Actor *entity = get(); - if (!entity) - return Boolean::newBoolean(false); - Vec3 delta; - if (args.size() == 1) { - if (!IsInstanceOf(args[0])) { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - delta = EngineScope::currentEngine() - ->getNativeInstance(args[0]) - ->getVec3(); - } else if (args.size() == 3) { - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + try { + Actor* entity = get(); + if (!entity) return Local(); - delta.x = args[0].asNumber().toFloat(); - delta.y = args[1].asNumber().toFloat(); - delta.z = args[2].asNumber().toFloat(); + return FloatPos::newPos(entity->getPosDelta(), entity->getDimensionId()); } - entity->getPosDeltaNonConst() = delta; + CATCH("Fail in GetEntityPosDelta!") +} + +Local EntityClass::setPosDelta(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + + try { + Actor* entity = get(); + if (!entity) return Boolean::newBoolean(false); + Vec3 delta; + if (args.size() == 1) { + if (!IsInstanceOf(args[0])) { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + delta = EngineScope::currentEngine()->getNativeInstance(args[0])->getVec3(); + } else if (args.size() == 3) { + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + + delta.x = args[0].asNumber().toFloat(); + delta.y = args[1].asNumber().toFloat(); + delta.z = args[2].asNumber().toFloat(); + } + entity->getPosDeltaNonConst() = delta; - return Boolean::newBoolean(true); - } - CATCH("Fail in GetEntityPos!") + return Boolean::newBoolean(true); + } + CATCH("Fail in GetEntityPos!") } Local EntityClass::getFeetPos() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return FloatPos::newPos(entity->getFeetPos(), entity->getDimensionId()); - } - CATCH("Fail in GetEntityFeetPos!") + return FloatPos::newPos(entity->getFeetPos(), entity->getDimensionId()); + } + CATCH("Fail in GetEntityFeetPos!") } Local EntityClass::getBlockPos() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return IntPos::newPos(entity->getFeetBlockPos(), entity->getDimensionId()); - } - CATCH("Fail in GetEntityBlockPos!") + return IntPos::newPos(entity->getFeetBlockPos(), entity->getDimensionId()); + } + CATCH("Fail in GetEntityBlockPos!") } Local EntityClass::getMaxHealth() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Number::newNumber(entity->getMaxHealth()); - } - CATCH("Fail in GetMaxHealth!") + return Number::newNumber(entity->getMaxHealth()); + } + CATCH("Fail in GetMaxHealth!") } Local EntityClass::getHealth() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Number::newNumber(entity->getHealth()); - } - CATCH("Fail in GetHealth!") + return Number::newNumber(entity->getHealth()); + } + CATCH("Fail in GetHealth!") } Local EntityClass::getCanFly() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->canFly()); - } - CATCH("Fail in getCanFly!") + return Boolean::newBoolean(entity->canFly()); + } + CATCH("Fail in getCanFly!") } Local EntityClass::getCanFreeze() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->canFreeze()); - } - CATCH("Fail in getCanFreeze!") + return Boolean::newBoolean(entity->canFreeze()); + } + CATCH("Fail in getCanFreeze!") } Local EntityClass::getCanSeeDaylight() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->canSeeDaylight()); - } - CATCH("Fail in getCanSeeDaylight!") + return Boolean::newBoolean(entity->canSeeDaylight()); + } + CATCH("Fail in getCanSeeDaylight!") } Local EntityClass::getCanPickupItems() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->getCanPickupItems()); - } - CATCH("Fail in getCanPickupItems!") + return Boolean::newBoolean(entity->getCanPickupItems()); + } + CATCH("Fail in getCanPickupItems!") } Local EntityClass::getInAir() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(!entity->isOnGround() && !entity->isInWater()); - } - CATCH("Fail in getInAir!") + return Boolean::newBoolean(!entity->isOnGround() && !entity->isInWater()); + } + CATCH("Fail in getInAir!") } Local EntityClass::getInWater() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->isInWater()); - } - CATCH("Fail in getInWater!") + return Boolean::newBoolean(entity->isInWater()); + } + CATCH("Fail in getInWater!") } Local EntityClass::getInClouds() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->isInClouds()); - } - CATCH("Fail in getInClouds!") + return Boolean::newBoolean(entity->isInClouds()); + } + CATCH("Fail in getInClouds!") } Local EntityClass::getInLava() { - try { - Actor *entity = get(); - if (!entity) - return Local(); - - return Boolean::newBoolean(ActorMobilityUtils::shouldApplyLava( - *(IConstBlockSource *)&entity->getDimensionBlockSourceConst(), - entity->getEntityContext())); - } - CATCH("Fail in getInLava!") + try { + Actor* entity = get(); + if (!entity) return Local(); + + return Boolean::newBoolean(ActorMobilityUtils::shouldApplyLava( + *(IConstBlockSource*)&entity->getDimensionBlockSourceConst(), + entity->getEntityContext() + )); + } + CATCH("Fail in getInLava!") } Local EntityClass::getInRain() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->isInRain()); - } - CATCH("Fail in getInRain!") + return Boolean::newBoolean(entity->isInRain()); + } + CATCH("Fail in getInRain!") } Local EntityClass::getInSnow() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->isInSnow()); - } - CATCH("Fail in getInSnow!") + return Boolean::newBoolean(entity->isInSnow()); + } + CATCH("Fail in getInSnow!") } Local EntityClass::getInWall() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->isInWall()); - } - CATCH("Fail in getInWall!") + return Boolean::newBoolean(entity->isInWall()); + } + CATCH("Fail in getInWall!") } Local EntityClass::getInWaterOrRain() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->isInWaterOrRain()); - } - CATCH("Fail in getInWaterOrRain!") + return Boolean::newBoolean(entity->isInWaterOrRain()); + } + CATCH("Fail in getInWaterOrRain!") } Local EntityClass::getInWorld() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Boolean::newBoolean(entity->isInWorld()); - } - CATCH("Fail in getInWorld!") + return Boolean::newBoolean(entity->isInWorld()); + } + CATCH("Fail in getInWorld!") } Local EntityClass::getSpeed() { - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - return Number::newNumber((float)entity->getPosDelta().length() * 20.0); - } - CATCH("Fail in getSpeed!") + return Number::newNumber((float)entity->getPosDelta().length() * 20.0); + } + CATCH("Fail in getSpeed!") } Local EntityClass::getDirection() { - try { - Actor *entity = get(); - if (!entity) - return Local(); - - Vec2 vec = entity->getRotation(); - return DirectionAngle::newAngle(vec.x, vec.y); - } - CATCH("Fail in getDirection!") -} - -Local EntityClass::teleport(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - - try { - Actor *entity = get(); - if (!entity) - return Boolean::newBoolean(false); - float pitch; - float yaw; - FloatVec4 pos; - bool rotationIsValid = false; - Vec2 ang; - - if (args.size() <= 2) { - if (IsInstanceOf(args[0])) { - // IntPos - IntPos *posObj = IntPos::extractPos(args[0]); - if (posObj->dim < 0) - return Boolean::newBoolean(false); - else { - pos.x = posObj->x; - pos.y = posObj->y; - pos.z = posObj->z; - pos.dim = posObj->dim; - } - } else if (IsInstanceOf(args[0])) { - // FloatPos - FloatPos *posObj = FloatPos::extractPos(args[0]); - if (posObj->dim < 0) - return Boolean::newBoolean(false); - else { - pos = *posObj; - } - } else { - LOG_WRONG_ARG_TYPE(); - return Boolean::newBoolean(false); - } - if (args.size() == 2 && IsInstanceOf(args[1])) { - auto angle = DirectionAngle::extract(args[1]); - pitch = angle->pitch; - yaw = angle->yaw; - rotationIsValid = true; - } - } else if (args.size() <= 5) { // teleport(x,y,z,dimid[,rot]) - // number pos - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - - pos.x = args[0].asNumber().toFloat(); - pos.y = args[1].asNumber().toFloat(); - pos.z = args[2].asNumber().toFloat(); - pos.dim = args[3].toInt(); - if (args.size() == 5 && IsInstanceOf(args[4])) { - auto angle = DirectionAngle::extract(args[4]); - ang.x = angle->pitch; - ang.y = angle->yaw; - rotationIsValid = true; - } - } else { - LOG_WRONG_ARG_TYPE(); - return Boolean::newBoolean(false); - } - if (!rotationIsValid) { - ang = entity->getRotation(); - } - entity->teleport(pos.getVec3(), pos.dim, ang); - return Boolean::newBoolean(true); - } - CATCH("Fail in TeleportEntity!") -} - -Local EntityClass::distanceTo(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - - try { - FloatVec4 pos{}; - - Actor *actor = get(); - if (!actor) - return Local(); - - if (args.size() == 1) { // pos | player | entity - if (IsInstanceOf(args[0])) { - // IntPos - IntPos *posObj = IntPos::extractPos(args[0]); - if (posObj->dim < 0) - return Local(); - else { - pos.x = posObj->x; - pos.y = posObj->y; - pos.z = posObj->z; - pos.dim = posObj->dim; + try { + Actor* entity = get(); + if (!entity) return Local(); + + Vec2 vec = entity->getRotation(); + return DirectionAngle::newAngle(vec.x, vec.y); + } + CATCH("Fail in getDirection!") +} + +Local EntityClass::teleport(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + + try { + Actor* entity = get(); + if (!entity) return Boolean::newBoolean(false); + float pitch; + float yaw; + FloatVec4 pos; + bool rotationIsValid = false; + Vec2 ang; + + if (args.size() <= 2) { + if (IsInstanceOf(args[0])) { + // IntPos + IntPos* posObj = IntPos::extractPos(args[0]); + if (posObj->dim < 0) return Boolean::newBoolean(false); + else { + pos.x = posObj->x; + pos.y = posObj->y; + pos.z = posObj->z; + pos.dim = posObj->dim; + } + } else if (IsInstanceOf(args[0])) { + // FloatPos + FloatPos* posObj = FloatPos::extractPos(args[0]); + if (posObj->dim < 0) return Boolean::newBoolean(false); + else { + pos = *posObj; + } + } else { + LOG_WRONG_ARG_TYPE(); + return Boolean::newBoolean(false); + } + if (args.size() == 2 && IsInstanceOf(args[1])) { + auto angle = DirectionAngle::extract(args[1]); + pitch = angle->pitch; + yaw = angle->yaw; + rotationIsValid = true; + } + } else if (args.size() <= 5) { // teleport(x,y,z,dimid[,rot]) + // number pos + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + + pos.x = args[0].asNumber().toFloat(); + pos.y = args[1].asNumber().toFloat(); + pos.z = args[2].asNumber().toFloat(); + pos.dim = args[3].toInt(); + if (args.size() == 5 && IsInstanceOf(args[4])) { + auto angle = DirectionAngle::extract(args[4]); + ang.x = angle->pitch; + ang.y = angle->yaw; + rotationIsValid = true; + } + } else { + LOG_WRONG_ARG_TYPE(); + return Boolean::newBoolean(false); } - } else if (IsInstanceOf(args[0])) { - // FloatPos - FloatPos *posObj = FloatPos::extractPos(args[0]); - if (posObj->dim < 0) - return Local(); - else { - pos = *posObj; + if (!rotationIsValid) { + ang = entity->getRotation(); } - } else if (IsInstanceOf(args[0]) || - IsInstanceOf(args[0])) { - // Player or Entity - - Actor *targetActor = EntityClass::tryExtractActor(args[0]).value(); - if (!targetActor) - return Local(); - - Vec3 targetActorPos = targetActor->getPosition(); - - pos.x = targetActorPos.x; - pos.y = targetActorPos.y; - pos.z = targetActorPos.z; - pos.dim = targetActor->getDimensionId(); - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - } else if (args.size() == 4) { // x, y, z, dimId - // number pos - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - - pos.x = args[0].asNumber().toFloat(); - pos.y = args[1].asNumber().toFloat(); - pos.z = args[2].asNumber().toFloat(); - pos.dim = args[3].toInt(); - } else { - LOG_WRONG_ARGS_COUNT(); - return Local(); - } - - if (actor->getDimensionId() != pos.dim) - return Number::newNumber(INT_MAX); - - return Number::newNumber(actor->distanceTo(pos.getVec3())); - } - CATCH("Fail in distanceTo!") -} - -Local EntityClass::distanceToSqr(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - - try { - FloatVec4 pos; - - Actor *actor = get(); - if (!actor) - return Local(); - - if (args.size() == 1) { - if (IsInstanceOf(args[0])) { - // IntPos - IntPos *posObj = IntPos::extractPos(args[0]); - if (posObj->dim < 0) - return Local(); - else { - pos.x = posObj->x; - pos.y = posObj->y; - pos.z = posObj->z; - pos.dim = posObj->dim; + entity->teleport(pos.getVec3(), pos.dim, ang); + return Boolean::newBoolean(true); + } + CATCH("Fail in TeleportEntity!") +} + +Local EntityClass::distanceTo(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + + try { + FloatVec4 pos{}; + + Actor* actor = get(); + if (!actor) return Local(); + + if (args.size() == 1) { // pos | player | entity + if (IsInstanceOf(args[0])) { + // IntPos + IntPos* posObj = IntPos::extractPos(args[0]); + if (posObj->dim < 0) return Local(); + else { + pos.x = posObj->x; + pos.y = posObj->y; + pos.z = posObj->z; + pos.dim = posObj->dim; + } + } else if (IsInstanceOf(args[0])) { + // FloatPos + FloatPos* posObj = FloatPos::extractPos(args[0]); + if (posObj->dim < 0) return Local(); + else { + pos = *posObj; + } + } else if (IsInstanceOf(args[0]) || IsInstanceOf(args[0])) { + // Player or Entity + + Actor* targetActor = EntityClass::tryExtractActor(args[0]).value(); + if (!targetActor) return Local(); + + Vec3 targetActorPos = targetActor->getPosition(); + + pos.x = targetActorPos.x; + pos.y = targetActorPos.y; + pos.z = targetActorPos.z; + pos.dim = targetActor->getDimensionId(); + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + } else if (args.size() == 4) { // x, y, z, dimId + // number pos + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + + pos.x = args[0].asNumber().toFloat(); + pos.y = args[1].asNumber().toFloat(); + pos.z = args[2].asNumber().toFloat(); + pos.dim = args[3].toInt(); + } else { + LOG_WRONG_ARGS_COUNT(); + return Local(); } - } else if (IsInstanceOf(args[0])) { - // FloatPos - FloatPos *posObj = FloatPos::extractPos(args[0]); - if (posObj->dim < 0) - return Local(); - else { - pos = *posObj; + + if (actor->getDimensionId() != pos.dim) return Number::newNumber(INT_MAX); + + return Number::newNumber(actor->distanceTo(pos.getVec3())); + } + CATCH("Fail in distanceTo!") +} + +Local EntityClass::distanceToSqr(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + + try { + FloatVec4 pos; + + Actor* actor = get(); + if (!actor) return Local(); + + if (args.size() == 1) { + if (IsInstanceOf(args[0])) { + // IntPos + IntPos* posObj = IntPos::extractPos(args[0]); + if (posObj->dim < 0) return Local(); + else { + pos.x = posObj->x; + pos.y = posObj->y; + pos.z = posObj->z; + pos.dim = posObj->dim; + } + } else if (IsInstanceOf(args[0])) { + // FloatPos + FloatPos* posObj = FloatPos::extractPos(args[0]); + if (posObj->dim < 0) return Local(); + else { + pos = *posObj; + } + } else if (IsInstanceOf(args[0]) || IsInstanceOf(args[0])) { + // Player or Entity + + Actor* targetActor = EntityClass::tryExtractActor(args[0]).value(); + if (!targetActor) return Local(); + + Vec3 targetActorPos = targetActor->getPosition(); + + pos.x = targetActorPos.x; + pos.y = targetActorPos.y; + pos.z = targetActorPos.z; + pos.dim = targetActor->getDimensionId(); + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + } else if (args.size() == 4) { + // number pos + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + + pos.x = args[0].asNumber().toFloat(); + pos.y = args[1].asNumber().toFloat(); + pos.z = args[2].asNumber().toFloat(); + pos.dim = args[3].toInt(); + } else { + LOG_WRONG_ARGS_COUNT(); + return Local(); } - } else if (IsInstanceOf(args[0]) || - IsInstanceOf(args[0])) { - // Player or Entity - - Actor *targetActor = EntityClass::tryExtractActor(args[0]).value(); - if (!targetActor) - return Local(); - - Vec3 targetActorPos = targetActor->getPosition(); - - pos.x = targetActorPos.x; - pos.y = targetActorPos.y; - pos.z = targetActorPos.z; - pos.dim = targetActor->getDimensionId(); - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - } else if (args.size() == 4) { - // number pos - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - - pos.x = args[0].asNumber().toFloat(); - pos.y = args[1].asNumber().toFloat(); - pos.z = args[2].asNumber().toFloat(); - pos.dim = args[3].toInt(); - } else { - LOG_WRONG_ARGS_COUNT(); - return Local(); - } - - if (actor->getDimensionId() != pos.dim) - return Number::newNumber(INT_MAX); - - return Number::newNumber(actor->distanceToSqr(pos.getVec3())); - } - CATCH("Fail in distanceToSqr!") -} - -Local EntityClass::kill(const Arguments &args) { - try { - Actor *entity = get(); - if (!entity) - return Local(); - - entity->kill(); - return Boolean::newBoolean(true); - } - CATCH("Fail in killEntity!") -} - -Local EntityClass::despawn(const Arguments &args) { - try { - Actor *entity = get(); - if (!entity) - return Local(); - - entity->despawn(); - return Boolean::newBoolean(true); - } - CATCH("Fail in despawnEntity!") -} - -Local EntityClass::remove(const Arguments &args) { - try { - Actor *entity = get(); - if (!entity) - return Local(); - - entity->remove(); - return Boolean::newBoolean(true); - } - CATCH("Fail in removeEntity!") -} - -Local EntityClass::isPlayer(const Arguments &args) { - try { - Actor *entity = get(); - if (!entity) - return Local(); - - return Boolean::newBoolean(entity->isType(ActorType::Player)); - } - CATCH("Fail in isPlayer!") -} - -Local EntityClass::toPlayer(const Arguments &args) { - try { - Actor *entity = get(); - if (!entity || !entity->isType(ActorType::Player)) - return Local(); - - auto pl = (Player *)entity; - if (!pl) - return Local(); - else - return PlayerClass::newPlayer(pl); - } - CATCH("Fail in toPlayer!"); -} - -Local EntityClass::isItemEntity(const Arguments &args) { - try { - Actor *entity = get(); - if (!entity) - return Local(); - - return Boolean::newBoolean(entity->hasCategory(ActorCategory::Item)); - } - CATCH("Fail in isPlayer!") -} - -Local EntityClass::toItem(const Arguments &args) { - try { - Actor *entity = get(); - if (!entity || !entity->hasCategory(ActorCategory::Item)) - return Local(); - auto it = (ItemActor *)entity; - if (!it) - return Local(); - else - return ItemClass::newItem(&it->item()); - } - CATCH("Fail in toItem!"); + if (actor->getDimensionId() != pos.dim) return Number::newNumber(INT_MAX); + + return Number::newNumber(actor->distanceToSqr(pos.getVec3())); + } + CATCH("Fail in distanceToSqr!") +} + +Local EntityClass::kill(const Arguments& args) { + try { + Actor* entity = get(); + if (!entity) return Local(); + + entity->kill(); + return Boolean::newBoolean(true); + } + CATCH("Fail in killEntity!") } -Local EntityClass::getBlockStandingOn(const Arguments &args) { - try { - Actor *entity = get(); - if (!entity) - return Local(); +Local EntityClass::despawn(const Arguments& args) { + try { + Actor* entity = get(); + if (!entity) return Local(); - return BlockClass::newBlock(entity->getBlockPosCurrentlyStandingOn(nullptr), - (int)entity->getDimensionId()); - } - CATCH("Fail in getBlockStandingOn!"); + entity->despawn(); + return Boolean::newBoolean(true); + } + CATCH("Fail in despawnEntity!") } -Local EntityClass::getArmor(const Arguments &args) { - try { - Actor *entity = get(); - if (!entity) - return Local(); +Local EntityClass::remove(const Arguments& args) { + try { + Actor* entity = get(); + if (!entity) return Local(); - return ContainerClass::newContainer(&entity->getArmorContainer()); - } - CATCH("Fail in getArmor!"); + entity->remove(); + return Boolean::newBoolean(true); + } + CATCH("Fail in removeEntity!") } -Local EntityClass::refreshItems(const Arguments &args) { - try { - Actor *entity = get(); - if (!entity) - return Local(); +Local EntityClass::isPlayer(const Arguments& args) { + try { + Actor* entity = get(); + if (!entity) return Local(); - ((Mob *)entity)->refreshInventory(); - return Boolean::newBoolean(true); - } - CATCH("Fail in refreshItems!"); + return Boolean::newBoolean(entity->isType(ActorType::Player)); + } + CATCH("Fail in isPlayer!") +} + +Local EntityClass::toPlayer(const Arguments& args) { + try { + Actor* entity = get(); + if (!entity || !entity->isType(ActorType::Player)) return Local(); + + auto pl = (Player*)entity; + if (!pl) return Local(); + else return PlayerClass::newPlayer(pl); + } + CATCH("Fail in toPlayer!"); +} + +Local EntityClass::isItemEntity(const Arguments& args) { + try { + Actor* entity = get(); + if (!entity) return Local(); + + return Boolean::newBoolean(entity->hasCategory(ActorCategory::Item)); + } + CATCH("Fail in isPlayer!") +} + +Local EntityClass::toItem(const Arguments& args) { + try { + Actor* entity = get(); + if (!entity || !entity->hasCategory(ActorCategory::Item)) return Local(); + + auto it = (ItemActor*)entity; + if (!it) return Local(); + else return ItemClass::newItem(&it->item()); + } + CATCH("Fail in toItem!"); +} + +Local EntityClass::getBlockStandingOn(const Arguments& args) { + try { + Actor* entity = get(); + if (!entity) return Local(); + + return BlockClass::newBlock(entity->getBlockPosCurrentlyStandingOn(nullptr), (int)entity->getDimensionId()); + } + CATCH("Fail in getBlockStandingOn!"); +} + +Local EntityClass::getArmor(const Arguments& args) { + try { + Actor* entity = get(); + if (!entity) return Local(); + + return ContainerClass::newContainer(&entity->getArmorContainer()); + } + CATCH("Fail in getArmor!"); +} + +Local EntityClass::refreshItems(const Arguments& args) { + try { + Actor* entity = get(); + if (!entity) return Local(); + + ((Mob*)entity)->refreshInventory(); + return Boolean::newBoolean(true); + } + CATCH("Fail in refreshItems!"); } #include "mc/world/level/BlockSource.h" #include "mc/world/level/dimension/Dimension.h" -Local EntityClass::hasContainer(const Arguments &args) { - try { - Actor *entity = get(); - if (!entity) - return Local(); - - Vec3 pos = entity->getPosition(); - return Boolean::newBoolean(entity->getDimension() - .getBlockSourceFromMainChunkSource() - .tryGetContainer(BlockPos(pos)) - ? true - : false); - } - CATCH("Fail in hasContainer!"); -} - -Local EntityClass::getContainer(const Arguments &args) { - try { - Actor *entity = get(); - if (!entity) - return Local(); - - Vec3 pos = entity->getPosition(); - Container *container = entity->getDimension() - .getBlockSourceFromMainChunkSource() - .tryGetContainer(BlockPos(pos)); - return container ? ContainerClass::newContainer(container) : Local(); - } - CATCH("Fail in getContainer!"); +Local EntityClass::hasContainer(const Arguments& args) { + try { + Actor* entity = get(); + if (!entity) return Local(); + + Vec3 pos = entity->getPosition(); + return Boolean::newBoolean( + entity->getDimension().getBlockSourceFromMainChunkSource().tryGetContainer(BlockPos(pos)) ? true : false + ); + } + CATCH("Fail in hasContainer!"); +} + +Local EntityClass::getContainer(const Arguments& args) { + try { + Actor* entity = get(); + if (!entity) return Local(); + + Vec3 pos = entity->getPosition(); + Container* container = + entity->getDimension().getBlockSourceFromMainChunkSource().tryGetContainer(BlockPos(pos)); + return container ? ContainerClass::newContainer(container) : Local(); + } + CATCH("Fail in getContainer!"); } #include "mc/world/actor/ActorDamageByActorSource.h" #include "mc/world/actor/ActorDamageSource.h" -Local EntityClass::hurt(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Actor *entity = get(); - if (!entity) { - return Boolean::newBoolean(false); - } - float damage = args[0].asNumber().toFloat(); - int type = 0; - if (args.size() == 2) { - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - type = args[1].asNumber().toInt32(); - ActorDamageSource damageSource = - ActorDamageSource((ActorDamageCause)type); - return Boolean::newBoolean( - entity->hurt(damageSource, damage, true, false)); - } - if (args.size() == 3) { - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - auto source = EntityClass::extract(args[2]); - type = args[1].asNumber().toInt32(); - ActorDamageByActorSource damageSource = - ActorDamageByActorSource(*source, (ActorDamageCause)type); - return Boolean::newBoolean( - entity->hurt(damageSource, damage, true, false)); +Local EntityClass::hurt(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + try { + Actor* entity = get(); + if (!entity) { + return Boolean::newBoolean(false); + } + float damage = args[0].asNumber().toFloat(); + int type = 0; + if (args.size() == 2) { + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + type = args[1].asNumber().toInt32(); + ActorDamageSource damageSource = ActorDamageSource((ActorDamageCause)type); + return Boolean::newBoolean(entity->hurt(damageSource, damage, true, false)); + } + if (args.size() == 3) { + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + auto source = EntityClass::extract(args[2]); + type = args[1].asNumber().toInt32(); + ActorDamageByActorSource damageSource = ActorDamageByActorSource(*source, (ActorDamageCause)type); + return Boolean::newBoolean(entity->hurt(damageSource, damage, true, false)); + } + return Boolean::newBoolean(false); } - return Boolean::newBoolean(false); - } - CATCH("Fail in hurt!"); + CATCH("Fail in hurt!"); } -Local EntityClass::heal(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Actor *entity = get(); - if (!entity) - return Local(); +Local EntityClass::heal(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + try { + Actor* entity = get(); + if (!entity) return Local(); - entity->heal(args[0].toInt()); - return Boolean::newBoolean(true); - } - CATCH("Fail in heal!"); + entity->heal(args[0].toInt()); + return Boolean::newBoolean(true); + } + CATCH("Fail in heal!"); } -Local EntityClass::setHealth(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local EntityClass::setHealth(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - AttributeInstance *healthAttribute = - entity->getMutableAttribute(SharedAttributes::HEALTH); + AttributeInstance* healthAttribute = entity->getMutableAttribute(SharedAttributes::HEALTH); - healthAttribute->setCurrentValue(args[0].asNumber().toFloat()); + healthAttribute->setCurrentValue(args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setHealth!"); + return Boolean::newBoolean(true); + } + CATCH("Fail in setHealth!"); } -Local EntityClass::setAbsorption(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local EntityClass::setAbsorption(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - AttributeInstance *absorptionAttribute = - entity->getMutableAttribute(SharedAttributes::ABSORPTION); + AttributeInstance* absorptionAttribute = entity->getMutableAttribute(SharedAttributes::ABSORPTION); - absorptionAttribute->setCurrentValue(args[0].asNumber().toFloat()); + absorptionAttribute->setCurrentValue(args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setAbsorptionAttribute!"); + return Boolean::newBoolean(true); + } + CATCH("Fail in setAbsorptionAttribute!"); } -Local EntityClass::setAttackDamage(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local EntityClass::setAttackDamage(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - AttributeInstance *attactDamageAttribute = - entity->getMutableAttribute(SharedAttributes::ATTACK_DAMAGE); + AttributeInstance* attactDamageAttribute = entity->getMutableAttribute(SharedAttributes::ATTACK_DAMAGE); - attactDamageAttribute->setCurrentValue(args[0].asNumber().toFloat()); + attactDamageAttribute->setCurrentValue(args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setAttackDamage!"); + return Boolean::newBoolean(true); + } + CATCH("Fail in setAttackDamage!"); } -Local EntityClass::setMaxAttackDamage(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local EntityClass::setMaxAttackDamage(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - AttributeInstance *attactDamageAttribute = - entity->getMutableAttribute(SharedAttributes::ATTACK_DAMAGE); + AttributeInstance* attactDamageAttribute = entity->getMutableAttribute(SharedAttributes::ATTACK_DAMAGE); - attactDamageAttribute->setMaxValue(args[0].asNumber().toFloat()); + attactDamageAttribute->setMaxValue(args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setMaxAttackDamage!"); + return Boolean::newBoolean(true); + } + CATCH("Fail in setMaxAttackDamage!"); } -Local EntityClass::setFollowRange(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local EntityClass::setFollowRange(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - AttributeInstance *followRangeAttribute = - entity->getMutableAttribute(SharedAttributes::FOLLOW_RANGE); + AttributeInstance* followRangeAttribute = entity->getMutableAttribute(SharedAttributes::FOLLOW_RANGE); - followRangeAttribute->setCurrentValue(args[0].asNumber().toFloat()); + followRangeAttribute->setCurrentValue(args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setFollowRange!"); + return Boolean::newBoolean(true); + } + CATCH("Fail in setFollowRange!"); } -Local EntityClass::setKnockbackResistance(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local EntityClass::setKnockbackResistance(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - AttributeInstance *knockbackResistanceAttribute = - entity->getMutableAttribute(SharedAttributes::KNOCKBACK_RESISTANCE); + AttributeInstance* knockbackResistanceAttribute = + entity->getMutableAttribute(SharedAttributes::KNOCKBACK_RESISTANCE); - knockbackResistanceAttribute->setCurrentValue(args[0].asNumber().toFloat()); + knockbackResistanceAttribute->setCurrentValue(args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setKnockbackResistance!"); + return Boolean::newBoolean(true); + } + CATCH("Fail in setKnockbackResistance!"); } -Local EntityClass::setLuck(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local EntityClass::setLuck(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - AttributeInstance *luckAttribute = - entity->getMutableAttribute(SharedAttributes::LUCK); + AttributeInstance* luckAttribute = entity->getMutableAttribute(SharedAttributes::LUCK); - luckAttribute->setCurrentValue(args[0].asNumber().toFloat()); + luckAttribute->setCurrentValue(args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setLuck!"); + return Boolean::newBoolean(true); + } + CATCH("Fail in setLuck!"); } -Local EntityClass::setMovementSpeed(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local EntityClass::setMovementSpeed(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - AttributeInstance *movementSpeedAttribute = - entity->getMutableAttribute(SharedAttributes::MOVEMENT_SPEED); + AttributeInstance* movementSpeedAttribute = entity->getMutableAttribute(SharedAttributes::MOVEMENT_SPEED); - movementSpeedAttribute->setCurrentValue(args[0].asNumber().toFloat()); + movementSpeedAttribute->setCurrentValue(args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setMovementSpeed!"); + return Boolean::newBoolean(true); + } + CATCH("Fail in setMovementSpeed!"); } -Local EntityClass::setUnderwaterMovementSpeed(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local EntityClass::setUnderwaterMovementSpeed(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - AttributeInstance *underwaterMovementSpeedAttribute = - entity->getMutableAttribute( - SharedAttributes::UNDERWATER_MOVEMENT_SPEED); + AttributeInstance* underwaterMovementSpeedAttribute = + entity->getMutableAttribute(SharedAttributes::UNDERWATER_MOVEMENT_SPEED); - underwaterMovementSpeedAttribute->setCurrentValue( - args[0].asNumber().toFloat()); + underwaterMovementSpeedAttribute->setCurrentValue(args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setUnderwaterMovementSpeed!"); + return Boolean::newBoolean(true); + } + CATCH("Fail in setUnderwaterMovementSpeed!"); } -Local EntityClass::setLavaMovementSpeed(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local EntityClass::setLavaMovementSpeed(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - AttributeInstance *lavaMovementSpeedAttribute = - entity->getMutableAttribute(SharedAttributes::LAVA_MOVEMENT_SPEED); + AttributeInstance* lavaMovementSpeedAttribute = + entity->getMutableAttribute(SharedAttributes::LAVA_MOVEMENT_SPEED); - lavaMovementSpeedAttribute->setCurrentValue(args[0].asNumber().toFloat()); + lavaMovementSpeedAttribute->setCurrentValue(args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setLavaMovementSpeed!"); + return Boolean::newBoolean(true); + } + CATCH("Fail in setLavaMovementSpeed!"); } -Local EntityClass::setMaxHealth(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local EntityClass::setMaxHealth(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - AttributeInstance *healthAttribute = - entity->getMutableAttribute(SharedAttributes::HEALTH); + AttributeInstance* healthAttribute = entity->getMutableAttribute(SharedAttributes::HEALTH); - healthAttribute->setMaxValue(args[0].asNumber().toFloat()); + healthAttribute->setMaxValue(args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setMaxHealth!"); + return Boolean::newBoolean(true); + } + CATCH("Fail in setMaxHealth!"); } // For Compatibility -Local EntityClass::setOnFire(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local EntityClass::setOnFire(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - int time = args[0].toInt(); - entity->setOnFire(time, true); - return Boolean::newBoolean(true); - } - CATCH("Fail in setOnFire!") + int time = args[0].toInt(); + entity->setOnFire(time, true); + return Boolean::newBoolean(true); + } + CATCH("Fail in setOnFire!") } -Local EntityClass::setFire(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kBoolean); +Local EntityClass::setFire(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kBoolean); - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - int time = args[0].toInt(); - bool isEffect = args[1].asBoolean().value(); + int time = args[0].toInt(); + bool isEffect = args[1].asBoolean().value(); - entity->setOnFire(time, isEffect); - return Boolean::newBoolean(true); - } - CATCH("Fail in setFire!") + entity->setOnFire(time, isEffect); + return Boolean::newBoolean(true); + } + CATCH("Fail in setFire!") } -Local EntityClass::stopFire(const Arguments &args) { - try { - Actor *entity = get(); - if (!entity) - return Local(); +Local EntityClass::stopFire(const Arguments& args) { + try { + Actor* entity = get(); + if (!entity) return Local(); - entity->stopFire(); - return Boolean::newBoolean(true); - } - CATCH("Fail in stopFire!") + entity->stopFire(); + return Boolean::newBoolean(true); + } + CATCH("Fail in stopFire!") } #include "mc/entity/utilities/ActorDataIDs.h" -Local EntityClass::setScale(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local EntityClass::setScale(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Actor *entity = get(); - if (!entity) - return Local(); + try { + Actor* entity = get(); + if (!entity) return Local(); - entity->getEntityData().set((ushort)ActorDataIDs::Scale, - args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setScale!") + entity->getEntityData().set((ushort)ActorDataIDs::Scale, args[0].asNumber().toFloat()); + return Boolean::newBoolean(true); + } + CATCH("Fail in setScale!") } -Local EntityClass::getNbt(const Arguments &args) { - try { - Actor *entity = get(); - if (!entity) - return Local(); +Local EntityClass::getNbt(const Arguments& args) { + try { + Actor* entity = get(); + if (!entity) return Local(); - CompoundTag tag = CompoundTag(); - entity->save(tag); - return NbtCompoundClass::pack(&tag); - } - CATCH("Fail in getNbt!") + CompoundTag tag = CompoundTag(); + entity->save(tag); + return NbtCompoundClass::pack(&tag); + } + CATCH("Fail in getNbt!") } #include "mc/dataloadhelper/DefaultDataLoadHelper.h" -Local EntityClass::setNbt(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - - try { - Actor *entity = get(); - if (!entity) - return Local(); - - auto nbt = NbtCompoundClass::extract(args[0]); - if (!nbt) - return Local(); // Null - - DefaultDataLoadHelper helper = DefaultDataLoadHelper(); - return Boolean::newBoolean(entity->load(*nbt, helper)); - } - CATCH("Fail in setNbt!") -} - -Local EntityClass::addTag(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - Actor *entity = get(); - if (!entity) - return Local(); - - return Boolean::newBoolean(entity->addTag(args[0].toStr())); - } - CATCH("Fail in addTag!"); -} - -Local EntityClass::removeTag(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - Actor *entity = get(); - if (!entity) - return Local(); - - return Boolean::newBoolean(entity->removeTag(args[0].toStr())); - } - CATCH("Fail in removeTag!"); -} - -Local EntityClass::hasTag(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - Actor *entity = get(); - if (!entity) - return Local(); - - return Boolean::newBoolean(entity->hasTag(args[0].toStr())); - } - CATCH("Fail in hasTag!"); -} - -Local EntityClass::getAllTags(const Arguments &args) { - try { - Actor *entity = get(); - if (!entity) - return Local(); - - Local arr = Array::newArray(); - CompoundTag tag = CompoundTag(); - entity->save(tag); - tag.getList("tags")->forEachCompoundTag([&arr](const CompoundTag &tag) { - arr.add(String::newString(tag.toString())); - }); - return arr; - } - CATCH("Fail in getAllTags!"); -} - -Local EntityClass::getEntityFromViewVector(const Arguments &args) { - - try { - Actor *actor = get(); - if (!actor) - return Local(); - float maxDistance = 5.25f; - if (args.size() > 0) { - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - maxDistance = args[0].asNumber().toFloat(); - } - Vec3 cameraPos = actor->getHeadPos(); - float distance = 1.0f; - Actor *result = nullptr; - Vec3 resultVec3{}; - HitDetection::searchActors(actor->getViewVector(1.0f), maxDistance, - cameraPos, actor->getAABB(), actor, - (Player *)actor, distance, result, resultVec3, - actor->isType(ActorType::Player) ? true : false); - if (result) - return EntityClass::newEntity(result); - return Local(); - } - CATCH("Fail in getEntityFromViewVector!"); -} - -Local EntityClass::getBlockFromViewVector(const Arguments &args) { - try { - Actor *actor = get(); - if (!actor) - return Local(); - bool includeLiquid = false; - bool solidOnly = false; // not used - float maxDistance = 5.25f; - bool ignoreBorderBlocks = true; // not used - bool fullOnly = false; // not used - if (args.size() > 0) { - CHECK_ARG_TYPE(args[0], ValueKind::kBoolean); - includeLiquid = args[0].asBoolean().value(); - } - if (args.size() > 1) { - CHECK_ARG_TYPE(args[1], ValueKind::kBoolean); - solidOnly = args[1].asBoolean().value(); - } - if (args.size() > 2) { - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - maxDistance = args[2].asNumber().toFloat(); - } - if (args.size() > 3) { - CHECK_ARG_TYPE(args[3], ValueKind::kBoolean); - fullOnly = args[3].asBoolean().value(); - } - HitResult res = actor->traceRay(maxDistance, false, true); - Block bl; - BlockPos bp; - if (includeLiquid && res.mIsHitLiquid) { - bp = res.mLiquidPos; - } else { - bp = res.mBlockPos; - } - actor->getDimensionBlockSource().getBlock(bp); - if (bl.isEmpty()) - return Local(); - return BlockClass::newBlock(std::move(&bl), &bp, - actor->getDimensionId().id); - } - CATCH("Fail in getBlockFromViewVector!"); -} - -Local EntityClass::quickEvalMolangScript(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - Actor *actor = get(); - if (!actor) - return Local(); - return Number::newNumber(actor->quickEvalMolangScript(args[0].toStr())); - } - CATCH("Fail in quickEvalMolangScript!"); +Local EntityClass::setNbt(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + + try { + Actor* entity = get(); + if (!entity) return Local(); + + auto nbt = NbtCompoundClass::extract(args[0]); + if (!nbt) return Local(); // Null + + DefaultDataLoadHelper helper = DefaultDataLoadHelper(); + return Boolean::newBoolean(entity->load(*nbt, helper)); + } + CATCH("Fail in setNbt!") +} + +Local EntityClass::addTag(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + Actor* entity = get(); + if (!entity) return Local(); + + return Boolean::newBoolean(entity->addTag(args[0].toStr())); + } + CATCH("Fail in addTag!"); +} + +Local EntityClass::removeTag(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + Actor* entity = get(); + if (!entity) return Local(); + + return Boolean::newBoolean(entity->removeTag(args[0].toStr())); + } + CATCH("Fail in removeTag!"); +} + +Local EntityClass::hasTag(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + Actor* entity = get(); + if (!entity) return Local(); + + return Boolean::newBoolean(entity->hasTag(args[0].toStr())); + } + CATCH("Fail in hasTag!"); +} + +Local EntityClass::getAllTags(const Arguments& args) { + try { + Actor* entity = get(); + if (!entity) return Local(); + + Local arr = Array::newArray(); + CompoundTag tag = CompoundTag(); + entity->save(tag); + tag.getList("tags")->forEachCompoundTag([&arr](const CompoundTag& tag) { + arr.add(String::newString(tag.toString())); + }); + return arr; + } + CATCH("Fail in getAllTags!"); +} + +Local EntityClass::getEntityFromViewVector(const Arguments& args) { + + try { + Actor* actor = get(); + if (!actor) return Local(); + float maxDistance = 5.25f; + if (args.size() > 0) { + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + maxDistance = args[0].asNumber().toFloat(); + } + Vec3 cameraPos = actor->getHeadPos(); + float distance = 1.0f; + Actor* result = nullptr; + Vec3 resultVec3{}; + HitDetection::searchActors( + actor->getViewVector(1.0f), + maxDistance, + cameraPos, + actor->getAABB(), + actor, + (Player*)actor, + distance, + result, + resultVec3, + actor->isType(ActorType::Player) ? true : false + ); + if (result) return EntityClass::newEntity(result); + return Local(); + } + CATCH("Fail in getEntityFromViewVector!"); +} + +Local EntityClass::getBlockFromViewVector(const Arguments& args) { + try { + Actor* actor = get(); + if (!actor) return Local(); + bool includeLiquid = false; + bool solidOnly = false; // not used + float maxDistance = 5.25f; + bool ignoreBorderBlocks = true; // not used + bool fullOnly = false; // not used + if (args.size() > 0) { + CHECK_ARG_TYPE(args[0], ValueKind::kBoolean); + includeLiquid = args[0].asBoolean().value(); + } + if (args.size() > 1) { + CHECK_ARG_TYPE(args[1], ValueKind::kBoolean); + solidOnly = args[1].asBoolean().value(); + } + if (args.size() > 2) { + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + maxDistance = args[2].asNumber().toFloat(); + } + if (args.size() > 3) { + CHECK_ARG_TYPE(args[3], ValueKind::kBoolean); + fullOnly = args[3].asBoolean().value(); + } + HitResult res = actor->traceRay(maxDistance, false, true); + Block bl; + BlockPos bp; + if (includeLiquid && res.mIsHitLiquid) { + bp = res.mLiquidPos; + } else { + bp = res.mBlockPos; + } + actor->getDimensionBlockSource().getBlock(bp); + if (bl.isEmpty()) return Local(); + return BlockClass::newBlock(std::move(&bl), &bp, actor->getDimensionId().id); + } + CATCH("Fail in getBlockFromViewVector!"); +} + +Local EntityClass::quickEvalMolangScript(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + try { + Actor* actor = get(); + if (!actor) return Local(); + return Number::newNumber(actor->quickEvalMolangScript(args[0].toStr())); + } + CATCH("Fail in quickEvalMolangScript!"); } Local EntityClass::getBiomeId() { - try { - Actor *actor = get(); - if (!actor) - return Local(); - auto bio = - actor->getDimensionBlockSource().getBiome(actor->getFeetBlockPos()); - return Number::newNumber(bio.getId()); - } - CATCH("Fail in getBiomeId!"); + try { + Actor* actor = get(); + if (!actor) return Local(); + auto bio = actor->getDimensionBlockSource().getBiome(actor->getFeetBlockPos()); + return Number::newNumber(bio.getId()); + } + CATCH("Fail in getBiomeId!"); } Local EntityClass::getBiomeName() { - try { - Actor *actor = get(); - if (!actor) - return Local(); - auto bio = - actor->getDimensionBlockSource().getBiome(actor->getFeetBlockPos()); - return String::newString(bio.getName()); - } - CATCH("Fail in getBiomeName!"); + try { + Actor* actor = get(); + if (!actor) return Local(); + auto bio = actor->getDimensionBlockSource().getBiome(actor->getFeetBlockPos()); + return String::newString(bio.getName()); + } + CATCH("Fail in getBiomeName!"); } Local EntityClass::getAllEffects() { - try { - Actor *actor = get(); - if (!actor) { - return Local(); - } - Local effectList = Array::newArray(); - for (unsigned int i = 0; i <= 30; i++) { - if (actor->getEffect(i)) { - effectList.add(Number::newNumber((int)i)); - } - } - return effectList; - } - CATCH("Fail in getAllEffects!") -} - -Local EntityClass::addEffect(const Arguments &args) { - CHECK_ARGS_COUNT(args, 4); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - CHECK_ARG_TYPE(args[3], ValueKind::kBoolean); - try { - Actor *actor = get(); - if (!actor) { - return Boolean::newBoolean(false); - } - unsigned int id = args[0].asNumber().toInt32(); - int tick = args[1].asNumber().toInt32(); - int level = args[2].asNumber().toInt32(); - bool showParticles = args[3].asBoolean().value(); - MobEffectInstance effect = - MobEffectInstance(id, tick, level, false, showParticles, false); - actor->addEffect(effect); - return Boolean::newBoolean(true); - } - CATCH("Fail in addEffect!"); -} - -Local EntityClass::removeEffect(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Actor *actor = get(); - if (!actor) { - return Boolean::newBoolean(false); - } - int id = args[0].asNumber().toInt32(); - actor->removeEffect(id); - return Boolean::newBoolean(true); - } - CATCH("Fail in removeEffect!"); -} - -Local McClass::getAllEntities(const Arguments &args) { - try { - auto &entityList = ll::service::getLevel()->getEntities(); - auto arr = Array::newArray(); - for (auto &i : entityList) { - arr.add(EntityClass::newEntity(i.tryUnwrap())); - } - return arr; - } - CATCH("Fail in GetAllEntities"); -} - -Local McClass::getEntities(const Arguments &args) { - try { - int dim; - float dis = 2.0f; - AABB aabb; - if (args.size() > 0) { - - if (IsInstanceOf(args[0])) { - // IntPos - IntPos *posObj = IntPos::extractPos(args[0]); - - aabb.min = Vec3(posObj->x, posObj->y, posObj->z); - dim = posObj->dim; - - } else if (IsInstanceOf(args[0])) { - // FloatPos - FloatPos *posObj = FloatPos::extractPos(args[0]); - aabb.min = posObj->getVec3(); - dim = posObj->dim; - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - if (args.size() > 1) { - if (IsInstanceOf(args[1])) { - // IntPos - IntPos *posObj = IntPos::extractPos(args[1]); - if (dim != posObj->dim) { - LOG_ERROR_WITH_SCRIPT_INFO("Wrong Dimension!"); - return Local(); - } - aabb.max = Vec3(posObj->x, posObj->y, posObj->z) + 1; - dim = posObj->dim; - - } else if (IsInstanceOf(args[1])) { - // FloatPos - FloatPos *posObj = FloatPos::extractPos(args[1]); - if (dim != posObj->dim) { - LOG_ERROR_WITH_SCRIPT_INFO("Wrong Dimension!"); + try { + Actor* actor = get(); + if (!actor) { return Local(); - } - aabb.max = posObj->getVec3(); - dim = posObj->dim; - } else if (args[1].getKind() == ValueKind::kNumber) { - aabb.max = aabb.min + 1; - dis = args[1].asNumber().toFloat(); - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); } - if (args.size() > 2) { - if (args[2].getKind() == ValueKind::kNumber) { - dis = args[1].asNumber().toFloat(); - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - } else { - aabb.max = aabb.min + 1; + Local effectList = Array::newArray(); + for (unsigned int i = 0; i <= 30; i++) { + if (actor->getEffect(i)) { + effectList.add(Number::newNumber((int)i)); + } } - } else { - aabb.max = aabb.min + 1; - } - } else { - LOG_TOO_FEW_ARGS(); - return Local(); - } - - auto arr = Array::newArray(); - BlockSource &bs = ll::service::getLevel() - ->getDimension(dim) - ->getBlockSourceFromMainChunkSource(); - // if (!bs) { - // LOG_ERROR_WITH_SCRIPT_INFO("Wrong Dimension!"); - // return Local(); - // } - auto entityList = bs.getEntities(aabb, dis); - for (auto i : entityList) { - arr.add(EntityClass::newEntity(i)); - } - return arr; - } - CATCH("Fail in GetAllEntities"); -} - -Local McClass::cloneMob(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - - try { - Actor *ac = EntityClass::extract(args[0]); - if (!ac) { - LOG_WRONG_ARG_TYPE(); - return Local(); // Null - } - - FloatVec4 pos; - - if (args.size() == 2) { - if (IsInstanceOf(args[1])) { - // IntPos - IntPos *posObj = IntPos::extractPos(args[1]); - if (posObj->dim < 0) - return Boolean::newBoolean(false); - else { - pos.x = posObj->x; - pos.y = posObj->y; - pos.z = posObj->z; - pos.dim = posObj->dim; + return effectList; + } + CATCH("Fail in getAllEffects!") +} + +Local EntityClass::addEffect(const Arguments& args) { + CHECK_ARGS_COUNT(args, 4); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + CHECK_ARG_TYPE(args[3], ValueKind::kBoolean); + try { + Actor* actor = get(); + if (!actor) { + return Boolean::newBoolean(false); } - } else if (IsInstanceOf(args[1])) { - // FloatPos - FloatPos *posObj = FloatPos::extractPos(args[1]); - if (posObj->dim < 0) - return Boolean::newBoolean(false); - else { - pos = *posObj; + unsigned int id = args[0].asNumber().toInt32(); + int tick = args[1].asNumber().toInt32(); + int level = args[2].asNumber().toInt32(); + bool showParticles = args[3].asBoolean().value(); + MobEffectInstance effect = MobEffectInstance(id, tick, level, false, showParticles, false); + actor->addEffect(effect); + return Boolean::newBoolean(true); + } + CATCH("Fail in addEffect!"); +} + +Local EntityClass::removeEffect(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + try { + Actor* actor = get(); + if (!actor) { + return Boolean::newBoolean(false); } - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - } else if (args.size() == 5) { - // Number Pos - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - CHECK_ARG_TYPE(args[4], ValueKind::kNumber); - pos = {args[1].asNumber().toFloat(), args[2].asNumber().toFloat(), - args[3].asNumber().toFloat(), args[4].toInt()}; - } else { - LOG_WRONG_ARGS_COUNT(); - return Local(); - } - ActorDefinitionIdentifier id(ac->getTypeName()); - Mob *entity = ll::service::getLevel()->getSpawner().spawnMob( - ll::service::getLevel() - ->getDimension(pos.dim) - ->getBlockSourceFromMainChunkSource(), - id, nullptr, pos.getVec3(), false, true, false); - if (!entity) - return Local(); // Null - else - return EntityClass::newEntity(entity); - } - CATCH("Fail in CloneMob!"); -} - -Local McClass::spawnMob(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - string name = args[0].toStr(); - FloatVec4 pos; - - if (args.size() == 2) { - if (IsInstanceOf(args[1])) { - // IntPos - IntPos *posObj = IntPos::extractPos(args[1]); - if (posObj->dim < 0) - return Boolean::newBoolean(false); - else { - pos.x = posObj->x; - pos.y = posObj->y; - pos.z = posObj->z; - pos.dim = posObj->dim; + int id = args[0].asNumber().toInt32(); + actor->removeEffect(id); + return Boolean::newBoolean(true); + } + CATCH("Fail in removeEffect!"); +} + +Local McClass::getAllEntities(const Arguments& args) { + try { + auto& entityList = ll::service::getLevel()->getEntities(); + auto arr = Array::newArray(); + for (auto& i : entityList) { + arr.add(EntityClass::newEntity(i.tryUnwrap())); } - } else if (IsInstanceOf(args[1])) { - // FloatPos - FloatPos *posObj = FloatPos::extractPos(args[1]); - if (posObj->dim < 0) - return Boolean::newBoolean(false); - else { - pos = *posObj; + return arr; + } + CATCH("Fail in GetAllEntities"); +} + +Local McClass::getEntities(const Arguments& args) { + try { + int dim; + float dis = 2.0f; + AABB aabb; + if (args.size() > 0) { + + if (IsInstanceOf(args[0])) { + // IntPos + IntPos* posObj = IntPos::extractPos(args[0]); + + aabb.min = Vec3(posObj->x, posObj->y, posObj->z); + dim = posObj->dim; + + } else if (IsInstanceOf(args[0])) { + // FloatPos + FloatPos* posObj = FloatPos::extractPos(args[0]); + aabb.min = posObj->getVec3(); + dim = posObj->dim; + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + if (args.size() > 1) { + if (IsInstanceOf(args[1])) { + // IntPos + IntPos* posObj = IntPos::extractPos(args[1]); + if (dim != posObj->dim) { + LOG_ERROR_WITH_SCRIPT_INFO("Wrong Dimension!"); + return Local(); + } + aabb.max = Vec3(posObj->x, posObj->y, posObj->z) + 1; + dim = posObj->dim; + + } else if (IsInstanceOf(args[1])) { + // FloatPos + FloatPos* posObj = FloatPos::extractPos(args[1]); + if (dim != posObj->dim) { + LOG_ERROR_WITH_SCRIPT_INFO("Wrong Dimension!"); + return Local(); + } + aabb.max = posObj->getVec3(); + dim = posObj->dim; + } else if (args[1].getKind() == ValueKind::kNumber) { + aabb.max = aabb.min + 1; + dis = args[1].asNumber().toFloat(); + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + if (args.size() > 2) { + if (args[2].getKind() == ValueKind::kNumber) { + dis = args[1].asNumber().toFloat(); + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + } else { + aabb.max = aabb.min + 1; + } + } else { + aabb.max = aabb.min + 1; + } + } else { + LOG_TOO_FEW_ARGS(); + return Local(); } - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - } else if (args.size() == 5) { - // Number Pos - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - CHECK_ARG_TYPE(args[4], ValueKind::kNumber); - pos = {args[1].asNumber().toFloat(), args[2].asNumber().toFloat(), - args[3].asNumber().toFloat(), args[4].toInt()}; - } else { - LOG_WRONG_ARGS_COUNT(); - return Local(); - } - - ActorDefinitionIdentifier id(name); - Mob *entity = ll::service::getLevel()->getSpawner().spawnMob( - ll::service::getLevel() - ->getDimension(pos.dim) - ->getBlockSourceFromMainChunkSource(), - id, nullptr, pos.getVec3(), false, true, false); - if (!entity) - return Local(); // Null - else - return EntityClass::newEntity(entity); - } - CATCH("Fail in SpawnMob!"); -} - -Local McClass::explode(const Arguments &args) { - CHECK_ARGS_COUNT(args, 5); - - try { - FloatVec4 pos; - int beginIndex; - if (args.size() == 5) { - // PosObj - beginIndex = 1; - - if (IsInstanceOf(args[0])) { - // IntPos - IntPos *posObj = IntPos::extractPos(args[0]); - if (posObj->dim < 0) - return Boolean::newBoolean(false); - else { - pos.x = posObj->x; - pos.y = posObj->y; - pos.z = posObj->z; - pos.dim = posObj->dim; + + auto arr = Array::newArray(); + BlockSource& bs = ll::service::getLevel()->getDimension(dim)->getBlockSourceFromMainChunkSource(); + // if (!bs) { + // LOG_ERROR_WITH_SCRIPT_INFO("Wrong Dimension!"); + // return Local(); + // } + auto entityList = bs.getEntities(aabb, dis); + for (auto i : entityList) { + arr.add(EntityClass::newEntity(i)); } - } else if (IsInstanceOf(args[0])) { - // FloatPos - FloatPos *posObj = FloatPos::extractPos(args[0]); - if (posObj->dim < 0) - return Boolean::newBoolean(false); - else { - pos = *posObj; + return arr; + } + CATCH("Fail in GetAllEntities"); +} + +Local McClass::cloneMob(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + + try { + Actor* ac = EntityClass::extract(args[0]); + if (!ac) { + LOG_WRONG_ARG_TYPE(); + return Local(); // Null } - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - } else if (args.size() == 8) { - // Number Pos - beginIndex = 4; - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - pos = {args[0].asNumber().toFloat(), args[1].asNumber().toFloat(), - args[2].asNumber().toFloat(), args[3].toInt()}; - } else { - LOG_WRONG_ARGS_COUNT(); - return Local(); - } - - auto source = EntityClass::extract(args[beginIndex + 0]); // Can be nullptr - - CHECK_ARG_TYPE(args[beginIndex + 1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[beginIndex + 2], ValueKind::kBoolean); - CHECK_ARG_TYPE(args[beginIndex + 3], ValueKind::kBoolean); - - float power = args[beginIndex + 1].asNumber().toFloat(); - bool isDestroy = args[beginIndex + 2].asBoolean().value(); - bool isFire = args[beginIndex + 3].asBoolean().value(); - - ll::service::getLevel()->explode(ll::service::getLevel() - ->getDimension(pos.dim) - ->getBlockSourceFromMainChunkSource(), - source, pos.getVec3(), power, isFire, - isDestroy, 3.40282347e+38, false); - return Boolean::newBoolean(true); - } - CATCH("Fail in Explode!"); + + FloatVec4 pos; + + if (args.size() == 2) { + if (IsInstanceOf(args[1])) { + // IntPos + IntPos* posObj = IntPos::extractPos(args[1]); + if (posObj->dim < 0) return Boolean::newBoolean(false); + else { + pos.x = posObj->x; + pos.y = posObj->y; + pos.z = posObj->z; + pos.dim = posObj->dim; + } + } else if (IsInstanceOf(args[1])) { + // FloatPos + FloatPos* posObj = FloatPos::extractPos(args[1]); + if (posObj->dim < 0) return Boolean::newBoolean(false); + else { + pos = *posObj; + } + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + } else if (args.size() == 5) { + // Number Pos + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + CHECK_ARG_TYPE(args[4], ValueKind::kNumber); + pos = { + args[1].asNumber().toFloat(), + args[2].asNumber().toFloat(), + args[3].asNumber().toFloat(), + args[4].toInt()}; + } else { + LOG_WRONG_ARGS_COUNT(); + return Local(); + } + ActorDefinitionIdentifier id(ac->getTypeName()); + Mob* entity = ll::service::getLevel()->getSpawner().spawnMob( + ll::service::getLevel()->getDimension(pos.dim)->getBlockSourceFromMainChunkSource(), + id, + nullptr, + pos.getVec3(), + false, + true, + false + ); + if (!entity) return Local(); // Null + else return EntityClass::newEntity(entity); + } + CATCH("Fail in CloneMob!"); +} + +Local McClass::spawnMob(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + string name = args[0].toStr(); + FloatVec4 pos; + + if (args.size() == 2) { + if (IsInstanceOf(args[1])) { + // IntPos + IntPos* posObj = IntPos::extractPos(args[1]); + if (posObj->dim < 0) return Boolean::newBoolean(false); + else { + pos.x = posObj->x; + pos.y = posObj->y; + pos.z = posObj->z; + pos.dim = posObj->dim; + } + } else if (IsInstanceOf(args[1])) { + // FloatPos + FloatPos* posObj = FloatPos::extractPos(args[1]); + if (posObj->dim < 0) return Boolean::newBoolean(false); + else { + pos = *posObj; + } + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + } else if (args.size() == 5) { + // Number Pos + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + CHECK_ARG_TYPE(args[4], ValueKind::kNumber); + pos = { + args[1].asNumber().toFloat(), + args[2].asNumber().toFloat(), + args[3].asNumber().toFloat(), + args[4].toInt()}; + } else { + LOG_WRONG_ARGS_COUNT(); + return Local(); + } + + ActorDefinitionIdentifier id(name); + Mob* entity = ll::service::getLevel()->getSpawner().spawnMob( + ll::service::getLevel()->getDimension(pos.dim)->getBlockSourceFromMainChunkSource(), + id, + nullptr, + pos.getVec3(), + false, + true, + false + ); + if (!entity) return Local(); // Null + else return EntityClass::newEntity(entity); + } + CATCH("Fail in SpawnMob!"); +} + +Local McClass::explode(const Arguments& args) { + CHECK_ARGS_COUNT(args, 5); + + try { + FloatVec4 pos; + int beginIndex; + if (args.size() == 5) { + // PosObj + beginIndex = 1; + + if (IsInstanceOf(args[0])) { + // IntPos + IntPos* posObj = IntPos::extractPos(args[0]); + if (posObj->dim < 0) return Boolean::newBoolean(false); + else { + pos.x = posObj->x; + pos.y = posObj->y; + pos.z = posObj->z; + pos.dim = posObj->dim; + } + } else if (IsInstanceOf(args[0])) { + // FloatPos + FloatPos* posObj = FloatPos::extractPos(args[0]); + if (posObj->dim < 0) return Boolean::newBoolean(false); + else { + pos = *posObj; + } + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + } else if (args.size() == 8) { + // Number Pos + beginIndex = 4; + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + pos = { + args[0].asNumber().toFloat(), + args[1].asNumber().toFloat(), + args[2].asNumber().toFloat(), + args[3].toInt()}; + } else { + LOG_WRONG_ARGS_COUNT(); + return Local(); + } + + auto source = EntityClass::extract(args[beginIndex + 0]); // Can be nullptr + + CHECK_ARG_TYPE(args[beginIndex + 1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[beginIndex + 2], ValueKind::kBoolean); + CHECK_ARG_TYPE(args[beginIndex + 3], ValueKind::kBoolean); + + float power = args[beginIndex + 1].asNumber().toFloat(); + bool isDestroy = args[beginIndex + 2].asBoolean().value(); + bool isFire = args[beginIndex + 3].asBoolean().value(); + + ll::service::getLevel()->explode( + ll::service::getLevel()->getDimension(pos.dim)->getBlockSourceFromMainChunkSource(), + source, + pos.getVec3(), + power, + isFire, + isDestroy, + 3.40282347e+38, + false + ); + return Boolean::newBoolean(true); + } + CATCH("Fail in Explode!"); } diff --git a/src/api/EntityAPI.h b/src/api/EntityAPI.h index 8d724b52..3bd030c2 100644 --- a/src/api/EntityAPI.h +++ b/src/api/EntityAPI.h @@ -6,115 +6,112 @@ class Actor; class EntityClass : public ScriptClass { private: - ActorUniqueID id; - bool isValid = true; + ActorUniqueID id; + bool isValid = true; public: - explicit EntityClass(Actor *p) - : ScriptClass(ScriptClass::ConstructFromCpp{}) { - set(p); - } + explicit EntityClass(Actor* p) : ScriptClass(ScriptClass::ConstructFromCpp{}) { set(p); } - void set(Actor *actor); - Actor *get(); + void set(Actor* actor); + Actor* get(); - static Local newEntity(Actor *p); - static Actor *extract(Local v); - static std::optional tryExtractActor(Local v); - Local asPointer(const Arguments &args); + static Local newEntity(Actor* p); + static Actor* extract(Local v); + static std::optional tryExtractActor(Local v); + Local asPointer(const Arguments& args); - Local getName(); - Local getType(); - Local getId(); - Local getPos(); - Local getPosDelta(); - Local getFeetPos(); - Local getBlockPos(); - Local getMaxHealth(); - Local getHealth(); - Local getCanFly(); - Local getCanFreeze(); - Local getCanSeeDaylight(); - Local getCanPickupItems(); - Local getInAir(); - Local getInWater(); - Local getInClouds(); - Local getInLava(); - Local getInRain(); - Local getInSnow(); - Local getInWall(); - Local getInWaterOrRain(); - Local getInWorld(); - Local getSpeed(); - Local getBiomeName(); - Local getBiomeId(); - Local getDirection(); - Local getUniqueID(); - Local isInvisible(); - Local isInsidePortal(); - Local isTrusting(); - Local isTouchingDamageBlock(); - Local isOnFire(); - Local isOnGround(); - Local isOnHotBlock(); - Local isTrading(); - Local isRiding(); - Local isDancing(); - Local isSleeping(); - Local isAngry(); - Local isBaby(); - Local isMoving(); + Local getName(); + Local getType(); + Local getId(); + Local getPos(); + Local getPosDelta(); + Local getFeetPos(); + Local getBlockPos(); + Local getMaxHealth(); + Local getHealth(); + Local getCanFly(); + Local getCanFreeze(); + Local getCanSeeDaylight(); + Local getCanPickupItems(); + Local getInAir(); + Local getInWater(); + Local getInClouds(); + Local getInLava(); + Local getInRain(); + Local getInSnow(); + Local getInWall(); + Local getInWaterOrRain(); + Local getInWorld(); + Local getSpeed(); + Local getBiomeName(); + Local getBiomeId(); + Local getDirection(); + Local getUniqueID(); + Local isInvisible(); + Local isInsidePortal(); + Local isTrusting(); + Local isTouchingDamageBlock(); + Local isOnFire(); + Local isOnGround(); + Local isOnHotBlock(); + Local isTrading(); + Local isRiding(); + Local isDancing(); + Local isSleeping(); + Local isAngry(); + Local isBaby(); + Local isMoving(); - Local setPosDelta(const Arguments &args); - Local teleport(const Arguments &args); - Local kill(const Arguments &args); - Local despawn(const Arguments &args); - Local remove(const Arguments &args); - Local hurt(const Arguments &args); - Local heal(const Arguments &args); - Local setHealth(const Arguments &args); - Local setAbsorption(const Arguments &args); - Local setAttackDamage(const Arguments &args); - Local setMaxAttackDamage(const Arguments &args); - Local setFollowRange(const Arguments &args); - Local setKnockbackResistance(const Arguments &args); - Local setLuck(const Arguments &args); - Local setMovementSpeed(const Arguments &args); - Local setUnderwaterMovementSpeed(const Arguments &args); - Local setLavaMovementSpeed(const Arguments &args); - Local setMaxHealth(const Arguments &args); - Local setOnFire(const Arguments &args); - Local setFire(const Arguments &args); - Local stopFire(const Arguments &args); - Local setScale(const Arguments &args); + Local setPosDelta(const Arguments& args); + Local teleport(const Arguments& args); + Local kill(const Arguments& args); + Local despawn(const Arguments& args); + Local remove(const Arguments& args); + Local hurt(const Arguments& args); + Local heal(const Arguments& args); + Local setHealth(const Arguments& args); + Local setAbsorption(const Arguments& args); + Local setAttackDamage(const Arguments& args); + Local setMaxAttackDamage(const Arguments& args); + Local setFollowRange(const Arguments& args); + Local setKnockbackResistance(const Arguments& args); + Local setLuck(const Arguments& args); + Local setMovementSpeed(const Arguments& args); + Local setUnderwaterMovementSpeed(const Arguments& args); + Local setLavaMovementSpeed(const Arguments& args); + Local setMaxHealth(const Arguments& args); + Local setOnFire(const Arguments& args); + Local setFire(const Arguments& args); + Local stopFire(const Arguments& args); + Local setScale(const Arguments& args); - Local distanceTo(const Arguments &args); - Local distanceToSqr(const Arguments &args); + Local distanceTo(const Arguments& args); + Local distanceToSqr(const Arguments& args); - Local isPlayer(const Arguments &args); - Local toPlayer(const Arguments &args); - Local isItemEntity(const Arguments &args); - Local toItem(const Arguments &args); - Local getBlockStandingOn(const Arguments &args); - Local getArmor(const Arguments &args); - Local hasContainer(const Arguments &args); - Local getContainer(const Arguments &args); - Local refreshItems(const Arguments &args); + Local isPlayer(const Arguments& args); + Local toPlayer(const Arguments& args); + Local isItemEntity(const Arguments& args); + Local toItem(const Arguments& args); + Local getBlockStandingOn(const Arguments& args); + Local getArmor(const Arguments& args); + Local hasContainer(const Arguments& args); + Local getContainer(const Arguments& args); + Local refreshItems(const Arguments& args); - Local getNbt(const Arguments &args); - Local setNbt(const Arguments &args); - Local addTag(const Arguments &args); - Local removeTag(const Arguments &args); - Local hasTag(const Arguments &args); - Local getAllTags(const Arguments &args); - Local getEntityFromViewVector(const Arguments &args); - Local getBlockFromViewVector(const Arguments &args); + Local getNbt(const Arguments& args); + Local setNbt(const Arguments& args); + Local addTag(const Arguments& args); + Local removeTag(const Arguments& args); + Local hasTag(const Arguments& args); + Local getAllTags(const Arguments& args); + Local getEntityFromViewVector(const Arguments& args); + Local getBlockFromViewVector(const Arguments& args); - Local quickEvalMolangScript(const Arguments &args); + Local quickEvalMolangScript(const Arguments& args); - Local getAllEffects(); - Local addEffect(const Arguments &args); - Local removeEffect(const Arguments &args); + Local getAllEffects(); + Local addEffect(const Arguments& args); + Local removeEffect(const Arguments& args); }; extern ClassDefine EntityClassBuilder; -extern ClassDefine ActorDamageCauseBuilder; \ No newline at end of file +extern ClassDefine ActorDamageCauseBuilder; \ No newline at end of file diff --git a/src/api/EventAPI.cpp b/src/api/EventAPI.cpp index 35e1fc33..3ab051cd 100644 --- a/src/api/EventAPI.cpp +++ b/src/api/EventAPI.cpp @@ -9,7 +9,7 @@ #include "ll/api/schedule/Scheduler.h" #include "ll/api/schedule/Task.h" #include "ll/api/service/Bedrock.h" -#include "main/Global.hpp" +#include "main/Global.h" #include #include #include @@ -28,109 +28,109 @@ //////////////////// Listeners //////////////////// enum class EVENT_TYPES : int { - /* Player Events */ - - onPreJoin = 0, - onJoin, - onLeft, - onRespawn, - onPlayerDie, - onPlayerCmd, - onChat, - onChangeDim, - onJump, - onSneak, - onPlayerSwing, - onAttackEntity, - onAttackBlock, - onUseItem, - onUseItemOn, - onUseBucketPlace, - onUseBucketTake, - onTakeItem, - onDropItem, - onEat, - onAte, - onConsumeTotem, - onEffectAdded, - onEffectUpdated, - onEffectRemoved, - onStartDestroyBlock, - onDestroyBlock, - onPlaceBlock, - afterPlaceBlock, - onOpenContainer, - onCloseContainer, - onInventoryChange, - onPlayerPullFishingHook, - // onMove, - onChangeSprinting, - onSetArmor, - onUseRespawnAnchor, - onOpenContainerScreen, - onExperienceAdd, - onBedEnter, - onOpenInventory, - /* Entity Events */ - onMobDie, - onMobHurt, - onEntityExplode, - onProjectileHitEntity, - onWitherBossDestroy, - onRide, - onStepOnPressurePlate, - onSpawnProjectile, - onProjectileCreated, - onChangeArmorStand, - onEntityTransformation, - /* Block Events */ - onBlockInteracted, - onBlockChanged, - onBlockExplode, - onRespawnAnchorExplode, - onBlockExploded, - onFireSpread, - onCmdBlockExecute, - onContainerChange, - onProjectileHitBlock, - onRedStoneUpdate, - onHopperSearchItem, - onHopperPushOut, - onPistonTryPush, - onPistonPush, - onFarmLandDecay, - onUseFrameBlock, - onLiquidFlow, - /* Other Events */ - onScoreChanged, - onTick, - onServerStarted, - onConsoleCmd, - onConsoleOutput, - /* Economic Events */ - onMoneyAdd, - onMoneyReduce, - onMoneyTrans, - onMoneySet, - beforeMoneyAdd, - beforeMoneyReduce, - beforeMoneyTrans, - beforeMoneySet, - onFormResponsePacket, - /* Outdated Events */ - onAttack, - onExplode, - onBedExplode, - onMobSpawn, - onMobTrySpawn, - onMobSpawned, - onContainerChangeSlot, - EVENT_COUNT + /* Player Events */ + + onPreJoin = 0, + onJoin, + onLeft, + onRespawn, + onPlayerDie, + onPlayerCmd, + onChat, + onChangeDim, + onJump, + onSneak, + onPlayerSwing, + onAttackEntity, + onAttackBlock, + onUseItem, + onUseItemOn, + onUseBucketPlace, + onUseBucketTake, + onTakeItem, + onDropItem, + onEat, + onAte, + onConsumeTotem, + onEffectAdded, + onEffectUpdated, + onEffectRemoved, + onStartDestroyBlock, + onDestroyBlock, + onPlaceBlock, + afterPlaceBlock, + onOpenContainer, + onCloseContainer, + onInventoryChange, + onPlayerPullFishingHook, + // onMove, + onChangeSprinting, + onSetArmor, + onUseRespawnAnchor, + onOpenContainerScreen, + onExperienceAdd, + onBedEnter, + onOpenInventory, + /* Entity Events */ + onMobDie, + onMobHurt, + onEntityExplode, + onProjectileHitEntity, + onWitherBossDestroy, + onRide, + onStepOnPressurePlate, + onSpawnProjectile, + onProjectileCreated, + onChangeArmorStand, + onEntityTransformation, + /* Block Events */ + onBlockInteracted, + onBlockChanged, + onBlockExplode, + onRespawnAnchorExplode, + onBlockExploded, + onFireSpread, + onCmdBlockExecute, + onContainerChange, + onProjectileHitBlock, + onRedStoneUpdate, + onHopperSearchItem, + onHopperPushOut, + onPistonTryPush, + onPistonPush, + onFarmLandDecay, + onUseFrameBlock, + onLiquidFlow, + /* Other Events */ + onScoreChanged, + onTick, + onServerStarted, + onConsoleCmd, + onConsoleOutput, + /* Economic Events */ + onMoneyAdd, + onMoneyReduce, + onMoneyTrans, + onMoneySet, + beforeMoneyAdd, + beforeMoneyReduce, + beforeMoneyTrans, + beforeMoneySet, + onFormResponsePacket, + /* Outdated Events */ + onAttack, + onExplode, + onBedExplode, + onMobSpawn, + onMobTrySpawn, + onMobSpawned, + onContainerChangeSlot, + EVENT_COUNT }; struct ListenerListType { - ScriptEngine *engine; - script::Global func; + ScriptEngine* engine; + script::Global func; }; // 监听器表 @@ -140,1357 +140,1341 @@ static std::list listenerList[int(EVENT_TYPES::EVENT_COUNT)]; static bool hasListened[int(EVENT_TYPES::EVENT_COUNT)] = {false}; // 监听器异常拦截 -string EventTypeToString(EVENT_TYPES e) { - return string(magic_enum::enum_name(e)); -} - -#define LISTENER_CATCH(TYPE) \ - catch (const Exception &e) { \ - logger.error("Event Callback Failed!"); \ - logger.error(e.what()); \ - logger.error("In Event: " + EventTypeToString(TYPE)); \ - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); \ - } \ - catch (const std::exception &e) { \ - logger.error("Event Callback Failed!"); \ - logger.error("C++ Uncaught Exception Detected!"); \ - logger.error(ll::string_utils::tou8str(e.what())); \ - PrintScriptStackTrace(); \ - logger.error("In Event: " + EventTypeToString(TYPE)); \ - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); \ - } +string EventTypeToString(EVENT_TYPES e) { return string(magic_enum::enum_name(e)); } + +#define LISTENER_CATCH(TYPE) \ + catch (const Exception& e) { \ + logger.error("Event Callback Failed!"); \ + logger.error(e.what()); \ + logger.error("In Event: " + EventTypeToString(TYPE)); \ + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); \ + } \ + catch (const std::exception& e) { \ + logger.error("Event Callback Failed!"); \ + logger.error("C++ Uncaught Exception Detected!"); \ + logger.error(ll::string_utils::tou8str(e.what())); \ + PrintScriptStackTrace(); \ + logger.error("In Event: " + EventTypeToString(TYPE)); \ + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); \ + } // 调用事件监听函数,拦截不执行original -#define CallEventRtnVoid(TYPE, ...) \ - std::list &nowList = listenerList[int(TYPE)]; \ - bool passToBDS = true; \ - for (auto &listener : nowList) { \ - EngineScope enter(listener.engine); \ - try { \ - auto result = listener.func.get().call({}, __VA_ARGS__); \ - if (result.isBoolean() && result.asBoolean().value() == false) \ - passToBDS = false; \ - } \ - LISTENER_CATCH(TYPE) \ - } \ - if (!passToBDS) { \ - return; \ - } +#define CallEventRtnVoid(TYPE, ...) \ + std::list& nowList = listenerList[int(TYPE)]; \ + bool passToBDS = true; \ + for (auto& listener : nowList) { \ + EngineScope enter(listener.engine); \ + try { \ + auto result = listener.func.get().call({}, __VA_ARGS__); \ + if (result.isBoolean() && result.asBoolean().value() == false) passToBDS = false; \ + } \ + LISTENER_CATCH(TYPE) \ + } \ + if (!passToBDS) { \ + return; \ + } // 调用事件监听函数,拦截返回false -#define CallEvent(TYPE, ...) \ - std::list &nowList = listenerList[int(TYPE)]; \ - bool passToBDS = true; \ - for (auto &listener : nowList) { \ - EngineScope enter(listener.engine); \ - try { \ - auto result = listener.func.get().call({}, __VA_ARGS__); \ - if (result.isBoolean() && result.asBoolean().value() == false) \ - passToBDS = false; \ - } \ - LISTENER_CATCH(TYPE) \ - } \ - return passToBDS; +#define CallEvent(TYPE, ...) \ + std::list& nowList = listenerList[int(TYPE)]; \ + bool passToBDS = true; \ + for (auto& listener : nowList) { \ + EngineScope enter(listener.engine); \ + try { \ + auto result = listener.func.get().call({}, __VA_ARGS__); \ + if (result.isBoolean() && result.asBoolean().value() == false) passToBDS = false; \ + } \ + LISTENER_CATCH(TYPE) \ + } \ + return passToBDS; // 调用事件监听函数,拦截返回RETURN_VALUE -#define CallEventRtnValue(TYPE, RETURN_VALUE, ...) \ - std::list &nowList = listenerList[int(TYPE)]; \ - bool passToBDS = true; \ - for (auto &listener : nowList) { \ - EngineScope enter(listener.engine); \ - try { \ - auto result = listener.func.get().call({}, __VA_ARGS__); \ - if (result.isBoolean() && result.asBoolean().value() == false) \ - passToBDS = false; \ - } \ - LISTENER_CATCH(TYPE) \ - } \ - if (!passToBDS) { \ - return RETURN_VALUE; \ - } +#define CallEventRtnValue(TYPE, RETURN_VALUE, ...) \ + std::list& nowList = listenerList[int(TYPE)]; \ + bool passToBDS = true; \ + for (auto& listener : nowList) { \ + EngineScope enter(listener.engine); \ + try { \ + auto result = listener.func.get().call({}, __VA_ARGS__); \ + if (result.isBoolean() && result.asBoolean().value() == false) passToBDS = false; \ + } \ + LISTENER_CATCH(TYPE) \ + } \ + if (!passToBDS) { \ + return RETURN_VALUE; \ + } // 模拟事件调用监听 -#define FakeCallEvent(ENGINE, TYPE, ...) \ - { \ - std::list &nowList = listenerList[int(TYPE)]; \ - for (auto &listener : nowList) { \ - if (listener.engine == ENGINE) { \ - EngineScope enter(listener.engine); \ - try { \ - listener.func.get().call({}, __VA_ARGS__); \ - } \ - LISTENER_CATCH(TYPE) \ - } \ - } \ - } +#define FakeCallEvent(ENGINE, TYPE, ...) \ + { \ + std::list& nowList = listenerList[int(TYPE)]; \ + for (auto& listener : nowList) { \ + if (listener.engine == ENGINE) { \ + EngineScope enter(listener.engine); \ + try { \ + listener.func.get().call({}, __VA_ARGS__); \ + } \ + LISTENER_CATCH(TYPE) \ + } \ + } \ + } // 延迟调用事件 -#define CallEventDelayed(TYPE, ...) \ - std::list &nowList = listenerList[int(TYPE)]; \ - for (auto &listener : nowList) { \ - EngineScope enter(listener.engine); \ - try { \ - NewTimeout(listener.func.get(), {__VA_ARGS__}, 5); \ - } \ - LISTENER_CATCH(TYPE) \ - } +#define CallEventDelayed(TYPE, ...) \ + std::list& nowList = listenerList[int(TYPE)]; \ + for (auto& listener : nowList) { \ + EngineScope enter(listener.engine); \ + try { \ + NewTimeout(listener.func.get(), {__VA_ARGS__}, 5); \ + } \ + LISTENER_CATCH(TYPE) \ + } // 异常检查 -#define IF_LISTENED(TYPE) \ - if (!listenerList[int(TYPE)].empty()) { \ - try -#define IF_LISTENED_END(TYPE) \ - catch (...) { \ - logger.error("Event Callback Failed!"); \ - logger.error("Uncaught Exception Detected!"); \ - logger.error("In Event: " + EventTypeToString(TYPE)); \ - } \ - } \ - return true; +#define IF_LISTENED(TYPE) \ + if (!listenerList[int(TYPE)].empty()) { \ + try +#define IF_LISTENED_END(TYPE) \ + catch (...) { \ + logger.error("Event Callback Failed!"); \ + logger.error("Uncaught Exception Detected!"); \ + logger.error("In Event: " + EventTypeToString(TYPE)); \ + } \ + } \ + return true; //////////////////// APIs //////////////////// -Local McClass::listen(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kFunction); +Local McClass::listen(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kFunction); - try { - return Boolean::newBoolean(LLSEAddEventListener( - EngineScope::currentEngine(), args[0].toStr(), args[1].asFunction())); - } - CATCH("Fail to Bind Listener!"); + try { + return Boolean::newBoolean( + LLSEAddEventListener(EngineScope::currentEngine(), args[0].toStr(), args[1].asFunction()) + ); + } + CATCH("Fail to Bind Listener!"); } //////////////////// Funcs //////////////////// -bool LLSEAddEventListener(ScriptEngine *engine, const string &eventName, - const Local &func) { - try { - auto event_enum = magic_enum::enum_cast(eventName); - auto eventId = int(event_enum.value()); - listenerList[eventId].push_back({engine, script::Global(func)}); - if (!hasListened[eventId]) { - hasListened[eventId] = true; - EnableEventListener(eventId); +bool LLSEAddEventListener(ScriptEngine* engine, const string& eventName, const Local& func) { + try { + auto event_enum = magic_enum::enum_cast(eventName); + auto eventId = int(event_enum.value()); + listenerList[eventId].push_back({engine, script::Global(func)}); + if (!hasListened[eventId]) { + hasListened[eventId] = true; + EnableEventListener(eventId); + } + return true; + } catch (...) { + logger.error("Event \"" + eventName + "\" No Found!\n"); + logger.error("In Plugin: " + ENGINE_GET_DATA(engine)->pluginName); + return false; + } +} + +bool LLSERemoveAllEventListeners(ScriptEngine* engine) { + for (auto& listeners : listenerList) { + listeners.remove_if([engine](auto& listener) { return listener.engine == engine; }); } return true; - } catch (...) { - logger.error("Event \"" + eventName + "\" No Found!\n"); - logger.error("In Plugin: " + ENGINE_GET_DATA(engine)->pluginName); - return false; - } } -bool LLSERemoveAllEventListeners(ScriptEngine *engine) { - for (auto &listeners : listenerList) { - listeners.remove_if( - [engine](auto &listener) { return listener.engine == engine; }); - } - return true; -} +bool LLSECallEventsOnHotLoad(ScriptEngine* engine) { + FakeCallEvent(engine, EVENT_TYPES::onServerStarted); -bool LLSECallEventsOnHotLoad(ScriptEngine *engine) { - FakeCallEvent(engine, EVENT_TYPES::onServerStarted); + ll::service::getLevel()->forEachPlayer([&](Player& pl) -> bool { + FakeCallEvent(engine, EVENT_TYPES::onPreJoin, PlayerClass::newPlayer(&pl)); + return true; + }); + ll::service::getLevel()->forEachPlayer([&](Player& pl) -> bool { + FakeCallEvent(engine, EVENT_TYPES::onJoin, PlayerClass::newPlayer(&pl)); + return true; + }); - ll::service::getLevel()->forEachPlayer([&](Player &pl) -> bool { - FakeCallEvent(engine, EVENT_TYPES::onPreJoin, PlayerClass::newPlayer(&pl)); - return true; - }); - ll::service::getLevel()->forEachPlayer([&](Player &pl) -> bool { - FakeCallEvent(engine, EVENT_TYPES::onJoin, PlayerClass::newPlayer(&pl)); return true; - }); - - return true; } -bool LLSECallEventsOnHotUnload(ScriptEngine *engine) { - ll::service::getLevel()->forEachPlayer([&](Player &pl) -> bool { - FakeCallEvent(engine, EVENT_TYPES::onLeft, PlayerClass::newPlayer(&pl)); - }); - for (auto &[index, cb] : ENGINE_GET_DATA(engine)->unloadCallbacks) { - cb(engine); - } - ENGINE_GET_DATA(engine)->unloadCallbacks.clear(); - return true; +bool LLSECallEventsOnHotUnload(ScriptEngine* engine) { + ll::service::getLevel()->forEachPlayer([&](Player& pl) -> bool { + FakeCallEvent(engine, EVENT_TYPES::onLeft, PlayerClass::newPlayer(&pl)); + }); + for (auto& [index, cb] : ENGINE_GET_DATA(engine)->unloadCallbacks) { + cb(engine); + } + ENGINE_GET_DATA(engine)->unloadCallbacks.clear(); + return true; } //////////////////// Events //////////////////// // Todo void EnableEventListener(int eventId) { - using namespace ll::event; - EventBus &bus = EventBus::getInstance(); - switch ((EVENT_TYPES)eventId) { - case EVENT_TYPES::onJoin: - bus.emplaceListener([](PlayerJoinEvent &ev) { - IF_LISTENED(EVENT_TYPES::onJoin) { - CallEvent(EVENT_TYPES::onJoin, PlayerClass::newPlayer(&ev.self())); - } - IF_LISTENED_END(EVENT_TYPES::onJoin); - }); - break; - - case EVENT_TYPES::onPreJoin: - bus.emplaceListener([](PlayerConnectEvent &ev) { - IF_LISTENED(EVENT_TYPES::onPreJoin) { - CallEvent(EVENT_TYPES::onPreJoin, PlayerClass::newPlayer(&ev.self())); - } - IF_LISTENED_END(EVENT_TYPES::onPreJoin); - }); - break; - - case EVENT_TYPES::onLeft: - bus.emplaceListener([](PlayerLeaveEvent &ev) { - IF_LISTENED(EVENT_TYPES::onLeft) { - CallEvent(EVENT_TYPES::onLeft, PlayerClass::newPlayer(&ev.self())); - } - IF_LISTENED_END(EVENT_TYPES::onLeft); - }); - break; - - case EVENT_TYPES::onChat: - bus.emplaceListener([](PlayerChatEvent &ev) { - IF_LISTENED(EVENT_TYPES::onChat) { - CallEvent(EVENT_TYPES::onChat, PlayerClass::newPlayer(&ev.self()), - String::newString(ev.message())); - } - IF_LISTENED_END(EVENT_TYPES::onChat); - }); - - // case EVENT_TYPES::onChangeDim: - // Event::PlayerChangeDimEvent::subscribe([](const PlayerChangeDimEvent - // &ev) { - // IF_LISTENED(EVENT_TYPES::onChangeDim) { - // CallEvent(EVENT_TYPES::onChangeDim, - // PlayerClass::newPlayer(ev.mPlayer), - // Number::newNumber(ev.mToDimensionId)); //======??? - // } - // IF_LISTENED_END(EVENT_TYPES::onChangeDim); - // }); - // break; + using namespace ll::event; + EventBus& bus = EventBus::getInstance(); + switch ((EVENT_TYPES)eventId) { + case EVENT_TYPES::onJoin: + bus.emplaceListener([](PlayerJoinEvent& ev) { + IF_LISTENED(EVENT_TYPES::onJoin) { CallEvent(EVENT_TYPES::onJoin, PlayerClass::newPlayer(&ev.self())); } + IF_LISTENED_END(EVENT_TYPES::onJoin); + }); + break; - // case EVENT_TYPES::onPlayerSwing: - // Event::PlayerSwingEvent::subscribe([](const PlayerSwingEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onPlayerSwing) { - // CallEvent(EVENT_TYPES::onPlayerSwing, - // PlayerClass::newPlayer(ev.mPlayer)); - // } - // IF_LISTENED_END(EVENT_TYPES::onPlayerSwing); - // }); - // break; - - // case EVENT_TYPES::onAttackEntity: - // Event::PlayerAttackEvent::subscribe([](const PlayerAttackEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onAttackEntity) { - // if (ev.mTarget) { - // CallEvent(EVENT_TYPES::onAttackEntity, - // PlayerClass::newPlayer(ev.mPlayer), - // EntityClass::newEntity(ev.mTarget), - // Number::newNumber(ev.mAttackDamage)); - // } - // } - // IF_LISTENED_END(EVENT_TYPES::onAttackEntity); - // }); - // break; - - // case EVENT_TYPES::onAttackBlock: - // Event::PlayerAttackBlockEvent::subscribe( - // [](const PlayerAttackBlockEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onAttackBlock) { - // CallEvent( - // EVENT_TYPES::onAttackBlock, - // PlayerClass::newPlayer(ev.mPlayer), - // BlockClass::newBlock(ev.mBlockInstance), - // !ev.mItemStack->isNull() ? - // ItemClass::newItem(ev.mItemStack) - // : Local()); - // } - // IF_LISTENED_END(EVENT_TYPES::onAttackBlock); - // }); - // break; - - case EVENT_TYPES::onPlayerDie: - bus.emplaceListener( - [](ll::event::PlayerDieEvent &ev) { - IF_LISTENED(EVENT_TYPES::onPlayerDie) { - Actor *source = - ll::service::getLevel() - ->getDimension(ev.self().getDimensionId()) - ->fetchEntity(ev.source().getEntityUniqueID(), false); - CallEvent( - EVENT_TYPES::onPlayerDie, PlayerClass::newPlayer(&ev.self()), - (source ? EntityClass::newEntity(source) : Local())); - } - IF_LISTENED_END(EVENT_TYPES::onPlayerDie); + case EVENT_TYPES::onPreJoin: + bus.emplaceListener([](PlayerConnectEvent& ev) { + IF_LISTENED(EVENT_TYPES::onPreJoin) { + CallEvent(EVENT_TYPES::onPreJoin, PlayerClass::newPlayer(&ev.self())); + } + IF_LISTENED_END(EVENT_TYPES::onPreJoin); }); - break; - - case EVENT_TYPES::onRespawn: - bus.emplaceListener( - [](ll::event::PlayerRespawnEvent &ev) { - IF_LISTENED(EVENT_TYPES::onRespawn) { - CallEvent(EVENT_TYPES::onRespawn, - PlayerClass::newPlayer(&ev.self())); - } - IF_LISTENED_END(EVENT_TYPES::onRespawn) + break; + + case EVENT_TYPES::onLeft: + bus.emplaceListener([](PlayerLeaveEvent& ev) { + IF_LISTENED(EVENT_TYPES::onLeft) { CallEvent(EVENT_TYPES::onLeft, PlayerClass::newPlayer(&ev.self())); } + IF_LISTENED_END(EVENT_TYPES::onLeft); }); - break; - - // case EVENT_TYPES::onStartDestroyBlock: - // Event::PlayerStartDestroyBlockEvent::subscribe( - // [](const PlayerStartDestroyBlockEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onStartDestroyBlock) { - // CallEvent(EVENT_TYPES::onStartDestroyBlock, - // PlayerClass::newPlayer(ev.mPlayer), - // BlockClass::newBlock(ev.mBlockInstance)); - // } - // IF_LISTENED_END(EVENT_TYPES::onStartDestroyBlock); - // }); - // break; - - // case EVENT_TYPES::onDestroyBlock: - // Event::PlayerDestroyBlockEvent::subscribe( - // [](const PlayerDestroyBlockEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onDestroyBlock) { - // CallEvent(EVENT_TYPES::onDestroyBlock, - // PlayerClass::newPlayer(ev.mPlayer), - // BlockClass::newBlock(ev.mBlockInstance)); - // } - // IF_LISTENED_END(EVENT_TYPES::onDestroyBlock); - // }); - // break; - - // case EVENT_TYPES::onPlaceBlock: - // Event::PlayerPlaceBlockEvent::subscribe( - // [](const PlayerPlaceBlockEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onPlaceBlock) { - // CallEvent(EVENT_TYPES::onPlaceBlock, - // PlayerClass::newPlayer(ev.mPlayer), - // BlockClass::newBlock(ev.mBlockInstance)); - // } - // IF_LISTENED_END(EVENT_TYPES::onPlaceBlock); - // }); - // break; - - // case EVENT_TYPES::afterPlaceBlock: - // Event::BlockPlacedByPlayerEvent::subscribe( - // [](const BlockPlacedByPlayerEvent &ev) { - // IF_LISTENED(EVENT_TYPES::afterPlaceBlock) { - // CallEvent(EVENT_TYPES::afterPlaceBlock, - // PlayerClass::newPlayer(ev.mPlayer), - // BlockClass::newBlock(ev.mBlockInstance)); - // } - // IF_LISTENED_END(EVENT_TYPES::afterPlaceBlock); - // }); - // break; - - /*case EVENT_TYPES::onMove: - Event::PlayerMoveEvent::subscribe([](const PlayerMoveEvent& ev) { - IF_LISTENED(EVENT_TYPES::onMove) { - CallEvent(EVENT_TYPES::onMove, - PlayerClass::newPlayer(ev.mPlayer), FloatPos::newPos(ev.mPos, - ev.mPlayer->getDimensionId())); + break; + + case EVENT_TYPES::onChat: + bus.emplaceListener([](PlayerChatEvent& ev) { + IF_LISTENED(EVENT_TYPES::onChat) { + CallEvent(EVENT_TYPES::onChat, PlayerClass::newPlayer(&ev.self()), String::newString(ev.message())); } - IF_LISTENED_END(EVENT_TYPES::onMove); + IF_LISTENED_END(EVENT_TYPES::onChat); }); - break;*/ - - // case EVENT_TYPES::onJump: - // Event::PlayerJumpEvent::subscribe([](const PlayerJumpEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onJump) { - // CallEvent(EVENT_TYPES::onJump, PlayerClass::newPlayer(ev.mPlayer)); - // } - // IF_LISTENED_END(EVENT_TYPES::onJump); - // }); - // break; - - // case EVENT_TYPES::onDropItem: - // Event::PlayerDropItemEvent::subscribe([](const PlayerDropItemEvent &ev) - // { - // IF_LISTENED(EVENT_TYPES::onDropItem) { - // CallEvent( - // EVENT_TYPES::onDropItem, PlayerClass::newPlayer(ev.mPlayer), - // ItemClass::newItem(ev.mItemStack)); // ###### Q lost items - // ###### - // } - // IF_LISTENED_END(EVENT_TYPES::onDropItem); - // }); - // break; - - // case EVENT_TYPES::onTakeItem: - // Event::PlayerPickupItemEvent::subscribe( - // [](const PlayerPickupItemEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onTakeItem) { - // CallEvent(EVENT_TYPES::onTakeItem, - // PlayerClass::newPlayer(ev.mPlayer), - // EntityClass::newEntity(ev.mItemEntity), - // ev.mItemStack ? ItemClass::newItem(ev.mItemStack) - // : Local()); - // } - // IF_LISTENED_END(EVENT_TYPES::onTakeItem); - // }); - // break; - - // case EVENT_TYPES::onOpenContainer: - // Event::PlayerOpenContainerEvent::subscribe( - // [](const PlayerOpenContainerEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onOpenContainer) { - // CallEvent(EVENT_TYPES::onOpenContainer, - // PlayerClass::newPlayer(ev.mPlayer), - // BlockClass::newBlock(ev.mBlockInstance)); - // } - // IF_LISTENED_END(EVENT_TYPES::onOpenContainer); - // }); - // break; - - // case EVENT_TYPES::onCloseContainer: - // Event::PlayerCloseContainerEvent::subscribe( - // [](const PlayerCloseContainerEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onCloseContainer) { - // CallEvent(EVENT_TYPES::onCloseContainer, - // PlayerClass::newPlayer(ev.mPlayer), - // BlockClass::newBlock(ev.mBlockInstance)); - // } - // IF_LISTENED_END(EVENT_TYPES::onCloseContainer); - // }); - // break; - - // case EVENT_TYPES::onInventoryChange: - // Event::PlayerInventoryChangeEvent::subscribe( - // [](const PlayerInventoryChangeEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onInventoryChange) { - // CallEvent(EVENT_TYPES::onInventoryChange, - // PlayerClass::newPlayer(ev.mPlayer), ev.mSlot, - // ItemClass::newItem(ev.mPreviousItemStack), - // ItemClass::newItem(ev.mNewItemStack)); - // } - // IF_LISTENED_END(EVENT_TYPES::onInventoryChange); - // }); - // break; - - // case EVENT_TYPES::onUseItem: - // Event::PlayerUseItemEvent::subscribe([](const PlayerUseItemEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onUseItem) { - // CallEvent(EVENT_TYPES::onUseItem, - // PlayerClass::newPlayer((Player *)ev.mPlayer), - // ItemClass::newItem(ev.mItemStack)); - // } - // IF_LISTENED_END(EVENT_TYPES::onUseItem); - // }); - // break; - - // case EVENT_TYPES::onUseItemOn: - // Event::PlayerUseItemOnEvent::subscribe([](const PlayerUseItemOnEvent - // &ev) { - // IF_LISTENED(EVENT_TYPES::onUseItemOn) { - // CallEvent(EVENT_TYPES::onUseItemOn, - // PlayerClass::newPlayer((Player *)ev.mPlayer), - // ItemClass::newItem(ev.mItemStack), - // BlockClass::newBlock(ev.mBlockInstance), - // Number::newNumber(ev.mFace), - // FloatPos::newPos(ev.mClickPos, - // ev.mPlayer->getDimensionId())); - // } - // IF_LISTENED_END(EVENT_TYPES::onUseItemOn); - // }); - // break; - - // case EVENT_TYPES::onUseBucketPlace: - // case EVENT_TYPES::onUseBucketTake: - // Event::PlayerUseBucketEvent::subscribe([](const PlayerUseBucketEvent - // &ev) { - // if (ev.mEventType == PlayerUseBucketEvent::EventType::Place) { - // IF_LISTENED(EVENT_TYPES::onUseBucketPlace) { - // CallEvent( - // EVENT_TYPES::onUseBucketPlace, - // PlayerClass::newPlayer((Player *)ev.mPlayer), - // ItemClass::newItem(ev.mBucket), - // BlockClass::newBlock(ev.mBlockInstance), - // Number::newNumber(ev.mFace), - // FloatPos::newPos(ev.mTargetPos, - // ev.mPlayer->getDimensionId())); - // } - // IF_LISTENED_END(EVENT_TYPES::onUseBucketPlace); - // } else if (ev.mEventType == PlayerUseBucketEvent::EventType::Take) { - // IF_LISTENED(EVENT_TYPES::onUseBucketTake) { - // if (ev.mTargetActor) { - // CallEvent( - // EVENT_TYPES::onUseBucketTake, - // PlayerClass::newPlayer((Player *)ev.mPlayer), - // ItemClass::newItem(ev.mBucket), - // EntityClass::newEntity(ev.mTargetActor), - // Number::newNumber(ev.mFace), - // FloatPos::newPos(ev.mTargetPos, - // ev.mPlayer->getDimensionId())); - // } else { - // CallEvent( - // EVENT_TYPES::onUseBucketTake, - // PlayerClass::newPlayer((Player *)ev.mPlayer), - // ItemClass::newItem(ev.mBucket), - // BlockClass::newBlock(ev.mBlockInstance), - // Number::newNumber(ev.mFace), - // FloatPos::newPos(ev.mTargetPos, - // ev.mPlayer->getDimensionId())); - // } - // } - // IF_LISTENED_END(EVENT_TYPES::onUseBucketTake); - // } - // return true; - // }); - // break; - - // case EVENT_TYPES::onContainerChange: - // Event::ContainerChangeEvent::subscribe([](const ContainerChangeEvent - // &ev) { - // IF_LISTENED(EVENT_TYPES::onContainerChange) { - // CallEvent(EVENT_TYPES::onContainerChange, - // PlayerClass::newPlayer(ev.mPlayer), - // BlockClass::newBlock(ev.mBlockInstance), - // Number::newNumber(ev.mSlot), - // ItemClass::newItem(ev.mPreviousItemStack), - // ItemClass::newItem(ev.mNewItemStack)); - // } - // IF_LISTENED_END(EVENT_TYPES::onContainerChange); - // }); - // break; - - // case EVENT_TYPES::onChangeArmorStand: - // Event::ArmorStandChangeEvent::subscribe( - // [](const ArmorStandChangeEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onChangeArmorStand) { - // CallEvent(EVENT_TYPES::onChangeArmorStand, - // EntityClass::newEntity((Actor *)ev.mArmorStand), - // PlayerClass::newPlayer(ev.mPlayer), - // Number::newNumber(ev.mSlot)); - // } - // IF_LISTENED_END(EVENT_TYPES::onChangeArmorStand); - // }); - // break; - - // case EVENT_TYPES::onChangeSprinting: - // Event::PlayerSprintEvent::subscribe([](const PlayerSprintEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onChangeSprinting) { - // CallEvent(EVENT_TYPES::onChangeSprinting, - // PlayerClass::newPlayer(ev.mPlayer), - // Boolean::newBoolean(ev.mIsSprinting)); - // } - // IF_LISTENED_END(EVENT_TYPES::onChangeSprinting); - // }); - // break; - // case EVENT_TYPES::onSneak: - // Event::PlayerSneakEvent::subscribe([](const PlayerSneakEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onSneak) { - // CallEvent(EVENT_TYPES::onSneak, PlayerClass::newPlayer(ev.mPlayer), - // Boolean::newBoolean(ev.mIsSneaking)); - // } - // IF_LISTENED_END(EVENT_TYPES::onSneak); - // }); - // break; - - // case EVENT_TYPES::onOpenContainerScreen: - // Event::PlayerOpenContainerScreenEvent::subscribe( - // [](const PlayerOpenContainerScreenEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onOpenContainerScreen) { - // CallEvent(EVENT_TYPES::onOpenContainerScreen, - // PlayerClass::newPlayer(ev.mPlayer)); - // } - // IF_LISTENED_END(EVENT_TYPES::onOpenContainerScreen); - // }); - // break; - - // case EVENT_TYPES::onSetArmor: - // Event::PlayerSetArmorEvent::subscribe([](const PlayerSetArmorEvent &ev) - // { - // IF_LISTENED(EVENT_TYPES::onSetArmor) { - // CallEvent(EVENT_TYPES::onSetArmor, - // PlayerClass::newPlayer(ev.mPlayer), - // Number::newNumber(ev.mSlot), - // ItemClass::newItem(ev.mArmorItem)); - // } - // IF_LISTENED_END(EVENT_TYPES::onSetArmor); - // }); - // break; + // case EVENT_TYPES::onChangeDim: + // Event::PlayerChangeDimEvent::subscribe([](const PlayerChangeDimEvent + // &ev) { + // IF_LISTENED(EVENT_TYPES::onChangeDim) { + // CallEvent(EVENT_TYPES::onChangeDim, + // PlayerClass::newPlayer(ev.mPlayer), + // Number::newNumber(ev.mToDimensionId)); //======??? + // } + // IF_LISTENED_END(EVENT_TYPES::onChangeDim); + // }); + // break; + + // case EVENT_TYPES::onPlayerSwing: + // Event::PlayerSwingEvent::subscribe([](const PlayerSwingEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onPlayerSwing) { + // CallEvent(EVENT_TYPES::onPlayerSwing, + // PlayerClass::newPlayer(ev.mPlayer)); + // } + // IF_LISTENED_END(EVENT_TYPES::onPlayerSwing); + // }); + // break; + + // case EVENT_TYPES::onAttackEntity: + // Event::PlayerAttackEvent::subscribe([](const PlayerAttackEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onAttackEntity) { + // if (ev.mTarget) { + // CallEvent(EVENT_TYPES::onAttackEntity, + // PlayerClass::newPlayer(ev.mPlayer), + // EntityClass::newEntity(ev.mTarget), + // Number::newNumber(ev.mAttackDamage)); + // } + // } + // IF_LISTENED_END(EVENT_TYPES::onAttackEntity); + // }); + // break; + + // case EVENT_TYPES::onAttackBlock: + // Event::PlayerAttackBlockEvent::subscribe( + // [](const PlayerAttackBlockEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onAttackBlock) { + // CallEvent( + // EVENT_TYPES::onAttackBlock, + // PlayerClass::newPlayer(ev.mPlayer), + // BlockClass::newBlock(ev.mBlockInstance), + // !ev.mItemStack->isNull() ? + // ItemClass::newItem(ev.mItemStack) + // : Local()); + // } + // IF_LISTENED_END(EVENT_TYPES::onAttackBlock); + // }); + // break; + + case EVENT_TYPES::onPlayerDie: + bus.emplaceListener([](ll::event::PlayerDieEvent& ev) { + IF_LISTENED(EVENT_TYPES::onPlayerDie) { + Actor* source = ll::service::getLevel() + ->getDimension(ev.self().getDimensionId()) + ->fetchEntity(ev.source().getEntityUniqueID(), false); + CallEvent( + EVENT_TYPES::onPlayerDie, + PlayerClass::newPlayer(&ev.self()), + (source ? EntityClass::newEntity(source) : Local()) + ); + } + IF_LISTENED_END(EVENT_TYPES::onPlayerDie); + }); + break; - // case EVENT_TYPES::onEat: - // Event::PlayerEatEvent::subscribe([](const PlayerEatEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onEat) { - // CallEvent(EVENT_TYPES::onEat, PlayerClass::newPlayer(ev.mPlayer), - // ItemClass::newItem(ev.mFoodItem)); - // } - // IF_LISTENED_END(EVENT_TYPES::onEat); - // }); - // break; + case EVENT_TYPES::onRespawn: + bus.emplaceListener([](ll::event::PlayerRespawnEvent& ev) { + IF_LISTENED(EVENT_TYPES::onRespawn) { + CallEvent(EVENT_TYPES::onRespawn, PlayerClass::newPlayer(&ev.self())); + } + IF_LISTENED_END(EVENT_TYPES::onRespawn) + }); + break; + + // case EVENT_TYPES::onStartDestroyBlock: + // Event::PlayerStartDestroyBlockEvent::subscribe( + // [](const PlayerStartDestroyBlockEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onStartDestroyBlock) { + // CallEvent(EVENT_TYPES::onStartDestroyBlock, + // PlayerClass::newPlayer(ev.mPlayer), + // BlockClass::newBlock(ev.mBlockInstance)); + // } + // IF_LISTENED_END(EVENT_TYPES::onStartDestroyBlock); + // }); + // break; + + // case EVENT_TYPES::onDestroyBlock: + // Event::PlayerDestroyBlockEvent::subscribe( + // [](const PlayerDestroyBlockEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onDestroyBlock) { + // CallEvent(EVENT_TYPES::onDestroyBlock, + // PlayerClass::newPlayer(ev.mPlayer), + // BlockClass::newBlock(ev.mBlockInstance)); + // } + // IF_LISTENED_END(EVENT_TYPES::onDestroyBlock); + // }); + // break; + + // case EVENT_TYPES::onPlaceBlock: + // Event::PlayerPlaceBlockEvent::subscribe( + // [](const PlayerPlaceBlockEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onPlaceBlock) { + // CallEvent(EVENT_TYPES::onPlaceBlock, + // PlayerClass::newPlayer(ev.mPlayer), + // BlockClass::newBlock(ev.mBlockInstance)); + // } + // IF_LISTENED_END(EVENT_TYPES::onPlaceBlock); + // }); + // break; + + // case EVENT_TYPES::afterPlaceBlock: + // Event::BlockPlacedByPlayerEvent::subscribe( + // [](const BlockPlacedByPlayerEvent &ev) { + // IF_LISTENED(EVENT_TYPES::afterPlaceBlock) { + // CallEvent(EVENT_TYPES::afterPlaceBlock, + // PlayerClass::newPlayer(ev.mPlayer), + // BlockClass::newBlock(ev.mBlockInstance)); + // } + // IF_LISTENED_END(EVENT_TYPES::afterPlaceBlock); + // }); + // break; + + /*case EVENT_TYPES::onMove: + Event::PlayerMoveEvent::subscribe([](const PlayerMoveEvent& ev) { + IF_LISTENED(EVENT_TYPES::onMove) { + CallEvent(EVENT_TYPES::onMove, + PlayerClass::newPlayer(ev.mPlayer), FloatPos::newPos(ev.mPos, + ev.mPlayer->getDimensionId())); + } + IF_LISTENED_END(EVENT_TYPES::onMove); + }); + break;*/ + + // case EVENT_TYPES::onJump: + // Event::PlayerJumpEvent::subscribe([](const PlayerJumpEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onJump) { + // CallEvent(EVENT_TYPES::onJump, PlayerClass::newPlayer(ev.mPlayer)); + // } + // IF_LISTENED_END(EVENT_TYPES::onJump); + // }); + // break; + + // case EVENT_TYPES::onDropItem: + // Event::PlayerDropItemEvent::subscribe([](const PlayerDropItemEvent &ev) + // { + // IF_LISTENED(EVENT_TYPES::onDropItem) { + // CallEvent( + // EVENT_TYPES::onDropItem, PlayerClass::newPlayer(ev.mPlayer), + // ItemClass::newItem(ev.mItemStack)); // ###### Q lost items + // ###### + // } + // IF_LISTENED_END(EVENT_TYPES::onDropItem); + // }); + // break; + + // case EVENT_TYPES::onTakeItem: + // Event::PlayerPickupItemEvent::subscribe( + // [](const PlayerPickupItemEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onTakeItem) { + // CallEvent(EVENT_TYPES::onTakeItem, + // PlayerClass::newPlayer(ev.mPlayer), + // EntityClass::newEntity(ev.mItemEntity), + // ev.mItemStack ? ItemClass::newItem(ev.mItemStack) + // : Local()); + // } + // IF_LISTENED_END(EVENT_TYPES::onTakeItem); + // }); + // break; + + // case EVENT_TYPES::onOpenContainer: + // Event::PlayerOpenContainerEvent::subscribe( + // [](const PlayerOpenContainerEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onOpenContainer) { + // CallEvent(EVENT_TYPES::onOpenContainer, + // PlayerClass::newPlayer(ev.mPlayer), + // BlockClass::newBlock(ev.mBlockInstance)); + // } + // IF_LISTENED_END(EVENT_TYPES::onOpenContainer); + // }); + // break; + + // case EVENT_TYPES::onCloseContainer: + // Event::PlayerCloseContainerEvent::subscribe( + // [](const PlayerCloseContainerEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onCloseContainer) { + // CallEvent(EVENT_TYPES::onCloseContainer, + // PlayerClass::newPlayer(ev.mPlayer), + // BlockClass::newBlock(ev.mBlockInstance)); + // } + // IF_LISTENED_END(EVENT_TYPES::onCloseContainer); + // }); + // break; + + // case EVENT_TYPES::onInventoryChange: + // Event::PlayerInventoryChangeEvent::subscribe( + // [](const PlayerInventoryChangeEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onInventoryChange) { + // CallEvent(EVENT_TYPES::onInventoryChange, + // PlayerClass::newPlayer(ev.mPlayer), ev.mSlot, + // ItemClass::newItem(ev.mPreviousItemStack), + // ItemClass::newItem(ev.mNewItemStack)); + // } + // IF_LISTENED_END(EVENT_TYPES::onInventoryChange); + // }); + // break; + + // case EVENT_TYPES::onUseItem: + // Event::PlayerUseItemEvent::subscribe([](const PlayerUseItemEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onUseItem) { + // CallEvent(EVENT_TYPES::onUseItem, + // PlayerClass::newPlayer((Player *)ev.mPlayer), + // ItemClass::newItem(ev.mItemStack)); + // } + // IF_LISTENED_END(EVENT_TYPES::onUseItem); + // }); + // break; + + // case EVENT_TYPES::onUseItemOn: + // Event::PlayerUseItemOnEvent::subscribe([](const PlayerUseItemOnEvent + // &ev) { + // IF_LISTENED(EVENT_TYPES::onUseItemOn) { + // CallEvent(EVENT_TYPES::onUseItemOn, + // PlayerClass::newPlayer((Player *)ev.mPlayer), + // ItemClass::newItem(ev.mItemStack), + // BlockClass::newBlock(ev.mBlockInstance), + // Number::newNumber(ev.mFace), + // FloatPos::newPos(ev.mClickPos, + // ev.mPlayer->getDimensionId())); + // } + // IF_LISTENED_END(EVENT_TYPES::onUseItemOn); + // }); + // break; + + // case EVENT_TYPES::onUseBucketPlace: + // case EVENT_TYPES::onUseBucketTake: + // Event::PlayerUseBucketEvent::subscribe([](const PlayerUseBucketEvent + // &ev) { + // if (ev.mEventType == PlayerUseBucketEvent::EventType::Place) { + // IF_LISTENED(EVENT_TYPES::onUseBucketPlace) { + // CallEvent( + // EVENT_TYPES::onUseBucketPlace, + // PlayerClass::newPlayer((Player *)ev.mPlayer), + // ItemClass::newItem(ev.mBucket), + // BlockClass::newBlock(ev.mBlockInstance), + // Number::newNumber(ev.mFace), + // FloatPos::newPos(ev.mTargetPos, + // ev.mPlayer->getDimensionId())); + // } + // IF_LISTENED_END(EVENT_TYPES::onUseBucketPlace); + // } else if (ev.mEventType == PlayerUseBucketEvent::EventType::Take) { + // IF_LISTENED(EVENT_TYPES::onUseBucketTake) { + // if (ev.mTargetActor) { + // CallEvent( + // EVENT_TYPES::onUseBucketTake, + // PlayerClass::newPlayer((Player *)ev.mPlayer), + // ItemClass::newItem(ev.mBucket), + // EntityClass::newEntity(ev.mTargetActor), + // Number::newNumber(ev.mFace), + // FloatPos::newPos(ev.mTargetPos, + // ev.mPlayer->getDimensionId())); + // } else { + // CallEvent( + // EVENT_TYPES::onUseBucketTake, + // PlayerClass::newPlayer((Player *)ev.mPlayer), + // ItemClass::newItem(ev.mBucket), + // BlockClass::newBlock(ev.mBlockInstance), + // Number::newNumber(ev.mFace), + // FloatPos::newPos(ev.mTargetPos, + // ev.mPlayer->getDimensionId())); + // } + // } + // IF_LISTENED_END(EVENT_TYPES::onUseBucketTake); + // } + // return true; + // }); + // break; + + // case EVENT_TYPES::onContainerChange: + // Event::ContainerChangeEvent::subscribe([](const ContainerChangeEvent + // &ev) { + // IF_LISTENED(EVENT_TYPES::onContainerChange) { + // CallEvent(EVENT_TYPES::onContainerChange, + // PlayerClass::newPlayer(ev.mPlayer), + // BlockClass::newBlock(ev.mBlockInstance), + // Number::newNumber(ev.mSlot), + // ItemClass::newItem(ev.mPreviousItemStack), + // ItemClass::newItem(ev.mNewItemStack)); + // } + // IF_LISTENED_END(EVENT_TYPES::onContainerChange); + // }); + // break; + + // case EVENT_TYPES::onChangeArmorStand: + // Event::ArmorStandChangeEvent::subscribe( + // [](const ArmorStandChangeEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onChangeArmorStand) { + // CallEvent(EVENT_TYPES::onChangeArmorStand, + // EntityClass::newEntity((Actor *)ev.mArmorStand), + // PlayerClass::newPlayer(ev.mPlayer), + // Number::newNumber(ev.mSlot)); + // } + // IF_LISTENED_END(EVENT_TYPES::onChangeArmorStand); + // }); + // break; + + // case EVENT_TYPES::onChangeSprinting: + // Event::PlayerSprintEvent::subscribe([](const PlayerSprintEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onChangeSprinting) { + // CallEvent(EVENT_TYPES::onChangeSprinting, + // PlayerClass::newPlayer(ev.mPlayer), + // Boolean::newBoolean(ev.mIsSprinting)); + // } + // IF_LISTENED_END(EVENT_TYPES::onChangeSprinting); + // }); + // break; + + // case EVENT_TYPES::onSneak: + // Event::PlayerSneakEvent::subscribe([](const PlayerSneakEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onSneak) { + // CallEvent(EVENT_TYPES::onSneak, PlayerClass::newPlayer(ev.mPlayer), + // Boolean::newBoolean(ev.mIsSneaking)); + // } + // IF_LISTENED_END(EVENT_TYPES::onSneak); + // }); + // break; + + // case EVENT_TYPES::onOpenContainerScreen: + // Event::PlayerOpenContainerScreenEvent::subscribe( + // [](const PlayerOpenContainerScreenEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onOpenContainerScreen) { + // CallEvent(EVENT_TYPES::onOpenContainerScreen, + // PlayerClass::newPlayer(ev.mPlayer)); + // } + // IF_LISTENED_END(EVENT_TYPES::onOpenContainerScreen); + // }); + // break; + + // case EVENT_TYPES::onSetArmor: + // Event::PlayerSetArmorEvent::subscribe([](const PlayerSetArmorEvent &ev) + // { + // IF_LISTENED(EVENT_TYPES::onSetArmor) { + // CallEvent(EVENT_TYPES::onSetArmor, + // PlayerClass::newPlayer(ev.mPlayer), + // Number::newNumber(ev.mSlot), + // ItemClass::newItem(ev.mArmorItem)); + // } + // IF_LISTENED_END(EVENT_TYPES::onSetArmor); + // }); + // break; + + // case EVENT_TYPES::onEat: + // Event::PlayerEatEvent::subscribe([](const PlayerEatEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onEat) { + // CallEvent(EVENT_TYPES::onEat, PlayerClass::newPlayer(ev.mPlayer), + // ItemClass::newItem(ev.mFoodItem)); + // } + // IF_LISTENED_END(EVENT_TYPES::onEat); + // }); + // break; + + // case EVENT_TYPES::onAte: + // Event::PlayerAteEvent::subscribe([](const PlayerAteEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onAte) { + // CallEvent(EVENT_TYPES::onAte, PlayerClass::newPlayer(ev.mPlayer), + // ItemClass::newItem(ev.mFoodItem)); + // } + // IF_LISTENED_END(EVENT_TYPES::onAte); + // }); + // break; + + // case EVENT_TYPES::onConsumeTotem: + // Event::PlayerConsumeTotemEvent::subscribe( + // [](const PlayerConsumeTotemEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onConsumeTotem) { + // CallEvent(EVENT_TYPES::onConsumeTotem, + // PlayerClass::newPlayer(ev.mPlayer)); + // } + // IF_LISTENED_END(EVENT_TYPES::onConsumeTotem); + // }); + // break; + + // case EVENT_TYPES::onEffectAdded: + // case EVENT_TYPES::onEffectRemoved: + // case EVENT_TYPES::onEffectUpdated: + // Event::PlayerEffectChangedEvent::subscribe([](const + // PlayerEffectChangedEvent + // &ev) { + // if (ev.mEventType == PlayerEffectChangedEvent::EventType::Add) { + // IF_LISTENED(EVENT_TYPES::onEffectAdded) { + // CallEvent( + // EVENT_TYPES::onEffectAdded, + // PlayerClass::newPlayer(ev.mPlayer), + // String::newString(ev.mEffect->getComponentName().getString()), + // Number::newNumber(ev.mEffect->getAmplifier()), + // Number::newNumber(ev.mEffect->getDuration())); + // } + // IF_LISTENED_END(EVENT_TYPES::onEffectAdded); + // } else if (ev.mEventType == + // PlayerEffectChangedEvent::EventType::Remove) { + // IF_LISTENED(EVENT_TYPES::onEffectRemoved) { + // CallEvent( + // EVENT_TYPES::onEffectRemoved, + // PlayerClass::newPlayer(ev.mPlayer), + // String::newString(ev.mEffect->getComponentName().getString())); + // } + // IF_LISTENED_END(EVENT_TYPES::onEffectRemoved); + // } else if (ev.mEventType == + // PlayerEffectChangedEvent::EventType::Update) { + // IF_LISTENED(EVENT_TYPES::onEffectUpdated) { + // CallEvent( + // EVENT_TYPES::onEffectUpdated, + // PlayerClass::newPlayer(ev.mPlayer), + // String::newString(ev.mEffect->getComponentName().getString()), + // Number::newNumber(ev.mEffect->getAmplifier()), + // Number::newNumber(ev.mEffect->getDuration())); + // } + // IF_LISTENED_END(EVENT_TYPES::onEffectUpdated); + // } + // return true; + // }); + // break; + + // case EVENT_TYPES::onUseRespawnAnchor: + // Event::PlayerUseRespawnAnchorEvent::subscribe( + // [](const PlayerUseRespawnAnchorEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onUseRespawnAnchor) { + // BlockInstance bl(ev.mBlockInstance); + // CallEvent(EVENT_TYPES::onUseRespawnAnchor, + // PlayerClass::newPlayer(ev.mPlayer), + // IntPos::newPos(bl.getPosition(), + // bl.getDimensionId())); + // } + // IF_LISTENED_END(EVENT_TYPES::onUseRespawnAnchor); + // }); + // break; + + // case EVENT_TYPES::onRide: + // Event::EntityRideEvent::subscribe([](const EntityRideEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onRide) { + // CallEvent(EVENT_TYPES::onRide, EntityClass::newEntity(ev.mRider), + // EntityClass::newEntity(ev.mVehicle)); + // } + // IF_LISTENED_END(EVENT_TYPES::onRide); + // }); + // break; + + // case EVENT_TYPES::onEntityExplode: + // Event::EntityExplodeEvent::subscribe([](const EntityExplodeEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onEntityExplode) { + // CallEvent( + // EVENT_TYPES::onEntityExplode, + // ev.mActor ? EntityClass::newEntity(ev.mActor) : Local(), + // FloatPos::newPos(ev.mPos, ev.mDimension->getDimensionId()), + // Number::newNumber(ev.mRadius), + // Number::newNumber(ev.mMaxResistance), + // Boolean::newBoolean(ev.mBreaking), + // Boolean::newBoolean(ev.mFire)); + // } + // IF_LISTENED_END(EVENT_TYPES::onEntityExplode); + // }); + // break; + + // case EVENT_TYPES::onBlockExplode: + // Event::BlockExplodeEvent::subscribe([](const BlockExplodeEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onBlockExplode) { + // BlockInstance bl(ev.mBlockInstance); + // CallEvent( + // EVENT_TYPES::onBlockExplode, BlockClass::newBlock(bl), + // IntPos::newPos(bl.getPosition(), bl.getDimensionId()), + // Number::newNumber(ev.mRadius), + // Number::newNumber(ev.mMaxResistance), + // Boolean::newBoolean(ev.mBreaking), + // Boolean::newBoolean(ev.mFire)); + // } + // IF_LISTENED_END(EVENT_TYPES::onBlockExplode); + // }); + // break; + + // case EVENT_TYPES::onRespawnAnchorExplode: + // Event::BlockExplodeEvent::subscribe([](const BlockExplodeEvent &ev) { + // BlockInstance bl(ev.mBlockInstance); + // if (bl.getBlock()->getName() == "minecraft:respawn_anchor") { + // IF_LISTENED(EVENT_TYPES::onRespawnAnchorExplode) { + // CallEvent(EVENT_TYPES::onRespawnAnchorExplode, + // IntPos::newPos(bl.getPosition(), bl.getDimensionId()), + // Local()); + // } + // IF_LISTENED_END(EVENT_TYPES::onRespawnAnchorExplode); + // } + // return true; + // }); + // break; + + // case EVENT_TYPES::onBlockExploded: + // Event::BlockExplodedEvent::subscribe([](const BlockExplodedEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onBlockExploded) { + // CallEvent(EVENT_TYPES::onBlockExploded, + // BlockClass::newBlock(ev.mBlockInstance), + // EntityClass::newEntity(ev.mExplodeSource)); + // } + // IF_LISTENED_END(EVENT_TYPES::onBlockExploded); + // }); + // break; + + // case EVENT_TYPES::onCmdBlockExecute: + // Event::CmdBlockExecuteEvent::subscribe([](const CmdBlockExecuteEvent + // &ev) { + // IF_LISTENED(EVENT_TYPES::onCmdBlockExecute) { + // if (ev.mIsMinecart) { + // CallEvent(EVENT_TYPES::onCmdBlockExecute, + // String::newString(ev.mCommand), + // FloatPos::newPos(ev.mMinecart->getPosition(), + // ev.mMinecart->getDimensionId()), + // Boolean::newBoolean(ev.mIsMinecart)); + // } else { + // BlockInstance bl = ev.mBlockInstance; + // CallEvent( + // EVENT_TYPES::onCmdBlockExecute, + // String::newString(ev.mCommand), + // FloatPos::newPos(bl.getPosition().toVec3(), + // bl.getDimensionId()), Boolean::newBoolean(ev.mIsMinecart)); + // } + // } + // IF_LISTENED_END(EVENT_TYPES::onCmdBlockExecute); + // }); + // break; + + // case EVENT_TYPES::onRedStoneUpdate: + // Event::RedStoneUpdateEvent::subscribe([](const RedStoneUpdateEvent &ev) + // { + // IF_LISTENED(EVENT_TYPES::onRedStoneUpdate) { + // CallEvent(EVENT_TYPES::onRedStoneUpdate, + // BlockClass::newBlock(ev.mBlockInstance), + // Number::newNumber(ev.mRedStonePower), + // Boolean::newBoolean(ev.mIsActivated)); + // } + // IF_LISTENED_END(EVENT_TYPES::onRedStoneUpdate); + // }); + // break; + + // case EVENT_TYPES::onWitherBossDestroy: + // Event::WitherBossDestroyEvent::subscribe( + // [](const WitherBossDestroyEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onWitherBossDestroy) { + // AABB range = ev.mDestroyRange; + // int dimId = ((Actor *)ev.mWitherBoss)->getDimensionId(); + // CallEvent(EVENT_TYPES::onWitherBossDestroy, + // EntityClass::newEntity((Actor *)ev.mWitherBoss), + // IntPos::newPos(range.min.toBlockPos(), dimId), + // IntPos::newPos(range.max.toBlockPos(), dimId)); + // } + // IF_LISTENED_END(EVENT_TYPES::onWitherBossDestroy); + // }); + // break; + + // case EVENT_TYPES::onMobHurt: + // Event::MobHurtEvent::subscribe([](const MobHurtEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onMobHurt) { + // Actor *source = nullptr; + // if (ev.mDamageSource->isEntitySource()) { + // if (ev.mDamageSource->isChildEntitySource()) + // source = + // Level::getEntity(ev.mDamageSource->getEntityUniqueID()); + // else + // source = + // Level::getEntity(ev.mDamageSource->getDamagingEntityUniqueID()); + // } + + // CallEvent(EVENT_TYPES::onMobHurt, EntityClass::newEntity(ev.mMob), + // source ? EntityClass::newEntity(source) : Local(), + // Number::newNumber(float(ev.mDamage)), + // Number::newNumber((int)ev.mDamageSource->getCause())); + // } + // IF_LISTENED_END(EVENT_TYPES::onMobHurt) + // }); + // break; + + // case EVENT_TYPES::onStepOnPressurePlate: + // Event::EntityStepOnPressurePlateEvent::subscribe( + // [](const EntityStepOnPressurePlateEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onStepOnPressurePlate) { + // CallEvent(EVENT_TYPES::onStepOnPressurePlate, + // EntityClass::newEntity(ev.mActor), + // BlockClass::newBlock(ev.mBlockInstance)); + // } + // IF_LISTENED_END(EVENT_TYPES::onStepOnPressurePlate); + // }); + // break; + + // case EVENT_TYPES::onMobDie: + // Event::MobDieEvent::subscribe([](const MobDieEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onMobDie) { + // Actor *source = nullptr; + // if (ev.mDamageSource->isEntitySource()) { + // source = + // Level::getEntity(ev.mDamageSource->getDamagingEntityUniqueID()); + // if (ev.mDamageSource->isChildEntitySource()) + // source = source->getOwner(); + // } + + // CallEvent(EVENT_TYPES::onMobDie, + // EntityClass::newEntity((Actor *)ev.mMob), + // (source ? EntityClass::newEntity(source) : + // Local()), + // Number::newNumber((int)ev.mDamageSource->getCause())); + // } + // IF_LISTENED_END(EVENT_TYPES::onMobDie); + // }); + // break; + + // case EVENT_TYPES::onSpawnProjectile: + // Event::ProjectileSpawnEvent::subscribe([](const ProjectileSpawnEvent + // &ev) { + // IF_LISTENED(EVENT_TYPES::onSpawnProjectile) { + // CallEvent(EVENT_TYPES::onSpawnProjectile, + // EntityClass::newEntity(ev.mShooter), + // String::newString(ev.mType)); + // } + // IF_LISTENED_END(EVENT_TYPES::onSpawnProjectile); + // }); + // break; + + // case EVENT_TYPES::onProjectileCreated: + // Event::ProjectileCreatedEvent::subscribe( + // [](const ProjectileCreatedEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onProjectileCreated) { + // CallEvent(EVENT_TYPES::onProjectileCreated, + // EntityClass::newEntity(ev.mShooter), + // EntityClass::newEntity(ev.mProjectile)); + // } + // IF_LISTENED_END(EVENT_TYPES::onProjectileCreated); + // }); + // break; + + // case EVENT_TYPES::onProjectileHitEntity: + // Event::ProjectileHitEntityEvent::subscribe( + // [](const ProjectileHitEntityEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onProjectileHitEntity) { + // CallEvent(EVENT_TYPES::onProjectileHitEntity, + // EntityClass::newEntity(ev.mTarget), + // EntityClass::newEntity(ev.mSource)); + // } + // IF_LISTENED_END(EVENT_TYPES::onProjectileHitEntity); + // }); + // break; + + // case EVENT_TYPES::onEntityTransformation: + // Event::EntityTransformEvent::subscribe([](const EntityTransformEvent + // &ev) { + // IF_LISTENED(EVENT_TYPES::onEntityTransformation) { + // CallEvent(EVENT_TYPES::onEntityTransformation, + // String::newString(to_string(ev.mBeforeEntityUniqueId->id)), + // EntityClass::newEntity(ev.mAfterEntity)); + // } + // IF_LISTENED_END(EVENT_TYPES::onEntityTransformation); + // }); + // break; + + // case EVENT_TYPES::onProjectileHitBlock: + // Event::ProjectileHitBlockEvent::subscribe( + // [](const ProjectileHitBlockEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onProjectileHitBlock) { + // CallEvent(EVENT_TYPES::onProjectileHitBlock, + // BlockClass::newBlock(ev.mBlockInstance), + // EntityClass::newEntity(ev.mSource)); + // } + // IF_LISTENED_END(EVENT_TYPES::onProjectileHitBlock); + // }); + // break; + + // case EVENT_TYPES::onLiquidFlow: + // Event::LiquidSpreadEvent::subscribe([](const LiquidSpreadEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onLiquidFlow) { + // CallEvent(EVENT_TYPES::onLiquidFlow, + // BlockClass::newBlock(ev.mBlockInstance), + // IntPos::newPos(ev.mTarget, ev.mDimensionId)); + // } + // IF_LISTENED_END(EVENT_TYPES::onLiquidFlow); + // }); + // break; + + // case EVENT_TYPES::onUseFrameBlock: + // Event::PlayerUseFrameBlockEvent::subscribe( + // [](const PlayerUseFrameBlockEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onUseFrameBlock) { + // CallEvent(EVENT_TYPES::onUseFrameBlock, + // PlayerClass::newPlayer(ev.mPlayer), + // BlockClass::newBlock(ev.mBlockInstance)); + // } + // IF_LISTENED_END(EVENT_TYPES::onUseFrameBlock); + // }); + // break; + + // case EVENT_TYPES::onBlockInteracted: + // Event::BlockInteractedEvent::subscribe([](const BlockInteractedEvent + // &ev) { + // IF_LISTENED(EVENT_TYPES::onBlockInteracted) { + // CallEvent(EVENT_TYPES::onBlockInteracted, + // PlayerClass::newPlayer(ev.mPlayer), + // BlockClass::newBlock(ev.mBlockInstance)); + // } + // IF_LISTENED_END(EVENT_TYPES::onBlockInteracted); + // }); + // break; + + // case EVENT_TYPES::onFarmLandDecay: + // Event::FarmLandDecayEvent::subscribe([](const FarmLandDecayEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onFarmLandDecay) { + // BlockInstance bl(ev.mBlockInstance); + // CallEvent(EVENT_TYPES::onFarmLandDecay, + // IntPos::newPos(bl.getPosition(), bl.getDimensionId()), + // EntityClass::newEntity(ev.mActor)); + // } + // IF_LISTENED_END(EVENT_TYPES::onFarmLandDecay); + // }); + // break; + + // case EVENT_TYPES::onPistonTryPush: + // Event::PistonTryPushEvent::subscribe([](const PistonTryPushEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onPistonTryPush) { + // BlockInstance bl(ev.mPistonBlockInstance); + // CallEvent(EVENT_TYPES::onPistonTryPush, + // IntPos::newPos(bl.getPosition(), bl.getDimensionId()), + // BlockClass::newBlock(ev.mTargetBlockInstance)); + // } + // IF_LISTENED_END(EVENT_TYPES::onPistonTryPush); + // }); + // break; + + // case EVENT_TYPES::onPistonPush: + // Event::PistonPushEvent::subscribe([](const PistonPushEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onPistonPush) { + // BlockInstance bl(ev.mPistonBlockInstance); + // CallEvent(EVENT_TYPES::onPistonPush, + // IntPos::newPos(bl.getPosition(), bl.getDimensionId()), + // BlockClass::newBlock(ev.mTargetBlockInstance)); + // } + // IF_LISTENED_END(EVENT_TYPES::onPistonPush); + // }); + // break; + + // case EVENT_TYPES::onHopperSearchItem: + // Event::HopperSearchItemEvent::subscribe( + // [](const HopperSearchItemEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onHopperSearchItem) { + // CallEvent(EVENT_TYPES::onHopperSearchItem, + // FloatPos::newPos(ev.mPos, ev.mDimensionId), + // Boolean::newBoolean(ev.isMinecart), + // ItemClass::newItem(ev.mItemStack)); + // } + // IF_LISTENED_END(EVENT_TYPES::onHopperSearchItem); + // }); + // break; + + // case EVENT_TYPES::onHopperPushOut: + // Event::HopperPushOutEvent::subscribe([](const HopperPushOutEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onHopperPushOut) { + // CallEvent(EVENT_TYPES::onHopperPushOut, + // FloatPos::newPos(ev.mPos, ev.mDimensionId), + // Boolean::newBoolean(ev.isMinecart), + // ItemClass::newItem(ev.mItemStack)); + // } + // IF_LISTENED_END(EVENT_TYPES::onHopperPushOut); + // }); + // break; + + // case EVENT_TYPES::onFireSpread: + // Event::FireSpreadEvent::subscribe([](const FireSpreadEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onFireSpread) { + // CallEvent(EVENT_TYPES::onFireSpread, + // IntPos::newPos(ev.mTarget, ev.mDimensionId)); + // } + // IF_LISTENED_END(EVENT_TYPES::onFireSpread); + // }); + // break; + + // case EVENT_TYPES::onBlockChanged: + // Event::BlockChangedEvent::subscribe([](const BlockChangedEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onBlockChanged) { + // CallEvent(EVENT_TYPES::onBlockChanged, + // BlockClass::newBlock(ev.mPreviousBlockInstance), + // BlockClass::newBlock(ev.mNewBlockInstance)); + // } + // IF_LISTENED_END(EVENT_TYPES::onBlockChanged); + // }); + // break; + + // case EVENT_TYPES::onScoreChanged: + // Event::PlayerScoreChangedEvent::subscribe( + // [](const PlayerScoreChangedEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onScoreChanged) { + // CallEvent(EVENT_TYPES::onScoreChanged, + // PlayerClass::newPlayer(ev.mPlayer), + // Number::newNumber(ev.mScore), + // String::newString(ev.mObjective->getName()), + // String::newString(ev.mObjective->getDisplayName())); + // } + // IF_LISTENED_END(EVENT_TYPES::onScoreChanged); + // }); + // break; + + // case EVENT_TYPES::onConsoleOutput: + // Event::ConsoleOutputEvent::subscribe([](const ConsoleOutputEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onConsoleOutput) { + // CallEvent(EVENT_TYPES::onConsoleOutput, + // String::newString(ev.mOutput)); + // } + // IF_LISTENED_END(EVENT_TYPES::onConsoleOutput); + // }); + // break; + + // case EVENT_TYPES::onMobSpawn: + // logger.warn( + // "Event 'onMobSpawn' is outdated, please use 'onMobTrySpawn' + // instead."); + // Event::MobTrySpawnEvent::subscribe([](const MobTrySpawnEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onMobSpawn) { + // CallEvent(EVENT_TYPES::onMobSpawn, String::newString(ev.mTypeName), + // FloatPos::newPos(ev.mPos, ev.mDimensionId)); + // } + // IF_LISTENED_END(EVENT_TYPES::onMobSpawn); + // }); + // break; + + // case EVENT_TYPES::onMobTrySpawn: + // Event::MobTrySpawnEvent::subscribe([](const MobTrySpawnEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onMobTrySpawn) { + // CallEvent(EVENT_TYPES::onMobTrySpawn, + // String::newString(ev.mTypeName), + // FloatPos::newPos(ev.mPos, ev.mDimensionId)); + // } + // IF_LISTENED_END(EVENT_TYPES::onMobTrySpawn); + // }); + // break; + + // case EVENT_TYPES::onMobSpawned: + // Event::MobSpawnedEvent::subscribe([](const MobSpawnedEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onMobSpawned) { + // CallEvent(EVENT_TYPES::onMobSpawned, + // EntityClass::newEntity((Actor *)(ev.mMob)), + // FloatPos::newPos(ev.mPos, ev.mDimensionId)); + // } + // IF_LISTENED_END(EVENT_TYPES::onMobSpawned); + // }); + // break; + + // case EVENT_TYPES::onExperienceAdd: + // Event::PlayerExperienceAddEvent::subscribe( + // [](const PlayerExperienceAddEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onExperienceAdd) { + // CallEvent(EVENT_TYPES::onExperienceAdd, + // PlayerClass::newPlayer(ev.mPlayer), + // Number::newNumber(ev.mExp)); + // } + // IF_LISTENED_END(EVENT_TYPES::onExperienceAdd); + // }); + // break; + + // case EVENT_TYPES::onBedEnter: + // Event::PlayerBedEnterEvent::subscribe([](const PlayerBedEnterEvent &ev) + // { + // IF_LISTENED(EVENT_TYPES::onBedEnter) { + // BlockInstance bl(*ev.mBlockInstance); + // CallEvent(EVENT_TYPES::onBedEnter, + // PlayerClass::newPlayer(ev.mPlayer), + // IntPos::newPos(bl.getPosition(), bl.getDimensionId())); + // } + // IF_LISTENED_END(EVENT_TYPES::onBedEnter); + // }); + // break; + + // case EVENT_TYPES::onOpenInventory: + // Event::PlayerOpenInventoryEvent::subscribe( + // [](const PlayerOpenInventoryEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onOpenInventory) { + // CallEvent(EVENT_TYPES::onOpenInventory, + // PlayerClass::newPlayer(ev.mPlayer)); + // } + // IF_LISTENED_END(EVENT_TYPES::onOpenInventory); + // }); + // break; + + // /* DEPRECATED AND RECENTLY REMOVED - START */ + + // case EVENT_TYPES::onAttack: + // Event::PlayerAttackEvent::subscribe([](const PlayerAttackEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onAttack) { + // if (ev.mTarget) { + // CallEvent(EVENT_TYPES::onAttack, + // PlayerClass::newPlayer(ev.mPlayer), + // EntityClass::newEntity(ev.mTarget)); + // } + // } + // IF_LISTENED_END(EVENT_TYPES::onAttack); + // }); + // break; + + // case EVENT_TYPES::onContainerChangeSlot: + // Event::ContainerChangeEvent::subscribe([](const ContainerChangeEvent + // &ev) { + // IF_LISTENED(EVENT_TYPES::onContainerChange) { + // CallEvent(EVENT_TYPES::onContainerChange, + // PlayerClass::newPlayer(ev.mPlayer), + // BlockClass::newBlock(ev.mBlockInstance), + // Number::newNumber(ev.mSlot), + // ItemClass::newItem(ev.mPreviousItemStack), + // ItemClass::newItem(ev.mNewItemStack)); + // } + // IF_LISTENED_END(EVENT_TYPES::onContainerChange); + // }); + // break; + + // case EVENT_TYPES::onExplode: + // Event::EntityExplodeEvent::subscribe([](const EntityExplodeEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onExplode) { + // CallEvent( + // EVENT_TYPES::onExplode, + // ev.mActor ? EntityClass::newEntity(ev.mActor) : Local(), + // FloatPos::newPos(ev.mPos, ev.mDimension->getDimensionId()), + // Number::newNumber(ev.mRadius), + // Number::newNumber(ev.mMaxResistance), + // Boolean::newBoolean(ev.mBreaking), + // Boolean::newBoolean(ev.mFire)); + // } + // IF_LISTENED_END(EVENT_TYPES::onExplode); + // }); + // break; + + // case EVENT_TYPES::onBedExplode: + // Event::BlockExplodeEvent::subscribe([](const BlockExplodeEvent &ev) { + // BlockInstance bl(ev.mBlockInstance); + // if (bl.getBlock()->getName() == "minecraft:bed") { + // IF_LISTENED(EVENT_TYPES::onBedExplode) { + // CallEvent(EVENT_TYPES::onBedExplode, + // IntPos::newPos(bl.getPosition(), bl.getDimensionId())); + // } + // IF_LISTENED_END(EVENT_TYPES::onBedExplode); + // } + // return true; + // }); + // break; + + // case EVENT_TYPES::onPlayerPullFishingHook: + // Event::PlayerPullFishingHookEvent::subscribe( + // [](const PlayerPullFishingHookEvent &ev) { + // IF_LISTENED(EVENT_TYPES::onPlayerPullFishingHook) { + // CallEvent(EVENT_TYPES::onPlayerPullFishingHook, + // PlayerClass::newPlayer(ev.mPlayer), + // ev.mActor ? EntityClass::newEntity(ev.mActor) + // : Local(), + // ev.mItemStack ? ItemClass::newItem(ev.mItemStack) + // : Local()); + // } + // IF_LISTENED_END(EVENT_TYPES::onPlayerPullFishingHook); + // return true; + // }); + // break; + + /* DEPRECATED AND RECENTLY REMOVED - END */ + + default: + break; + } +} - // case EVENT_TYPES::onAte: - // Event::PlayerAteEvent::subscribe([](const PlayerAteEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onAte) { - // CallEvent(EVENT_TYPES::onAte, PlayerClass::newPlayer(ev.mPlayer), - // ItemClass::newItem(ev.mFoodItem)); - // } - // IF_LISTENED_END(EVENT_TYPES::onAte); - // }); - // break; - - // case EVENT_TYPES::onConsumeTotem: - // Event::PlayerConsumeTotemEvent::subscribe( - // [](const PlayerConsumeTotemEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onConsumeTotem) { - // CallEvent(EVENT_TYPES::onConsumeTotem, - // PlayerClass::newPlayer(ev.mPlayer)); +void InitBasicEventListeners() { + using namespace ll::event; + + // Event::PlayerCmdEvent::subscribe([](const PlayerCmdEvent &ev) { + // string cmd = ev.mCommand; + // Player *player = ev.mPlayer; + + // vector paras; + // bool isFromOtherEngine = false; + // string prefix = LLSEFindCmdReg(true, cmd, paras, &isFromOtherEngine); + + // if (!prefix.empty()) { + // // LLSE Registered Cmd + // int perm = localShareData->playerCmdCallbacks[prefix].perm; + // auto permission_level = player->getCommandPermissionLevel(); + // if (static_cast(permission_level) >= perm) { + // bool callbackRes = CallPlayerCmdCallback(player, prefix, paras); + // IF_LISTENED(EVENT_TYPES::onPlayerCmd) { + // CallEvent(EVENT_TYPES::onPlayerCmd, + // PlayerClass::newPlayer(player), + // String::newString(cmd)); // } - // IF_LISTENED_END(EVENT_TYPES::onConsumeTotem); - // }); - // break; - - // case EVENT_TYPES::onEffectAdded: - // case EVENT_TYPES::onEffectRemoved: - // case EVENT_TYPES::onEffectUpdated: - // Event::PlayerEffectChangedEvent::subscribe([](const - // PlayerEffectChangedEvent - // &ev) { - // if (ev.mEventType == PlayerEffectChangedEvent::EventType::Add) { - // IF_LISTENED(EVENT_TYPES::onEffectAdded) { - // CallEvent( - // EVENT_TYPES::onEffectAdded, - // PlayerClass::newPlayer(ev.mPlayer), - // String::newString(ev.mEffect->getComponentName().getString()), - // Number::newNumber(ev.mEffect->getAmplifier()), - // Number::newNumber(ev.mEffect->getDuration())); + // IF_LISTENED_END(EVENT_TYPES::onPlayerCmd); + // if (!callbackRes) + // return false; // } - // IF_LISTENED_END(EVENT_TYPES::onEffectAdded); - // } else if (ev.mEventType == - // PlayerEffectChangedEvent::EventType::Remove) { - // IF_LISTENED(EVENT_TYPES::onEffectRemoved) { - // CallEvent( - // EVENT_TYPES::onEffectRemoved, - // PlayerClass::newPlayer(ev.mPlayer), - // String::newString(ev.mEffect->getComponentName().getString())); + // } else { + // if (isFromOtherEngine) + // return false; + + // // Other Cmd + // IF_LISTENED(EVENT_TYPES::onPlayerCmd) { + // CallEvent(EVENT_TYPES::onPlayerCmd, PlayerClass::newPlayer(player), + // String::newString(cmd)); // } - // IF_LISTENED_END(EVENT_TYPES::onEffectRemoved); - // } else if (ev.mEventType == - // PlayerEffectChangedEvent::EventType::Update) { - // IF_LISTENED(EVENT_TYPES::onEffectUpdated) { - // CallEvent( - // EVENT_TYPES::onEffectUpdated, - // PlayerClass::newPlayer(ev.mPlayer), - // String::newString(ev.mEffect->getComponentName().getString()), - // Number::newNumber(ev.mEffect->getAmplifier()), - // Number::newNumber(ev.mEffect->getDuration())); - // } - // IF_LISTENED_END(EVENT_TYPES::onEffectUpdated); + // IF_LISTENED_END(EVENT_TYPES::onPlayerCmd); // } // return true; // }); - // break; - - // case EVENT_TYPES::onUseRespawnAnchor: - // Event::PlayerUseRespawnAnchorEvent::subscribe( - // [](const PlayerUseRespawnAnchorEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onUseRespawnAnchor) { - // BlockInstance bl(ev.mBlockInstance); - // CallEvent(EVENT_TYPES::onUseRespawnAnchor, - // PlayerClass::newPlayer(ev.mPlayer), - // IntPos::newPos(bl.getPosition(), - // bl.getDimensionId())); - // } - // IF_LISTENED_END(EVENT_TYPES::onUseRespawnAnchor); - // }); - // break; - // case EVENT_TYPES::onRide: - // Event::EntityRideEvent::subscribe([](const EntityRideEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onRide) { - // CallEvent(EVENT_TYPES::onRide, EntityClass::newEntity(ev.mRider), - // EntityClass::newEntity(ev.mVehicle)); - // } - // IF_LISTENED_END(EVENT_TYPES::onRide); - // }); - // break; - - // case EVENT_TYPES::onEntityExplode: - // Event::EntityExplodeEvent::subscribe([](const EntityExplodeEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onEntityExplode) { - // CallEvent( - // EVENT_TYPES::onEntityExplode, - // ev.mActor ? EntityClass::newEntity(ev.mActor) : Local(), - // FloatPos::newPos(ev.mPos, ev.mDimension->getDimensionId()), - // Number::newNumber(ev.mRadius), - // Number::newNumber(ev.mMaxResistance), - // Boolean::newBoolean(ev.mBreaking), - // Boolean::newBoolean(ev.mFire)); - // } - // IF_LISTENED_END(EVENT_TYPES::onEntityExplode); - // }); - // break; - - // case EVENT_TYPES::onBlockExplode: - // Event::BlockExplodeEvent::subscribe([](const BlockExplodeEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onBlockExplode) { - // BlockInstance bl(ev.mBlockInstance); - // CallEvent( - // EVENT_TYPES::onBlockExplode, BlockClass::newBlock(bl), - // IntPos::newPos(bl.getPosition(), bl.getDimensionId()), - // Number::newNumber(ev.mRadius), - // Number::newNumber(ev.mMaxResistance), - // Boolean::newBoolean(ev.mBreaking), - // Boolean::newBoolean(ev.mFire)); - // } - // IF_LISTENED_END(EVENT_TYPES::onBlockExplode); - // }); - // break; - - // case EVENT_TYPES::onRespawnAnchorExplode: - // Event::BlockExplodeEvent::subscribe([](const BlockExplodeEvent &ev) { - // BlockInstance bl(ev.mBlockInstance); - // if (bl.getBlock()->getName() == "minecraft:respawn_anchor") { - // IF_LISTENED(EVENT_TYPES::onRespawnAnchorExplode) { - // CallEvent(EVENT_TYPES::onRespawnAnchorExplode, - // IntPos::newPos(bl.getPosition(), bl.getDimensionId()), - // Local()); + // Event::ConsoleCmdEvent::subscribe_ref([](ConsoleCmdEvent &ev) { + // string cmd = ev.mCommand; + + // // PreProcess + // if (!ProcessDebugEngine(cmd)) + // return false; + // if (!ProcessOldHotManageCommand(ev.mCommand)) + // return false; + // #ifdef LLSE_BACKEND_NODEJS + // if (!NodeJsHelper::processConsoleNpmCmd(ev.mCommand)) + // return false; + // #elif defined(LLSE_BACKEND_PYTHON) + // if (!PythonHelper::processConsolePipCmd(ev.mCommand)) + // return false; + // #endif + // // CallEvents + // vector paras; + // bool isFromOtherEngine = false; + // string prefix = LLSEFindCmdReg(false, cmd, paras, &isFromOtherEngine); + + // if (!prefix.empty()) { + // // LLSE Registered Cmd + + // bool callbackRes = CallServerCmdCallback(prefix, paras); + // IF_LISTENED(EVENT_TYPES::onConsoleCmd) { + // CallEvent(EVENT_TYPES::onConsoleCmd, String::newString(cmd)); // } - // IF_LISTENED_END(EVENT_TYPES::onRespawnAnchorExplode); - // } - // return true; - // }); - // break; - - // case EVENT_TYPES::onBlockExploded: - // Event::BlockExplodedEvent::subscribe([](const BlockExplodedEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onBlockExploded) { - // CallEvent(EVENT_TYPES::onBlockExploded, - // BlockClass::newBlock(ev.mBlockInstance), - // EntityClass::newEntity(ev.mExplodeSource)); - // } - // IF_LISTENED_END(EVENT_TYPES::onBlockExploded); - // }); - // break; - - // case EVENT_TYPES::onCmdBlockExecute: - // Event::CmdBlockExecuteEvent::subscribe([](const CmdBlockExecuteEvent - // &ev) { - // IF_LISTENED(EVENT_TYPES::onCmdBlockExecute) { - // if (ev.mIsMinecart) { - // CallEvent(EVENT_TYPES::onCmdBlockExecute, - // String::newString(ev.mCommand), - // FloatPos::newPos(ev.mMinecart->getPosition(), - // ev.mMinecart->getDimensionId()), - // Boolean::newBoolean(ev.mIsMinecart)); - // } else { - // BlockInstance bl = ev.mBlockInstance; - // CallEvent( - // EVENT_TYPES::onCmdBlockExecute, - // String::newString(ev.mCommand), - // FloatPos::newPos(bl.getPosition().toVec3(), - // bl.getDimensionId()), Boolean::newBoolean(ev.mIsMinecart)); + // IF_LISTENED_END(EVENT_TYPES::onConsoleCmd); + // if (!callbackRes) + // return false; + // } else { + // if (isFromOtherEngine) + // return false; + + // // Other Cmd + // IF_LISTENED(EVENT_TYPES::onConsoleCmd) { + // CallEvent(EVENT_TYPES::onConsoleCmd, String::newString(cmd)); // } + // IF_LISTENED_END(EVENT_TYPES::onConsoleCmd); // } - // IF_LISTENED_END(EVENT_TYPES::onCmdBlockExecute); - // }); - // break; - - // case EVENT_TYPES::onRedStoneUpdate: - // Event::RedStoneUpdateEvent::subscribe([](const RedStoneUpdateEvent &ev) - // { - // IF_LISTENED(EVENT_TYPES::onRedStoneUpdate) { - // CallEvent(EVENT_TYPES::onRedStoneUpdate, - // BlockClass::newBlock(ev.mBlockInstance), - // Number::newNumber(ev.mRedStonePower), - // Boolean::newBoolean(ev.mIsActivated)); - // } - // IF_LISTENED_END(EVENT_TYPES::onRedStoneUpdate); + // return true; // }); - // break; - - // case EVENT_TYPES::onWitherBossDestroy: - // Event::WitherBossDestroyEvent::subscribe( - // [](const WitherBossDestroyEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onWitherBossDestroy) { - // AABB range = ev.mDestroyRange; - // int dimId = ((Actor *)ev.mWitherBoss)->getDimensionId(); - // CallEvent(EVENT_TYPES::onWitherBossDestroy, - // EntityClass::newEntity((Actor *)ev.mWitherBoss), - // IntPos::newPos(range.min.toBlockPos(), dimId), - // IntPos::newPos(range.max.toBlockPos(), dimId)); - // } - // IF_LISTENED_END(EVENT_TYPES::onWitherBossDestroy); - // }); - // break; - - // case EVENT_TYPES::onMobHurt: - // Event::MobHurtEvent::subscribe([](const MobHurtEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onMobHurt) { - // Actor *source = nullptr; - // if (ev.mDamageSource->isEntitySource()) { - // if (ev.mDamageSource->isChildEntitySource()) - // source = - // Level::getEntity(ev.mDamageSource->getEntityUniqueID()); - // else - // source = - // Level::getEntity(ev.mDamageSource->getDamagingEntityUniqueID()); - // } - // CallEvent(EVENT_TYPES::onMobHurt, EntityClass::newEntity(ev.mMob), - // source ? EntityClass::newEntity(source) : Local(), - // Number::newNumber(float(ev.mDamage)), - // Number::newNumber((int)ev.mDamageSource->getCause())); - // } - // IF_LISTENED_END(EVENT_TYPES::onMobHurt) - // }); - // break; - - // case EVENT_TYPES::onStepOnPressurePlate: - // Event::EntityStepOnPressurePlateEvent::subscribe( - // [](const EntityStepOnPressurePlateEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onStepOnPressurePlate) { - // CallEvent(EVENT_TYPES::onStepOnPressurePlate, - // EntityClass::newEntity(ev.mActor), - // BlockClass::newBlock(ev.mBlockInstance)); + // // Plugin Hot Management + // Event::ScriptPluginManagerEvent::subscribe_ref( + // [](ScriptPluginManagerEvent &ev) { + // switch (ev.operation) { + // case ScriptPluginManagerEvent::Operation::Load: + // // ev.pluginType is not used + // // since in loadPlugin there will be check + // try { + // if (PluginManager::loadPlugin(ev.target, true, true)) + // ev.success = true; + // } catch (...) { + // } + // break; + + // case ScriptPluginManagerEvent::Operation::Unload: + // if (PluginManager::unloadPlugin(ev.target)) + // ev.success = true; + // break; + + // case ScriptPluginManagerEvent::Operation::Reload: + // if (PluginManager::reloadPlugin(ev.target)) + // ev.success = true; + // break; + + // default: + // break; // } - // IF_LISTENED_END(EVENT_TYPES::onStepOnPressurePlate); + // if (ev.success) + // return false; // Success. No need to spread to next engine + // return true; // }); - // break; - - // case EVENT_TYPES::onMobDie: - // Event::MobDieEvent::subscribe([](const MobDieEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onMobDie) { - // Actor *source = nullptr; - // if (ev.mDamageSource->isEntitySource()) { - // source = - // Level::getEntity(ev.mDamageSource->getDamagingEntityUniqueID()); - // if (ev.mDamageSource->isChildEntitySource()) - // source = source->getOwner(); - // } - // CallEvent(EVENT_TYPES::onMobDie, - // EntityClass::newEntity((Actor *)ev.mMob), - // (source ? EntityClass::newEntity(source) : - // Local()), - // Number::newNumber((int)ev.mDamageSource->getCause())); - // } - // IF_LISTENED_END(EVENT_TYPES::onMobDie); - // }); - // break; - - // case EVENT_TYPES::onSpawnProjectile: - // Event::ProjectileSpawnEvent::subscribe([](const ProjectileSpawnEvent - // &ev) { - // IF_LISTENED(EVENT_TYPES::onSpawnProjectile) { - // CallEvent(EVENT_TYPES::onSpawnProjectile, - // EntityClass::newEntity(ev.mShooter), - // String::newString(ev.mType)); - // } - // IF_LISTENED_END(EVENT_TYPES::onSpawnProjectile); - // }); - // break; - - // case EVENT_TYPES::onProjectileCreated: - // Event::ProjectileCreatedEvent::subscribe( - // [](const ProjectileCreatedEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onProjectileCreated) { - // CallEvent(EVENT_TYPES::onProjectileCreated, - // EntityClass::newEntity(ev.mShooter), - // EntityClass::newEntity(ev.mProjectile)); - // } - // IF_LISTENED_END(EVENT_TYPES::onProjectileCreated); - // }); - // break; - - // case EVENT_TYPES::onProjectileHitEntity: - // Event::ProjectileHitEntityEvent::subscribe( - // [](const ProjectileHitEntityEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onProjectileHitEntity) { - // CallEvent(EVENT_TYPES::onProjectileHitEntity, - // EntityClass::newEntity(ev.mTarget), - // EntityClass::newEntity(ev.mSource)); - // } - // IF_LISTENED_END(EVENT_TYPES::onProjectileHitEntity); - // }); - // break; - - // case EVENT_TYPES::onEntityTransformation: - // Event::EntityTransformEvent::subscribe([](const EntityTransformEvent - // &ev) { - // IF_LISTENED(EVENT_TYPES::onEntityTransformation) { - // CallEvent(EVENT_TYPES::onEntityTransformation, - // String::newString(to_string(ev.mBeforeEntityUniqueId->id)), - // EntityClass::newEntity(ev.mAfterEntity)); - // } - // IF_LISTENED_END(EVENT_TYPES::onEntityTransformation); - // }); - // break; - - // case EVENT_TYPES::onProjectileHitBlock: - // Event::ProjectileHitBlockEvent::subscribe( - // [](const ProjectileHitBlockEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onProjectileHitBlock) { - // CallEvent(EVENT_TYPES::onProjectileHitBlock, - // BlockClass::newBlock(ev.mBlockInstance), - // EntityClass::newEntity(ev.mSource)); - // } - // IF_LISTENED_END(EVENT_TYPES::onProjectileHitBlock); - // }); - // break; - - // case EVENT_TYPES::onLiquidFlow: - // Event::LiquidSpreadEvent::subscribe([](const LiquidSpreadEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onLiquidFlow) { - // CallEvent(EVENT_TYPES::onLiquidFlow, - // BlockClass::newBlock(ev.mBlockInstance), - // IntPos::newPos(ev.mTarget, ev.mDimensionId)); - // } - // IF_LISTENED_END(EVENT_TYPES::onLiquidFlow); - // }); - // break; - - // case EVENT_TYPES::onUseFrameBlock: - // Event::PlayerUseFrameBlockEvent::subscribe( - // [](const PlayerUseFrameBlockEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onUseFrameBlock) { - // CallEvent(EVENT_TYPES::onUseFrameBlock, - // PlayerClass::newPlayer(ev.mPlayer), - // BlockClass::newBlock(ev.mBlockInstance)); - // } - // IF_LISTENED_END(EVENT_TYPES::onUseFrameBlock); - // }); - // break; - - // case EVENT_TYPES::onBlockInteracted: - // Event::BlockInteractedEvent::subscribe([](const BlockInteractedEvent - // &ev) { - // IF_LISTENED(EVENT_TYPES::onBlockInteracted) { - // CallEvent(EVENT_TYPES::onBlockInteracted, - // PlayerClass::newPlayer(ev.mPlayer), - // BlockClass::newBlock(ev.mBlockInstance)); - // } - // IF_LISTENED_END(EVENT_TYPES::onBlockInteracted); - // }); - // break; - - // case EVENT_TYPES::onFarmLandDecay: - // Event::FarmLandDecayEvent::subscribe([](const FarmLandDecayEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onFarmLandDecay) { - // BlockInstance bl(ev.mBlockInstance); - // CallEvent(EVENT_TYPES::onFarmLandDecay, - // IntPos::newPos(bl.getPosition(), bl.getDimensionId()), - // EntityClass::newEntity(ev.mActor)); - // } - // IF_LISTENED_END(EVENT_TYPES::onFarmLandDecay); - // }); - // break; - - // case EVENT_TYPES::onPistonTryPush: - // Event::PistonTryPushEvent::subscribe([](const PistonTryPushEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onPistonTryPush) { - // BlockInstance bl(ev.mPistonBlockInstance); - // CallEvent(EVENT_TYPES::onPistonTryPush, - // IntPos::newPos(bl.getPosition(), bl.getDimensionId()), - // BlockClass::newBlock(ev.mTargetBlockInstance)); - // } - // IF_LISTENED_END(EVENT_TYPES::onPistonTryPush); - // }); - // break; - - // case EVENT_TYPES::onPistonPush: - // Event::PistonPushEvent::subscribe([](const PistonPushEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onPistonPush) { - // BlockInstance bl(ev.mPistonBlockInstance); - // CallEvent(EVENT_TYPES::onPistonPush, - // IntPos::newPos(bl.getPosition(), bl.getDimensionId()), - // BlockClass::newBlock(ev.mTargetBlockInstance)); - // } - // IF_LISTENED_END(EVENT_TYPES::onPistonPush); - // }); - // break; - - // case EVENT_TYPES::onHopperSearchItem: - // Event::HopperSearchItemEvent::subscribe( - // [](const HopperSearchItemEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onHopperSearchItem) { - // CallEvent(EVENT_TYPES::onHopperSearchItem, - // FloatPos::newPos(ev.mPos, ev.mDimensionId), - // Boolean::newBoolean(ev.isMinecart), - // ItemClass::newItem(ev.mItemStack)); - // } - // IF_LISTENED_END(EVENT_TYPES::onHopperSearchItem); - // }); - // break; - - // case EVENT_TYPES::onHopperPushOut: - // Event::HopperPushOutEvent::subscribe([](const HopperPushOutEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onHopperPushOut) { - // CallEvent(EVENT_TYPES::onHopperPushOut, - // FloatPos::newPos(ev.mPos, ev.mDimensionId), - // Boolean::newBoolean(ev.isMinecart), - // ItemClass::newItem(ev.mItemStack)); - // } - // IF_LISTENED_END(EVENT_TYPES::onHopperPushOut); - // }); - // break; + // // For RegisterCmd... + // Event::RegCmdEvent::subscribe([](const RegCmdEvent &ev) { + // isCmdRegisterEnabled = true; - // case EVENT_TYPES::onFireSpread: - // Event::FireSpreadEvent::subscribe([](const FireSpreadEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onFireSpread) { - // CallEvent(EVENT_TYPES::onFireSpread, - // IntPos::newPos(ev.mTarget, ev.mDimensionId)); - // } - // IF_LISTENED_END(EVENT_TYPES::onFireSpread); - // }); - // break; - - // case EVENT_TYPES::onBlockChanged: - // Event::BlockChangedEvent::subscribe([](const BlockChangedEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onBlockChanged) { - // CallEvent(EVENT_TYPES::onBlockChanged, - // BlockClass::newBlock(ev.mPreviousBlockInstance), - // BlockClass::newBlock(ev.mNewBlockInstance)); - // } - // IF_LISTENED_END(EVENT_TYPES::onBlockChanged); - // }); - // break; - - // case EVENT_TYPES::onScoreChanged: - // Event::PlayerScoreChangedEvent::subscribe( - // [](const PlayerScoreChangedEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onScoreChanged) { - // CallEvent(EVENT_TYPES::onScoreChanged, - // PlayerClass::newPlayer(ev.mPlayer), - // Number::newNumber(ev.mScore), - // String::newString(ev.mObjective->getName()), - // String::newString(ev.mObjective->getDisplayName())); - // } - // IF_LISTENED_END(EVENT_TYPES::onScoreChanged); - // }); - // break; - - // case EVENT_TYPES::onConsoleOutput: - // Event::ConsoleOutputEvent::subscribe([](const ConsoleOutputEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onConsoleOutput) { - // CallEvent(EVENT_TYPES::onConsoleOutput, - // String::newString(ev.mOutput)); - // } - // IF_LISTENED_END(EVENT_TYPES::onConsoleOutput); - // }); - // break; - - // case EVENT_TYPES::onMobSpawn: - // logger.warn( - // "Event 'onMobSpawn' is outdated, please use 'onMobTrySpawn' - // instead."); - // Event::MobTrySpawnEvent::subscribe([](const MobTrySpawnEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onMobSpawn) { - // CallEvent(EVENT_TYPES::onMobSpawn, String::newString(ev.mTypeName), - // FloatPos::newPos(ev.mPos, ev.mDimensionId)); - // } - // IF_LISTENED_END(EVENT_TYPES::onMobSpawn); - // }); - // break; - - // case EVENT_TYPES::onMobTrySpawn: - // Event::MobTrySpawnEvent::subscribe([](const MobTrySpawnEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onMobTrySpawn) { - // CallEvent(EVENT_TYPES::onMobTrySpawn, - // String::newString(ev.mTypeName), - // FloatPos::newPos(ev.mPos, ev.mDimensionId)); - // } - // IF_LISTENED_END(EVENT_TYPES::onMobTrySpawn); - // }); - // break; - - // case EVENT_TYPES::onMobSpawned: - // Event::MobSpawnedEvent::subscribe([](const MobSpawnedEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onMobSpawned) { - // CallEvent(EVENT_TYPES::onMobSpawned, - // EntityClass::newEntity((Actor *)(ev.mMob)), - // FloatPos::newPos(ev.mPos, ev.mDimensionId)); - // } - // IF_LISTENED_END(EVENT_TYPES::onMobSpawned); - // }); - // break; - - // case EVENT_TYPES::onExperienceAdd: - // Event::PlayerExperienceAddEvent::subscribe( - // [](const PlayerExperienceAddEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onExperienceAdd) { - // CallEvent(EVENT_TYPES::onExperienceAdd, - // PlayerClass::newPlayer(ev.mPlayer), - // Number::newNumber(ev.mExp)); - // } - // IF_LISTENED_END(EVENT_TYPES::onExperienceAdd); - // }); - // break; - - // case EVENT_TYPES::onBedEnter: - // Event::PlayerBedEnterEvent::subscribe([](const PlayerBedEnterEvent &ev) - // { - // IF_LISTENED(EVENT_TYPES::onBedEnter) { - // BlockInstance bl(*ev.mBlockInstance); - // CallEvent(EVENT_TYPES::onBedEnter, - // PlayerClass::newPlayer(ev.mPlayer), - // IntPos::newPos(bl.getPosition(), bl.getDimensionId())); - // } - // IF_LISTENED_END(EVENT_TYPES::onBedEnter); + // // 处理延迟注册 + // ProcessRegCmdQueue(); + // return true; // }); - // break; - - // case EVENT_TYPES::onOpenInventory: - // Event::PlayerOpenInventoryEvent::subscribe( - // [](const PlayerOpenInventoryEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onOpenInventory) { - // CallEvent(EVENT_TYPES::onOpenInventory, - // PlayerClass::newPlayer(ev.mPlayer)); - // } - // IF_LISTENED_END(EVENT_TYPES::onOpenInventory); - // }); - // break; - // /* DEPRECATED AND RECENTLY REMOVED - START */ - - // case EVENT_TYPES::onAttack: - // Event::PlayerAttackEvent::subscribe([](const PlayerAttackEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onAttack) { - // if (ev.mTarget) { - // CallEvent(EVENT_TYPES::onAttack, - // PlayerClass::newPlayer(ev.mPlayer), - // EntityClass::newEntity(ev.mTarget)); - // } - // } - // IF_LISTENED_END(EVENT_TYPES::onAttack); - // }); - // break; - - // case EVENT_TYPES::onContainerChangeSlot: - // Event::ContainerChangeEvent::subscribe([](const ContainerChangeEvent - // &ev) { - // IF_LISTENED(EVENT_TYPES::onContainerChange) { - // CallEvent(EVENT_TYPES::onContainerChange, - // PlayerClass::newPlayer(ev.mPlayer), - // BlockClass::newBlock(ev.mBlockInstance), - // Number::newNumber(ev.mSlot), - // ItemClass::newItem(ev.mPreviousItemStack), - // ItemClass::newItem(ev.mNewItemStack)); - // } - // IF_LISTENED_END(EVENT_TYPES::onContainerChange); - // }); - // break; - - // case EVENT_TYPES::onExplode: - // Event::EntityExplodeEvent::subscribe([](const EntityExplodeEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onExplode) { - // CallEvent( - // EVENT_TYPES::onExplode, - // ev.mActor ? EntityClass::newEntity(ev.mActor) : Local(), - // FloatPos::newPos(ev.mPos, ev.mDimension->getDimensionId()), - // Number::newNumber(ev.mRadius), - // Number::newNumber(ev.mMaxResistance), - // Boolean::newBoolean(ev.mBreaking), - // Boolean::newBoolean(ev.mFire)); - // } - // IF_LISTENED_END(EVENT_TYPES::onExplode); - // }); - // break; - - // case EVENT_TYPES::onBedExplode: - // Event::BlockExplodeEvent::subscribe([](const BlockExplodeEvent &ev) { - // BlockInstance bl(ev.mBlockInstance); - // if (bl.getBlock()->getName() == "minecraft:bed") { - // IF_LISTENED(EVENT_TYPES::onBedExplode) { - // CallEvent(EVENT_TYPES::onBedExplode, - // IntPos::newPos(bl.getPosition(), bl.getDimensionId())); - // } - // IF_LISTENED_END(EVENT_TYPES::onBedExplode); + // // ===== onServerStarted ===== + // Event::ServerStartedEvent::subscribe([](Event::ServerStartedEvent ev) { + // IF_LISTENED(EVENT_TYPES::onServerStarted) { + // CallEventDelayed(EVENT_TYPES::onServerStarted); // } + // IF_LISTENED_END(EVENT_TYPES::onServerStarted); // return true; // }); - // break; - - // case EVENT_TYPES::onPlayerPullFishingHook: - // Event::PlayerPullFishingHookEvent::subscribe( - // [](const PlayerPullFishingHookEvent &ev) { - // IF_LISTENED(EVENT_TYPES::onPlayerPullFishingHook) { - // CallEvent(EVENT_TYPES::onPlayerPullFishingHook, - // PlayerClass::newPlayer(ev.mPlayer), - // ev.mActor ? EntityClass::newEntity(ev.mActor) - // : Local(), - // ev.mItemStack ? ItemClass::newItem(ev.mItemStack) - // : Local()); - // } - // IF_LISTENED_END(EVENT_TYPES::onPlayerPullFishingHook); - // return true; - // }); - // break; - - /* DEPRECATED AND RECENTLY REMOVED - END */ - - default: - break; - } -} -void InitBasicEventListeners() { - using namespace ll::event; - - // Event::PlayerCmdEvent::subscribe([](const PlayerCmdEvent &ev) { - // string cmd = ev.mCommand; - // Player *player = ev.mPlayer; - - // vector paras; - // bool isFromOtherEngine = false; - // string prefix = LLSEFindCmdReg(true, cmd, paras, &isFromOtherEngine); - - // if (!prefix.empty()) { - // // LLSE Registered Cmd - // int perm = localShareData->playerCmdCallbacks[prefix].perm; - // auto permission_level = player->getCommandPermissionLevel(); - // if (static_cast(permission_level) >= perm) { - // bool callbackRes = CallPlayerCmdCallback(player, prefix, paras); - // IF_LISTENED(EVENT_TYPES::onPlayerCmd) { - // CallEvent(EVENT_TYPES::onPlayerCmd, - // PlayerClass::newPlayer(player), - // String::newString(cmd)); - // } - // IF_LISTENED_END(EVENT_TYPES::onPlayerCmd); - // if (!callbackRes) - // return false; - // } - // } else { - // if (isFromOtherEngine) - // return false; - - // // Other Cmd - // IF_LISTENED(EVENT_TYPES::onPlayerCmd) { - // CallEvent(EVENT_TYPES::onPlayerCmd, PlayerClass::newPlayer(player), - // String::newString(cmd)); - // } - // IF_LISTENED_END(EVENT_TYPES::onPlayerCmd); - // } - // return true; - // }); - - // Event::ConsoleCmdEvent::subscribe_ref([](ConsoleCmdEvent &ev) { - // string cmd = ev.mCommand; - - // // PreProcess - // if (!ProcessDebugEngine(cmd)) - // return false; - // if (!ProcessOldHotManageCommand(ev.mCommand)) - // return false; - // #ifdef LLSE_BACKEND_NODEJS - // if (!NodeJsHelper::processConsoleNpmCmd(ev.mCommand)) - // return false; - // #elif defined(LLSE_BACKEND_PYTHON) - // if (!PythonHelper::processConsolePipCmd(ev.mCommand)) - // return false; - // #endif - // // CallEvents - // vector paras; - // bool isFromOtherEngine = false; - // string prefix = LLSEFindCmdReg(false, cmd, paras, &isFromOtherEngine); - - // if (!prefix.empty()) { - // // LLSE Registered Cmd - - // bool callbackRes = CallServerCmdCallback(prefix, paras); - // IF_LISTENED(EVENT_TYPES::onConsoleCmd) { - // CallEvent(EVENT_TYPES::onConsoleCmd, String::newString(cmd)); - // } - // IF_LISTENED_END(EVENT_TYPES::onConsoleCmd); - // if (!callbackRes) - // return false; - // } else { - // if (isFromOtherEngine) - // return false; - - // // Other Cmd - // IF_LISTENED(EVENT_TYPES::onConsoleCmd) { - // CallEvent(EVENT_TYPES::onConsoleCmd, String::newString(cmd)); - // } - // IF_LISTENED_END(EVENT_TYPES::onConsoleCmd); - // } - // return true; - // }); - - // // Plugin Hot Management - // Event::ScriptPluginManagerEvent::subscribe_ref( - // [](ScriptPluginManagerEvent &ev) { - // switch (ev.operation) { - // case ScriptPluginManagerEvent::Operation::Load: - // // ev.pluginType is not used - // // since in loadPlugin there will be check - // try { - // if (PluginManager::loadPlugin(ev.target, true, true)) - // ev.success = true; - // } catch (...) { - // } - // break; - - // case ScriptPluginManagerEvent::Operation::Unload: - // if (PluginManager::unloadPlugin(ev.target)) - // ev.success = true; - // break; - - // case ScriptPluginManagerEvent::Operation::Reload: - // if (PluginManager::reloadPlugin(ev.target)) - // ev.success = true; - // break; - - // default: - // break; - // } - // if (ev.success) - // return false; // Success. No need to spread to next engine - // return true; - // }); - - // // For RegisterCmd... - // Event::RegCmdEvent::subscribe([](const RegCmdEvent &ev) { - // isCmdRegisterEnabled = true; - - // // 处理延迟注册 - // ProcessRegCmdQueue(); - // return true; - // }); - - // // ===== onServerStarted ===== - // Event::ServerStartedEvent::subscribe([](Event::ServerStartedEvent ev) { - // IF_LISTENED(EVENT_TYPES::onServerStarted) { - // CallEventDelayed(EVENT_TYPES::onServerStarted); - // } - // IF_LISTENED_END(EVENT_TYPES::onServerStarted); - // return true; - // }); - - // 植入tick - ll::schedule::ServerTimeScheduler scheduler; - scheduler.add(ll::chrono::ticks(1), []() { + // 植入tick + ll::schedule::ServerTimeScheduler scheduler; + scheduler.add(ll::chrono::ticks(1), []() { #ifndef LLSE_BACKEND_NODEJS - try { - std::list tmpList; - { - std::shared_lock lock( - globalShareData->engineListLock); - // low efficiency - tmpList = globalShareData->globalEngineList; - } - for (auto engine : tmpList) { - if (EngineManager::isValid(engine) && - EngineManager::getEngineType(engine) == LLSE_BACKEND_TYPE) { - EngineScope enter(engine); - engine->messageQueue()->loopQueue( - script::utils::MessageQueue::LoopType::kLoopOnce); + try { + std::list tmpList; + { + std::shared_lock lock(globalShareData->engineListLock); + // low efficiency + tmpList = globalShareData->globalEngineList; + } + for (auto engine : tmpList) { + if (EngineManager::isValid(engine) && EngineManager::getEngineType(engine) == LLSE_BACKEND_TYPE) { + EngineScope enter(engine); + engine->messageQueue()->loopQueue(script::utils::MessageQueue::LoopType::kLoopOnce); + } + } + } catch (...) { + logger.error("Error occurred in Engine Message Loop!"); + logger.error("Uncaught Exception Detected!"); } - } - } catch (...) { - logger.error("Error occurred in Engine Message Loop!"); - logger.error("Uncaught Exception Detected!"); - } #endif - // Call tick event - IF_LISTENED(EVENT_TYPES::onTick) { CallEvent(EVENT_TYPES::onTick); } - IF_LISTENED_END(EVENT_TYPES::onTick); - }); + // Call tick event + IF_LISTENED(EVENT_TYPES::onTick) { CallEvent(EVENT_TYPES::onTick); } + IF_LISTENED_END(EVENT_TYPES::onTick); + }); } /* onTurnLectern // 由于还是不能拦截掉书,暂时注释 @@ -1522,84 +1506,84 @@ page, totalPages, Boolean::newBoolean(shouldDropBook)); } */ -bool MoneyBeforeEventCallback(LLMoneyEvent type, xuid_t from, xuid_t to, - money_t value) { - switch (type) { - case LLMoneyEvent::Add: { - IF_LISTENED(EVENT_TYPES::beforeMoneyAdd) { - CallEvent(EVENT_TYPES::beforeMoneyAdd, String::newString(to), - Number::newNumber(value)); +bool MoneyBeforeEventCallback(LLMoneyEvent type, xuid_t from, xuid_t to, money_t value) { + switch (type) { + case LLMoneyEvent::Add: { + IF_LISTENED(EVENT_TYPES::beforeMoneyAdd) { + CallEvent(EVENT_TYPES::beforeMoneyAdd, String::newString(to), Number::newNumber(value)); + } + IF_LISTENED_END(EVENT_TYPES::beforeMoneyAdd); + break; } - IF_LISTENED_END(EVENT_TYPES::beforeMoneyAdd); - break; - } - case LLMoneyEvent::Reduce: { - IF_LISTENED(EVENT_TYPES::beforeMoneyReduce) { - CallEvent(EVENT_TYPES::beforeMoneyReduce, String::newString(to), - Number::newNumber(value)); + case LLMoneyEvent::Reduce: { + IF_LISTENED(EVENT_TYPES::beforeMoneyReduce) { + CallEvent(EVENT_TYPES::beforeMoneyReduce, String::newString(to), Number::newNumber(value)); + } + IF_LISTENED_END(EVENT_TYPES::beforeMoneyReduce); + break; } - IF_LISTENED_END(EVENT_TYPES::beforeMoneyReduce); - break; - } - case LLMoneyEvent::Trans: { - IF_LISTENED(EVENT_TYPES::beforeMoneyTrans) { - CallEvent(EVENT_TYPES::beforeMoneyTrans, String::newString(from), - String::newString(to), Number::newNumber(value)); + case LLMoneyEvent::Trans: { + IF_LISTENED(EVENT_TYPES::beforeMoneyTrans) { + CallEvent( + EVENT_TYPES::beforeMoneyTrans, + String::newString(from), + String::newString(to), + Number::newNumber(value) + ); + } + IF_LISTENED_END(EVENT_TYPES::beforeMoneyTrans); + break; + } + case LLMoneyEvent::Set: { + IF_LISTENED(EVENT_TYPES::beforeMoneySet) { + CallEvent(EVENT_TYPES::beforeMoneySet, String::newString(to), Number::newNumber(value)); + } + IF_LISTENED_END(EVENT_TYPES::beforeMoneySet); + break; } - IF_LISTENED_END(EVENT_TYPES::beforeMoneyTrans); - break; - } - case LLMoneyEvent::Set: { - IF_LISTENED(EVENT_TYPES::beforeMoneySet) { - CallEvent(EVENT_TYPES::beforeMoneySet, String::newString(to), - Number::newNumber(value)); + default: + break; } - IF_LISTENED_END(EVENT_TYPES::beforeMoneySet); - break; - } - default: - break; - } - return true; + return true; } -bool MoneyEventCallback(LLMoneyEvent type, xuid_t from, xuid_t to, - money_t value) { - switch (type) { - case LLMoneyEvent::Add: { - IF_LISTENED(EVENT_TYPES::onMoneyAdd) { - CallEvent(EVENT_TYPES::onMoneyAdd, String::newString(to), - Number::newNumber(value)); +bool MoneyEventCallback(LLMoneyEvent type, xuid_t from, xuid_t to, money_t value) { + switch (type) { + case LLMoneyEvent::Add: { + IF_LISTENED(EVENT_TYPES::onMoneyAdd) { + CallEvent(EVENT_TYPES::onMoneyAdd, String::newString(to), Number::newNumber(value)); + } + IF_LISTENED_END(EVENT_TYPES::onMoneyAdd); + break; } - IF_LISTENED_END(EVENT_TYPES::onMoneyAdd); - break; - } - case LLMoneyEvent::Reduce: { - IF_LISTENED(EVENT_TYPES::onMoneyReduce) { - CallEvent(EVENT_TYPES::onMoneyReduce, String::newString(to), - Number::newNumber(value)); + case LLMoneyEvent::Reduce: { + IF_LISTENED(EVENT_TYPES::onMoneyReduce) { + CallEvent(EVENT_TYPES::onMoneyReduce, String::newString(to), Number::newNumber(value)); + } + IF_LISTENED_END(EVENT_TYPES::onMoneyReduce); + break; + } + case LLMoneyEvent::Trans: { + IF_LISTENED(EVENT_TYPES::onMoneyTrans) { + CallEvent( + EVENT_TYPES::onMoneyTrans, + String::newString(from), + String::newString(to), + Number::newNumber(value) + ); + } + IF_LISTENED_END(EVENT_TYPES::onMoneyTrans); + break; } - IF_LISTENED_END(EVENT_TYPES::onMoneyReduce); - break; - } - case LLMoneyEvent::Trans: { - IF_LISTENED(EVENT_TYPES::onMoneyTrans) { - CallEvent(EVENT_TYPES::onMoneyTrans, String::newString(from), - String::newString(to), Number::newNumber(value)); + case LLMoneyEvent::Set: { + IF_LISTENED(EVENT_TYPES::onMoneySet) { + CallEvent(EVENT_TYPES::onMoneySet, String::newString(to), Number::newNumber(value)); + } + IF_LISTENED_END(EVENT_TYPES::onMoneySet); + break; } - IF_LISTENED_END(EVENT_TYPES::onMoneyTrans); - break; - } - case LLMoneyEvent::Set: { - IF_LISTENED(EVENT_TYPES::onMoneySet) { - CallEvent(EVENT_TYPES::onMoneySet, String::newString(to), - Number::newNumber(value)); + default: + break; } - IF_LISTENED_END(EVENT_TYPES::onMoneySet); - break; - } - default: - break; - } - return true; + return true; } diff --git a/src/api/FileSystemAPI.cpp b/src/api/FileSystemAPI.cpp index ab2c459b..45efc8c3 100644 --- a/src/api/FileSystemAPI.cpp +++ b/src/api/FileSystemAPI.cpp @@ -43,14 +43,9 @@ ClassDefine FileClassBuilder = .instanceFunction("errorCode", &FileClass::errorCode) .instanceFunction("clear", &FileClass::clear) - .property("ReadMode", - [] { return Number::newNumber((int)FileOpenMode::ReadMode); }) - .property( - "WriteMode", - [] { return Number::newNumber((int)FileOpenMode::WriteMode); }) - .property( - "AppendMode", - [] { return Number::newNumber((int)FileOpenMode::AppendMode); }) + .property("ReadMode", [] { return Number::newNumber((int)FileOpenMode::ReadMode); }) + .property("WriteMode", [] { return Number::newNumber((int)FileOpenMode::WriteMode); }) + .property("AppendMode", [] { return Number::newNumber((int)FileOpenMode::AppendMode); }) .function("readFrom", &FileClass::readFromStatic) .function("writeTo", &FileClass::writeToStatic) @@ -71,735 +66,696 @@ ClassDefine FileClassBuilder = .function("open", &FileClass::open) .build(); -std::optional getDirectoryPath(const std::string &path) { - std::string dirPath; // Directory path - if (path.find('/') != - std::string::npos) { // e.g. plugins/LiteLoader/LiteLoader.json - std::size_t pos = path.find_last_of('/'); - if (pos != std::string::npos) { - dirPath = path.substr(0, pos); - } - } else if (path.find('\\') != - std::string::npos) { // e.g. plugins\\LiteLoader\\LiteLoader.json - std::size_t pos = path.find_last_of('\\'); - if (pos != std::string::npos) { - dirPath = path.substr(0, pos); +std::optional getDirectoryPath(const std::string& path) { + std::string dirPath; // Directory path + if (path.find('/') != std::string::npos) { // e.g. plugins/LiteLoader/LiteLoader.json + std::size_t pos = path.find_last_of('/'); + if (pos != std::string::npos) { + dirPath = path.substr(0, pos); + } + } else if (path.find('\\') != std::string::npos) { // e.g. plugins\\LiteLoader\\LiteLoader.json + std::size_t pos = path.find_last_of('\\'); + if (pos != std::string::npos) { + dirPath = path.substr(0, pos); + } + } else { + return {}; } - } else { - return {}; - } - return dirPath; + return dirPath; } //////////////////// Classes //////////////////// // 生成函数 -FileClass::FileClass(const Local &scriptObj, std::fstream &&f, - const std::string &path, bool isBinary) - : ScriptClass(scriptObj) { - this->file = std::move(f); - this->path = path; - this->isBinary = isBinary; -} - -FileClass::FileClass(std::fstream &&f, const std::string &path, bool isBinary) - : ScriptClass(ScriptClass::ConstructFromCpp{}) { - this->file = std::move(f); - this->path = path; - this->isBinary = isBinary; -} - -FileClass *FileClass::constructor(const Arguments &args) { - CHECK_ARGS_COUNT_C(args, 2); - CHECK_ARG_TYPE_C(args[0], ValueKind::kString); - CHECK_ARG_TYPE_C(args[1], ValueKind::kNumber); - if (args.size() >= 3) - CHECK_ARG_TYPE_C(args[2], ValueKind::kBoolean); - - try { - string path = args[0].toStr(); - std::optional dirPath = getDirectoryPath(path); - if (dirPath.has_value()) { - CreateDirs(dirPath.value()); - } else { - LOG_ERROR_WITH_SCRIPT_INFO("Fail to create directory " + dirPath.value() + - "!\n"); - return nullptr; - } - FileOpenMode fMode = (FileOpenMode)(args[1].toInt()); - // Auto Create - if (fMode == FileOpenMode::ReadMode || fMode == FileOpenMode::WriteMode) { - std::fstream tmp(ll::string_utils::str2wstr(path), std::ios_base::app); - tmp.flush(); - tmp.close(); - } +FileClass::FileClass(const Local& scriptObj, std::fstream&& f, const std::string& path, bool isBinary) +: ScriptClass(scriptObj) { + this->file = std::move(f); + this->path = path; + this->isBinary = isBinary; +} + +FileClass::FileClass(std::fstream&& f, const std::string& path, bool isBinary) +: ScriptClass(ScriptClass::ConstructFromCpp{}) { + this->file = std::move(f); + this->path = path; + this->isBinary = isBinary; +} + +FileClass* FileClass::constructor(const Arguments& args) { + CHECK_ARGS_COUNT_C(args, 2); + CHECK_ARG_TYPE_C(args[0], ValueKind::kString); + CHECK_ARG_TYPE_C(args[1], ValueKind::kNumber); + if (args.size() >= 3) CHECK_ARG_TYPE_C(args[2], ValueKind::kBoolean); + + try { + string path = args[0].toStr(); + std::optional dirPath = getDirectoryPath(path); + if (dirPath.has_value()) { + CreateDirs(dirPath.value()); + } else { + LOG_ERROR_WITH_SCRIPT_INFO("Fail to create directory " + dirPath.value() + "!\n"); + return nullptr; + } + FileOpenMode fMode = (FileOpenMode)(args[1].toInt()); + // Auto Create + if (fMode == FileOpenMode::ReadMode || fMode == FileOpenMode::WriteMode) { + std::fstream tmp(ll::string_utils::str2wstr(path), std::ios_base::app); + tmp.flush(); + tmp.close(); + } - std::ios_base::openmode mode = std::ios_base::in; - if (fMode == FileOpenMode::WriteMode) { - mode |= std::ios_base::out; - // mode |= ios_base::ate; - mode |= std::ios_base::trunc; - } else if (fMode == FileOpenMode::AppendMode) { - mode |= std::ios_base::app; - } + std::ios_base::openmode mode = std::ios_base::in; + if (fMode == FileOpenMode::WriteMode) { + mode |= std::ios_base::out; + // mode |= ios_base::ate; + mode |= std::ios_base::trunc; + } else if (fMode == FileOpenMode::AppendMode) { + mode |= std::ios_base::app; + } - bool isBinary = false; - if (args.size() >= 3 && args[2].asBoolean().value()) { - isBinary = true; - mode |= std::ios_base::binary; - } + bool isBinary = false; + if (args.size() >= 3 && args[2].asBoolean().value()) { + isBinary = true; + mode |= std::ios_base::binary; + } - std::fstream fs(ll::string_utils::str2wstr(path), mode); - if (!fs.is_open()) { - LOG_ERROR_WITH_SCRIPT_INFO("Fail to Open File " + path + "!\n"); - return nullptr; + std::fstream fs(ll::string_utils::str2wstr(path), mode); + if (!fs.is_open()) { + LOG_ERROR_WITH_SCRIPT_INFO("Fail to Open File " + path + "!\n"); + return nullptr; + } + return new FileClass(args.thiz(), std::move(fs), path, isBinary); + } catch (const filesystem_error& e) { + LOG_ERROR_WITH_SCRIPT_INFO("Fail to Open File " + args[0].asString().toString() + "!\n"); + return nullptr; } - return new FileClass(args.thiz(), std::move(fs), path, isBinary); - } catch (const filesystem_error &e) { - LOG_ERROR_WITH_SCRIPT_INFO("Fail to Open File " + - args[0].asString().toString() + "!\n"); - return nullptr; - } - CATCH_C("Fail in OpenFile!"); + CATCH_C("Fail in OpenFile!"); } // 成员函数 Local FileClass::getPath() { - try { - return String::newString(path); - } - CATCH("Fail in getPath!"); + try { + return String::newString(path); + } + CATCH("Fail in getPath!"); } Local FileClass::getAbsolutePath() { - try { - return String::newString( - canonical(std::filesystem::path(ll::string_utils::str2wstr(path))) - .u8string()); - } - CATCH("Fail in getAbsolutePath!"); + try { + return String::newString(canonical(std::filesystem::path(ll::string_utils::str2wstr(path))).u8string()); + } + CATCH("Fail in getAbsolutePath!"); } Local FileClass::getSize() { - try { - size_t cur = file.tellg(); - file.seekg(0, file.end); - size_t size = file.tellg(); - file.seekg(cur, file.beg); - - return Number::newNumber((long long)size); - } - CATCH("Fail in getPath!"); -} - -Local FileClass::readSync(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - - try { - int cnt = args[0].toInt(); - char *buf = new char[cnt]; - file.read(buf, cnt); - size_t bytes = file.gcount(); - - Local res = - isBinary ? ByteBuffer::newByteBuffer(buf, bytes).asValue() - : String::newString(std::string_view(buf, bytes)).asValue(); - delete[] buf; - return res; - } - CATCH("Fail in readSync!"); -} - -Local FileClass::readLineSync(const Arguments &args) { - try { - string buf; - getline(file, buf); - return String::newString(buf); - } - CATCH("Fail in readLineSync!"); -} - -Local FileClass::readAllSync(const Arguments &args) { - try { - string res((std::istreambuf_iterator(file)), - std::istreambuf_iterator()); - return isBinary - ? ByteBuffer::newByteBuffer(res.data(), res.size()).asValue() - : String::newString(res).asValue(); - } - CATCH("Fail in readAllSync!"); -} - -Local FileClass::writeSync(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - - try { - if (args[0].isString()) { - file << args[0].toStr(); - } else if (args[0].isByteBuffer()) { - file.write((char *)args[0].asByteBuffer().getRawBytes(), - args[0].asByteBuffer().byteLength()); - } else { - LOG_WRONG_ARG_TYPE(); - return {}; - } - return Boolean::newBoolean(!file.fail() && !file.bad()); - } - CATCH("Fail in writeSync!"); -} - -Local FileClass::writeLineSync(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - file << args[0].toStr() << "\n"; - return Boolean::newBoolean(!file.fail() && !file.bad()); - } - CATCH("Fail in writeLineSync!"); -} - -Local FileClass::read(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kFunction); - - try { - int cnt = args[0].toInt(); - script::Global callbackFunc{args[1].asFunction()}; - - pool.enqueue([cnt, fp{&file}, isBinary{isBinary}, lock{&lock}, - callback{std::move(callbackFunc)}, - engine{EngineScope::currentEngine()}]() -> void { - if ((ll::getServerStatus() != ll::ServerStatus::Running)) - return; - if (!EngineManager::isValid(engine)) - return; - - char *buf = new char[cnt]; - lock->lock(); - fp->read(buf, cnt); - size_t bytes = fp->gcount(); - lock->unlock(); - - EngineScope scope(engine); - try { - Local res = - isBinary - ? ByteBuffer::newByteBuffer(buf, bytes).asValue() - : String::newString(std::string_view(buf, bytes)).asValue(); + try { + size_t cur = file.tellg(); + file.seekg(0, file.end); + size_t size = file.tellg(); + file.seekg(cur, file.beg); + + return Number::newNumber((long long)size); + } + CATCH("Fail in getPath!"); +} + +Local FileClass::readSync(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + + try { + int cnt = args[0].toInt(); + char* buf = new char[cnt]; + file.read(buf, cnt); + size_t bytes = file.gcount(); + + Local res = isBinary ? ByteBuffer::newByteBuffer(buf, bytes).asValue() + : String::newString(std::string_view(buf, bytes)).asValue(); delete[] buf; - // dangerous - NewTimeout(callback.get(), {res}, 1); - } - CATCH_IN_CALLBACK("ReadFile") - }); - return Boolean::newBoolean(true); - } - CATCH("Fail in read!"); -} - -Local FileClass::readLine(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kFunction); - - try { - script::Global callbackFunc{args[0].asFunction()}; - - pool.enqueue([fp{&file}, lock{&lock}, callback{std::move(callbackFunc)}, - engine{EngineScope::currentEngine()}]() { - if ((ll::getServerStatus() != ll::ServerStatus::Running)) - return; - if (!EngineManager::isValid(engine)) - return; - - string buf; - lock->lock(); - getline(*fp, buf); - lock->unlock(); - - EngineScope scope(engine); - try { - NewTimeout(callback.get(), {String::newString(buf)}, 1); - } - CATCH_IN_CALLBACK("FileReadLine") - }); - return Boolean::newBoolean(true); - } - CATCH("Fail in readLine!"); -} - -Local FileClass::readAll(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kFunction); - - try { - script::Global callbackFunc{args[0].asFunction()}; - - pool.enqueue([fp{&file}, isBinary{isBinary}, lock{&lock}, - callback{std::move(callbackFunc)}, - engine{EngineScope::currentEngine()}]() { - if ((ll::getServerStatus() != ll::ServerStatus::Running)) - return; - if (!EngineManager::isValid(engine)) - return; - - lock->lock(); - string res((std::istreambuf_iterator(*fp)), - std::istreambuf_iterator()); - lock->unlock(); - - EngineScope scope(engine); - try { - Local readed = - isBinary - ? ByteBuffer::newByteBuffer(res.data(), res.size()).asValue() - : String::newString(res).asValue(); - NewTimeout(callback.get(), {readed}, 1); - } - CATCH_IN_CALLBACK("FileReadAll") - }); - return Boolean::newBoolean(true); - } - CATCH("Fail in readAll!"); -} - -Local FileClass::write(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - if (args.size() >= 2) - CHECK_ARG_TYPE(args[1], ValueKind::kFunction); + return res; + } + CATCH("Fail in readSync!"); +} - try { - string data; - bool isString = true; - if (args[0].isString()) { - data = std::move(args[0].toStr()); - } else if (args[0].isByteBuffer()) { - isString = false; - data = std::move(string((char *)args[0].asByteBuffer().getRawBytes(), - args[0].asByteBuffer().byteLength())); - } else { - LOG_WRONG_ARG_TYPE(); - return {}; - } - - script::Global callbackFunc; - if (args.size() >= 2) - callbackFunc = args[1].asFunction(); - - pool.enqueue([fp{&file}, lock{&lock}, data{std::move(data)}, isString, - callback{std::move(callbackFunc)}, - engine{EngineScope::currentEngine()}]() { - if ((ll::getServerStatus() != ll::ServerStatus::Running)) - return; - if (!EngineManager::isValid(engine)) - return; - - lock->lock(); - if (isString) - *fp << data; - else - fp->write(data.data(), data.size()); - bool isOk = !fp->fail() && !fp->bad(); - lock->unlock(); - - if (!callback.isEmpty()) { - EngineScope scope(engine); - try { - NewTimeout(callback.get(), {Boolean::newBoolean(isOk)}, 1); +Local FileClass::readLineSync(const Arguments& args) { + try { + string buf; + getline(file, buf); + return String::newString(buf); + } + CATCH("Fail in readLineSync!"); +} + +Local FileClass::readAllSync(const Arguments& args) { + try { + string res((std::istreambuf_iterator(file)), std::istreambuf_iterator()); + return isBinary ? ByteBuffer::newByteBuffer(res.data(), res.size()).asValue() + : String::newString(res).asValue(); + } + CATCH("Fail in readAllSync!"); +} + +Local FileClass::writeSync(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + + try { + if (args[0].isString()) { + file << args[0].toStr(); + } else if (args[0].isByteBuffer()) { + file.write((char*)args[0].asByteBuffer().getRawBytes(), args[0].asByteBuffer().byteLength()); + } else { + LOG_WRONG_ARG_TYPE(); + return {}; } - CATCH_IN_CALLBACK("WriteFile") - } - }); - return Boolean::newBoolean(true); - } - CATCH("Fail in write!"); -} - -Local FileClass::writeLine(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - if (args.size() >= 2) + return Boolean::newBoolean(!file.fail() && !file.bad()); + } + CATCH("Fail in writeSync!"); +} + +Local FileClass::writeLineSync(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + file << args[0].toStr() << "\n"; + return Boolean::newBoolean(!file.fail() && !file.bad()); + } + CATCH("Fail in writeLineSync!"); +} + +Local FileClass::read(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); CHECK_ARG_TYPE(args[1], ValueKind::kFunction); - try { - string data{std::move(args[0].toStr())}; - - script::Global callbackFunc; - if (args.size() >= 2) - callbackFunc = args[1].asFunction(); - - pool.enqueue([fp{&file}, lock{&lock}, data{std::move(data)}, - callback{std::move(callbackFunc)}, - engine{EngineScope::currentEngine()}]() { - if ((ll::getServerStatus() != ll::ServerStatus::Running)) - return; - if (!EngineManager::isValid(engine)) - return; - - lock->lock(); - *fp << data << "\n"; - bool isOk = !fp->fail() && !fp->bad(); - lock->unlock(); - - if (!callback.isEmpty()) { - EngineScope scope(engine); - try { - NewTimeout(callback.get(), {Boolean::newBoolean(isOk)}, 1); + try { + int cnt = args[0].toInt(); + script::Global callbackFunc{args[1].asFunction()}; + + pool.enqueue( + [cnt, + fp{&file}, + isBinary{isBinary}, + lock{&lock}, + callback{std::move(callbackFunc)}, + engine{EngineScope::currentEngine()}]() -> void { + if ((ll::getServerStatus() != ll::ServerStatus::Running)) return; + if (!EngineManager::isValid(engine)) return; + + char* buf = new char[cnt]; + lock->lock(); + fp->read(buf, cnt); + size_t bytes = fp->gcount(); + lock->unlock(); + + EngineScope scope(engine); + try { + Local res = isBinary ? ByteBuffer::newByteBuffer(buf, bytes).asValue() + : String::newString(std::string_view(buf, bytes)).asValue(); + delete[] buf; + // dangerous + NewTimeout(callback.get(), {res}, 1); + } + CATCH_IN_CALLBACK("ReadFile") + } + ); + return Boolean::newBoolean(true); + } + CATCH("Fail in read!"); +} + +Local FileClass::readLine(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kFunction); + + try { + script::Global callbackFunc{args[0].asFunction()}; + + pool.enqueue([fp{&file}, lock{&lock}, callback{std::move(callbackFunc)}, engine{EngineScope::currentEngine()}]( + ) { + if ((ll::getServerStatus() != ll::ServerStatus::Running)) return; + if (!EngineManager::isValid(engine)) return; + + string buf; + lock->lock(); + getline(*fp, buf); + lock->unlock(); + + EngineScope scope(engine); + try { + NewTimeout(callback.get(), {String::newString(buf)}, 1); + } + CATCH_IN_CALLBACK("FileReadLine") + }); + return Boolean::newBoolean(true); + } + CATCH("Fail in readLine!"); +} + +Local FileClass::readAll(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kFunction); + + try { + script::Global callbackFunc{args[0].asFunction()}; + + pool.enqueue([fp{&file}, + isBinary{isBinary}, + lock{&lock}, + callback{std::move(callbackFunc)}, + engine{EngineScope::currentEngine()}]() { + if ((ll::getServerStatus() != ll::ServerStatus::Running)) return; + if (!EngineManager::isValid(engine)) return; + + lock->lock(); + string res((std::istreambuf_iterator(*fp)), std::istreambuf_iterator()); + lock->unlock(); + + EngineScope scope(engine); + try { + Local readed = isBinary ? ByteBuffer::newByteBuffer(res.data(), res.size()).asValue() + : String::newString(res).asValue(); + NewTimeout(callback.get(), {readed}, 1); + } + CATCH_IN_CALLBACK("FileReadAll") + }); + return Boolean::newBoolean(true); + } + CATCH("Fail in readAll!"); +} + +Local FileClass::write(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + if (args.size() >= 2) CHECK_ARG_TYPE(args[1], ValueKind::kFunction); + + try { + string data; + bool isString = true; + if (args[0].isString()) { + data = std::move(args[0].toStr()); + } else if (args[0].isByteBuffer()) { + isString = false; + data = std::move(string((char*)args[0].asByteBuffer().getRawBytes(), args[0].asByteBuffer().byteLength())); + } else { + LOG_WRONG_ARG_TYPE(); + return {}; } - CATCH_IN_CALLBACK("FileWriteLine") - } - }); - return Boolean::newBoolean(true); - } - CATCH("Fail in writeLine!"); -} - -Local FileClass::seekTo(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kBoolean); - - try { - int pos = args[0].toInt(); - if (args[1].asBoolean().value()) { - // relative - std::ios_base::seekdir way = std::ios_base::cur; - file.seekg(pos, way); - file.seekp(pos, way); - } else { - // absolute - if (pos >= 0) { - std::ios_base::seekdir way = std::ios_base::beg; - file.seekg(pos, way); - file.seekp(pos, way); - } else { - std::ios_base::seekdir way = std::ios_base::end; - file.seekg(0, way); - file.seekp(0, way); - } - } - return Boolean::newBoolean(!file.fail() && !file.bad()); - } - CATCH("Fail in seekTo!"); -} - -Local FileClass::setSize(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - - try { - return Boolean::newBoolean(false); - } - CATCH("Fail in setSize!"); -} - -Local FileClass::close(const Arguments &args) { - try { - file.close(); - return Boolean::newBoolean(true); - } - CATCH("Fail in flush!"); -} - -Local FileClass::isEOF(const Arguments &args) { - try { - return Boolean::newBoolean(file.eof()); - } - CATCH("Fail in isEOF!"); -} - -Local FileClass::flush(const Arguments &args) { - try { - pool.enqueue([fp{&file}, lock{&lock}]() { - lock->lock(); - fp->flush(); - lock->unlock(); - }); - return Boolean::newBoolean(true); - } - CATCH("Fail in flush!"); -} - -Local FileClass::errorCode(const Arguments &args) { - try { - file.flush(); - return Number::newNumber(errno); - } - CATCH("Fail in flush!"); -} - -Local FileClass::clear(const Arguments &args) { - try { - file.clear(); - return Boolean::newBoolean(true); - } - CATCH("Fail in flush!"); + + script::Global callbackFunc; + if (args.size() >= 2) callbackFunc = args[1].asFunction(); + + pool.enqueue([fp{&file}, + lock{&lock}, + data{std::move(data)}, + isString, + callback{std::move(callbackFunc)}, + engine{EngineScope::currentEngine()}]() { + if ((ll::getServerStatus() != ll::ServerStatus::Running)) return; + if (!EngineManager::isValid(engine)) return; + + lock->lock(); + if (isString) *fp << data; + else fp->write(data.data(), data.size()); + bool isOk = !fp->fail() && !fp->bad(); + lock->unlock(); + + if (!callback.isEmpty()) { + EngineScope scope(engine); + try { + NewTimeout(callback.get(), {Boolean::newBoolean(isOk)}, 1); + } + CATCH_IN_CALLBACK("WriteFile") + } + }); + return Boolean::newBoolean(true); + } + CATCH("Fail in write!"); +} + +Local FileClass::writeLine(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + if (args.size() >= 2) CHECK_ARG_TYPE(args[1], ValueKind::kFunction); + + try { + string data{std::move(args[0].toStr())}; + + script::Global callbackFunc; + if (args.size() >= 2) callbackFunc = args[1].asFunction(); + + pool.enqueue([fp{&file}, + lock{&lock}, + data{std::move(data)}, + callback{std::move(callbackFunc)}, + engine{EngineScope::currentEngine()}]() { + if ((ll::getServerStatus() != ll::ServerStatus::Running)) return; + if (!EngineManager::isValid(engine)) return; + + lock->lock(); + *fp << data << "\n"; + bool isOk = !fp->fail() && !fp->bad(); + lock->unlock(); + + if (!callback.isEmpty()) { + EngineScope scope(engine); + try { + NewTimeout(callback.get(), {Boolean::newBoolean(isOk)}, 1); + } + CATCH_IN_CALLBACK("FileWriteLine") + } + }); + return Boolean::newBoolean(true); + } + CATCH("Fail in writeLine!"); +} + +Local FileClass::seekTo(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kBoolean); + + try { + int pos = args[0].toInt(); + if (args[1].asBoolean().value()) { + // relative + std::ios_base::seekdir way = std::ios_base::cur; + file.seekg(pos, way); + file.seekp(pos, way); + } else { + // absolute + if (pos >= 0) { + std::ios_base::seekdir way = std::ios_base::beg; + file.seekg(pos, way); + file.seekp(pos, way); + } else { + std::ios_base::seekdir way = std::ios_base::end; + file.seekg(0, way); + file.seekp(0, way); + } + } + return Boolean::newBoolean(!file.fail() && !file.bad()); + } + CATCH("Fail in seekTo!"); +} + +Local FileClass::setSize(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + + try { + return Boolean::newBoolean(false); + } + CATCH("Fail in setSize!"); +} + +Local FileClass::close(const Arguments& args) { + try { + file.close(); + return Boolean::newBoolean(true); + } + CATCH("Fail in flush!"); +} + +Local FileClass::isEOF(const Arguments& args) { + try { + return Boolean::newBoolean(file.eof()); + } + CATCH("Fail in isEOF!"); +} + +Local FileClass::flush(const Arguments& args) { + try { + pool.enqueue([fp{&file}, lock{&lock}]() { + lock->lock(); + fp->flush(); + lock->unlock(); + }); + return Boolean::newBoolean(true); + } + CATCH("Fail in flush!"); +} + +Local FileClass::errorCode(const Arguments& args) { + try { + file.flush(); + return Number::newNumber(errno); + } + CATCH("Fail in flush!"); +} + +Local FileClass::clear(const Arguments& args) { + try { + file.clear(); + return Boolean::newBoolean(true); + } + CATCH("Fail in flush!"); } //////////////////// APIs //////////////////// -Local DirCreate(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - return Boolean::newBoolean(CreateDirs(args[0].toStr())); - } catch (const filesystem_error &e) { - LOG_ERROR_WITH_SCRIPT_INFO("Fail to Create Dir " + - args[0].asString().toString() + "!\n"); - return Boolean::newBoolean(false); - } - CATCH("Fail in CreateDir!"); -} - -Local PathDelete(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - return Boolean::newBoolean(remove_all(ll::string_utils::str2wstr( - args[0].asString().toString())) > 0); - } catch (const filesystem_error &e) { - LOG_ERROR_WITH_SCRIPT_INFO("Fail to Delete " + - args[0].asString().toString() + "!\n"); - return Boolean::newBoolean(false); - } - CATCH("Fail in DeletePath!"); -} - -Local PathExists(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - return Boolean::newBoolean(std::filesystem::exists( - ll::string_utils::str2wstr(args[0].asString().toString()))); - } catch (const filesystem_error &e) { - LOG_ERROR_WITH_SCRIPT_INFO("Fail to Check " + - args[0].asString().toString() + "!\n"); - return Boolean::newBoolean(false); - } - CATCH("Fail in ExistsPath!"); -} - -Local PathCopy(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - - try { - copy(ll::string_utils::str2wstr(args[0].asString().toString()), - ll::string_utils::str2wstr(args[1].asString().toString())); - return Boolean::newBoolean(true); - } catch (const filesystem_error &e) { - LOG_ERROR_WITH_SCRIPT_INFO("Fail to Copy " + args[0].asString().toString() + - "!\n"); - return Boolean::newBoolean(false); - } - CATCH("Fail in CopyPath!"); -} - -Local PathRename(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - - try { - rename(ll::string_utils::str2wstr(args[0].asString().toString()), - ll::string_utils::str2wstr(args[1].asString().toString())); - return Boolean::newBoolean(true); - } catch (const filesystem_error &e) { - LOG_ERROR_WITH_SCRIPT_INFO("Fail to Rename " + - args[0].asString().toString() + "!\n"); - return Boolean::newBoolean(false); - } - CATCH("Fail in RenamePath!"); -} - -Local PathMove(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - - try { - copy(ll::string_utils::str2wstr(args[0].asString().toString()), - ll::string_utils::str2wstr(args[1].asString().toString())); - remove_all(ll::string_utils::str2wstr(args[0].asString().toString())); - return Boolean::newBoolean(true); - } catch (const filesystem_error &e) { - LOG_ERROR_WITH_SCRIPT_INFO("Fail to Move " + args[0].asString().toString() + - "!\n"); - return Boolean::newBoolean(false); - } - CATCH("Fail in MovePath!"); -} - -Local CheckIsDir(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - path p(ll::string_utils::str2wstr(args[0].toStr())); - if (!exists(p)) - return Boolean::newBoolean(false); - - return Boolean::newBoolean(directory_entry(p).is_directory()); - } catch (const filesystem_error &e) { - LOG_ERROR_WITH_SCRIPT_INFO("Fail to Get Type of " + - args[0].asString().toString() + "!\n"); - return {}; - } - CATCH("Fail in GetFilesList!"); -} - -Local GetFileSize(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - path p(ll::string_utils::str2wstr(args[0].toStr())); - if (!exists(p)) - return Number::newNumber(0); - if (directory_entry(p).is_directory()) - return Number::newNumber(0); - - auto sz = file_size(p); - return Number::newNumber((int64_t)sz); - } catch (const filesystem_error &e) { - LOG_ERROR_WITH_SCRIPT_INFO("Fail to Get Size of " + - args[0].asString().toString() + "!\n"); - return {}; - } - CATCH("Fail in GetFilesList!"); -} - -Local GetFilesList(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - auto fileList = GetFileNameList(args[0].toStr()); - - Local arr = Array::newArray(); - for (auto &file : fileList) - arr.add(String::newString(file)); - return arr; - } - CATCH("Fail in GetFilesList!"); -} - -Local FileReadFrom(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - auto content = ReadAllFile(args[0].toStr()); - if (!content) - return {}; // Null - return String::newString(*content); - } - CATCH("Fail in FileReadAll!"); -} - -Local FileWriteTo(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - - try { - string path = args[0].toStr(); - std::optional dirPath = getDirectoryPath(path); - if (dirPath.has_value()) { - CreateDirs(dirPath.value()); - } else { - LOG_ERROR_WITH_SCRIPT_INFO("Fail to create directory " + dirPath.value() + - "!\n"); - return Boolean::newBoolean(false); +Local DirCreate(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + return Boolean::newBoolean(CreateDirs(args[0].toStr())); + } catch (const filesystem_error& e) { + LOG_ERROR_WITH_SCRIPT_INFO("Fail to Create Dir " + args[0].asString().toString() + "!\n"); + return Boolean::newBoolean(false); } - return Boolean::newBoolean(WriteAllFile(path, args[1].toStr(), false)); - } - CATCH("Fail in FileWriteAll!"); + CATCH("Fail in CreateDir!"); } -Local FileWriteLine(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); +Local PathDelete(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - string path = args[0].toStr(); - std::optional dirPath = getDirectoryPath(path); - if (dirPath.has_value()) { - CreateDirs(dirPath.value()); - } else { - LOG_ERROR_WITH_SCRIPT_INFO("Fail to create directory " + dirPath.value() + - "!\n"); - return Boolean::newBoolean(false); + try { + return Boolean::newBoolean(remove_all(ll::string_utils::str2wstr(args[0].asString().toString())) > 0); + } catch (const filesystem_error& e) { + LOG_ERROR_WITH_SCRIPT_INFO("Fail to Delete " + args[0].asString().toString() + "!\n"); + return Boolean::newBoolean(false); + } + CATCH("Fail in DeletePath!"); +} + +Local PathExists(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + return Boolean::newBoolean(std::filesystem::exists(ll::string_utils::str2wstr(args[0].asString().toString()))); + } catch (const filesystem_error& e) { + LOG_ERROR_WITH_SCRIPT_INFO("Fail to Check " + args[0].asString().toString() + "!\n"); + return Boolean::newBoolean(false); + } + CATCH("Fail in ExistsPath!"); +} + +Local PathCopy(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + + try { + copy( + ll::string_utils::str2wstr(args[0].asString().toString()), + ll::string_utils::str2wstr(args[1].asString().toString()) + ); + return Boolean::newBoolean(true); + } catch (const filesystem_error& e) { + LOG_ERROR_WITH_SCRIPT_INFO("Fail to Copy " + args[0].asString().toString() + "!\n"); + return Boolean::newBoolean(false); + } + CATCH("Fail in CopyPath!"); +} + +Local PathRename(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + + try { + rename( + ll::string_utils::str2wstr(args[0].asString().toString()), + ll::string_utils::str2wstr(args[1].asString().toString()) + ); + return Boolean::newBoolean(true); + } catch (const filesystem_error& e) { + LOG_ERROR_WITH_SCRIPT_INFO("Fail to Rename " + args[0].asString().toString() + "!\n"); + return Boolean::newBoolean(false); + } + CATCH("Fail in RenamePath!"); +} + +Local PathMove(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + + try { + copy( + ll::string_utils::str2wstr(args[0].asString().toString()), + ll::string_utils::str2wstr(args[1].asString().toString()) + ); + remove_all(ll::string_utils::str2wstr(args[0].asString().toString())); + return Boolean::newBoolean(true); + } catch (const filesystem_error& e) { + LOG_ERROR_WITH_SCRIPT_INFO("Fail to Move " + args[0].asString().toString() + "!\n"); + return Boolean::newBoolean(false); + } + CATCH("Fail in MovePath!"); +} + +Local CheckIsDir(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + path p(ll::string_utils::str2wstr(args[0].toStr())); + if (!exists(p)) return Boolean::newBoolean(false); + + return Boolean::newBoolean(directory_entry(p).is_directory()); + } catch (const filesystem_error& e) { + LOG_ERROR_WITH_SCRIPT_INFO("Fail to Get Type of " + args[0].asString().toString() + "!\n"); + return {}; } + CATCH("Fail in GetFilesList!"); +} + +Local GetFileSize(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - std::ofstream fileWrite(path, std::ios::app); - if (!fileWrite) - return Boolean::newBoolean(false); - fileWrite << args[1].toStr() << std::endl; - return Boolean::newBoolean(fileWrite.good()); - } - CATCH("Fail in FileWriteLine!"); + try { + path p(ll::string_utils::str2wstr(args[0].toStr())); + if (!exists(p)) return Number::newNumber(0); + if (directory_entry(p).is_directory()) return Number::newNumber(0); + + auto sz = file_size(p); + return Number::newNumber((int64_t)sz); + } catch (const filesystem_error& e) { + LOG_ERROR_WITH_SCRIPT_INFO("Fail to Get Size of " + args[0].asString().toString() + "!\n"); + return {}; + } + CATCH("Fail in GetFilesList!"); +} + +Local GetFilesList(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + auto fileList = GetFileNameList(args[0].toStr()); + + Local arr = Array::newArray(); + for (auto& file : fileList) arr.add(String::newString(file)); + return arr; + } + CATCH("Fail in GetFilesList!"); +} + +Local FileReadFrom(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + auto content = ReadAllFile(args[0].toStr()); + if (!content) return {}; // Null + return String::newString(*content); + } + CATCH("Fail in FileReadAll!"); +} + +Local FileWriteTo(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + + try { + string path = args[0].toStr(); + std::optional dirPath = getDirectoryPath(path); + if (dirPath.has_value()) { + CreateDirs(dirPath.value()); + } else { + LOG_ERROR_WITH_SCRIPT_INFO("Fail to create directory " + dirPath.value() + "!\n"); + return Boolean::newBoolean(false); + } + return Boolean::newBoolean(WriteAllFile(path, args[1].toStr(), false)); + } + CATCH("Fail in FileWriteAll!"); +} + +Local FileWriteLine(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + + try { + string path = args[0].toStr(); + std::optional dirPath = getDirectoryPath(path); + if (dirPath.has_value()) { + CreateDirs(dirPath.value()); + } else { + LOG_ERROR_WITH_SCRIPT_INFO("Fail to create directory " + dirPath.value() + "!\n"); + return Boolean::newBoolean(false); + } + + std::ofstream fileWrite(path, std::ios::app); + if (!fileWrite) return Boolean::newBoolean(false); + fileWrite << args[1].toStr() << std::endl; + return Boolean::newBoolean(fileWrite.good()); + } + CATCH("Fail in FileWriteLine!"); } //////////////////// For Compatibility //////////////////// -Local OpenFile(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - if (args.size() >= 3) - CHECK_ARG_TYPE(args[2], ValueKind::kBoolean); - - try { - string path = args[0].toStr(); - std::optional dirPath = getDirectoryPath(path); - if (dirPath.has_value()) { - CreateDirs(dirPath.value()); - } else { - LOG_ERROR_WITH_SCRIPT_INFO("Fail to create directory " + dirPath.value() + - "!\n"); - return {}; - } - - FileOpenMode fMode = (FileOpenMode)(args[1].toInt()); - std::ios_base::openmode mode = std::ios_base::in; - if (fMode == FileOpenMode::WriteMode) { - std::fstream tmp(ll::string_utils::str2wstr(path), std::ios_base::app); - tmp.flush(); - tmp.close(); - mode |= std::ios_base::out; - } else if (fMode == FileOpenMode::AppendMode) - mode |= std::ios_base::app; - - bool isBinary = false; - if (args.size() >= 3 && args[2].asBoolean().value()) { - isBinary = true; - mode |= std::ios_base::binary; - } - - std::fstream fs(ll::string_utils::str2wstr(path), mode); - if (!fs.is_open()) { - LOG_ERROR_WITH_SCRIPT_INFO("Fail to Open File " + path + "!\n"); - return {}; - } - return FileClass::newFile(std::move(fs), path, isBinary); - } catch (const filesystem_error &e) { - LOG_ERROR_WITH_SCRIPT_INFO("Fail to Open File " + - args[0].asString().toString() + "!\n"); - return {}; - } - CATCH("Fail in OpenFile!"); -} - -Local FileClass::newFile(std::fstream &&f, const std::string &path, - bool isBinary) { - auto newp = new FileClass(std::move(f), path, isBinary); - return newp->getScriptObject(); +Local OpenFile(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + if (args.size() >= 3) CHECK_ARG_TYPE(args[2], ValueKind::kBoolean); + + try { + string path = args[0].toStr(); + std::optional dirPath = getDirectoryPath(path); + if (dirPath.has_value()) { + CreateDirs(dirPath.value()); + } else { + LOG_ERROR_WITH_SCRIPT_INFO("Fail to create directory " + dirPath.value() + "!\n"); + return {}; + } + + FileOpenMode fMode = (FileOpenMode)(args[1].toInt()); + std::ios_base::openmode mode = std::ios_base::in; + if (fMode == FileOpenMode::WriteMode) { + std::fstream tmp(ll::string_utils::str2wstr(path), std::ios_base::app); + tmp.flush(); + tmp.close(); + mode |= std::ios_base::out; + } else if (fMode == FileOpenMode::AppendMode) mode |= std::ios_base::app; + + bool isBinary = false; + if (args.size() >= 3 && args[2].asBoolean().value()) { + isBinary = true; + mode |= std::ios_base::binary; + } + + std::fstream fs(ll::string_utils::str2wstr(path), mode); + if (!fs.is_open()) { + LOG_ERROR_WITH_SCRIPT_INFO("Fail to Open File " + path + "!\n"); + return {}; + } + return FileClass::newFile(std::move(fs), path, isBinary); + } catch (const filesystem_error& e) { + LOG_ERROR_WITH_SCRIPT_INFO("Fail to Open File " + args[0].asString().toString() + "!\n"); + return {}; + } + CATCH("Fail in OpenFile!"); +} + +Local FileClass::newFile(std::fstream&& f, const std::string& path, bool isBinary) { + auto newp = new FileClass(std::move(f), path, isBinary); + return newp->getScriptObject(); } diff --git a/src/api/FileSystemAPI.h b/src/api/FileSystemAPI.h index b41e6884..368c50a6 100644 --- a/src/api/FileSystemAPI.h +++ b/src/api/FileSystemAPI.h @@ -2,8 +2,8 @@ #include "api/APIHelp.h" #include -#include #include +#include //////////////////// APIs //////////////////// @@ -28,9 +28,9 @@ Local GetFilesList(const Arguments& args); class FileClass : public ScriptClass { private: std::fstream file; - string path; - bool isBinary; - std::mutex lock; + string path; + bool isBinary; + std::mutex lock; public: explicit FileClass(const Local& scriptObj, std::fstream&& f, const std::string& path, bool isBinary); @@ -61,48 +61,22 @@ class FileClass : public ScriptClass { Local errorCode(const Arguments& args); Local clear(const Arguments& args); - static Local readFromStatic(const Arguments& args) { - return FileReadFrom(args); - } - static Local writeToStatic(const Arguments& args) { - return FileWriteTo(args); - } - static Local writeLineStatic(const Arguments& args) { - return FileWriteLine(args); - } + static Local readFromStatic(const Arguments& args) { return FileReadFrom(args); } + static Local writeToStatic(const Arguments& args) { return FileWriteTo(args); } + static Local writeLineStatic(const Arguments& args) { return FileWriteLine(args); } - static Local createDir(const Arguments& args) { - return DirCreate(args); - } - static Local copy(const Arguments& args) { - return PathCopy(args); - } - static Local move(const Arguments& args) { - return PathMove(args); - } - static Local rename(const Arguments& args) { - return PathRename(args); - } - static Local del(const Arguments& args) { - return PathDelete(args); - } - static Local exists(const Arguments& args) { - return PathExists(args); - } - static Local checkIsDir(const Arguments& args) { - return CheckIsDir(args); - } - static Local getFileSize(const Arguments& args) { - return GetFileSize(args); - } - static Local getFilesList(const Arguments& args) { - return GetFilesList(args); - } + static Local createDir(const Arguments& args) { return DirCreate(args); } + static Local copy(const Arguments& args) { return PathCopy(args); } + static Local move(const Arguments& args) { return PathMove(args); } + static Local rename(const Arguments& args) { return PathRename(args); } + static Local del(const Arguments& args) { return PathDelete(args); } + static Local exists(const Arguments& args) { return PathExists(args); } + static Local checkIsDir(const Arguments& args) { return CheckIsDir(args); } + static Local getFileSize(const Arguments& args) { return GetFileSize(args); } + static Local getFilesList(const Arguments& args) { return GetFilesList(args); } // For Compatibility static Local newFile(std::fstream&& f, const std::string& path, bool isBinary); - static Local open(const Arguments& args) { - return OpenFile(args); - } + static Local open(const Arguments& args) { return OpenFile(args); } }; extern ClassDefine FileClassBuilder; \ No newline at end of file diff --git a/src/api/GameUtilsAPI.cpp b/src/api/GameUtilsAPI.cpp index b5ff7a45..96a09b7f 100644 --- a/src/api/GameUtilsAPI.cpp +++ b/src/api/GameUtilsAPI.cpp @@ -2,29 +2,28 @@ #include "api/APIHelp.h" -ClassDefine TextClassBuilder = - defineClass("Format") - .property("Black", []() { return String::newString("§0"); }) - .property("DarkBlue", []() { return String::newString("§1"); }) - .property("DarkGreen", []() { return String::newString("§2"); }) - .property("DarkAqua", []() { return String::newString("§3"); }) - .property("DarkRed", []() { return String::newString("§4"); }) - .property("DarkPurple", []() { return String::newString("§5"); }) - .property("Gold", []() { return String::newString("§6"); }) - .property("Gray", []() { return String::newString("§7"); }) - .property("DarkGray", []() { return String::newString("§8"); }) - .property("Blue", []() { return String::newString("§9"); }) - .property("Green", []() { return String::newString("§a"); }) - .property("Aqua", []() { return String::newString("§b"); }) - .property("Red", []() { return String::newString("§c"); }) - .property("LightPurple", []() { return String::newString("§d"); }) - .property("Yellow", []() { return String::newString("§e"); }) - .property("White", []() { return String::newString("§f"); }) - .property("MinecoinGold", []() { return String::newString("§g"); }) - .property("Bold", []() { return String::newString("§l"); }) - .property("Italics", []() { return String::newString("§o"); }) - .property("Underline", []() { return String::newString("§n"); }) - .property("StrikeThrough", []() { return String::newString("§m"); }) - .property("Random", []() { return String::newString("§k"); }) - .property("Clear", []() { return String::newString("§r"); }) - .build(); \ No newline at end of file +ClassDefine TextClassBuilder = defineClass("Format") + .property("Black", []() { return String::newString("§0"); }) + .property("DarkBlue", []() { return String::newString("§1"); }) + .property("DarkGreen", []() { return String::newString("§2"); }) + .property("DarkAqua", []() { return String::newString("§3"); }) + .property("DarkRed", []() { return String::newString("§4"); }) + .property("DarkPurple", []() { return String::newString("§5"); }) + .property("Gold", []() { return String::newString("§6"); }) + .property("Gray", []() { return String::newString("§7"); }) + .property("DarkGray", []() { return String::newString("§8"); }) + .property("Blue", []() { return String::newString("§9"); }) + .property("Green", []() { return String::newString("§a"); }) + .property("Aqua", []() { return String::newString("§b"); }) + .property("Red", []() { return String::newString("§c"); }) + .property("LightPurple", []() { return String::newString("§d"); }) + .property("Yellow", []() { return String::newString("§e"); }) + .property("White", []() { return String::newString("§f"); }) + .property("MinecoinGold", []() { return String::newString("§g"); }) + .property("Bold", []() { return String::newString("§l"); }) + .property("Italics", []() { return String::newString("§o"); }) + .property("Underline", []() { return String::newString("§n"); }) + .property("StrikeThrough", []() { return String::newString("§m"); }) + .property("Random", []() { return String::newString("§k"); }) + .property("Clear", []() { return String::newString("§r"); }) + .build(); \ No newline at end of file diff --git a/src/api/GlobalNativePointer.cpp b/src/api/GlobalNativePointer.cpp index 8858f1f5..046169b9 100644 --- a/src/api/GlobalNativePointer.cpp +++ b/src/api/GlobalNativePointer.cpp @@ -4,58 +4,48 @@ #include "mc/server/common/commands/AllowListCommand.h" #include "mc/world/Minecraft.h" -Local GlobalNativePointer::getLevelPtr(const Arguments &args) { - return NativePointer::newNativePointer(ll::service::getLevel()); +Local GlobalNativePointer::getLevelPtr(const Arguments& args) { + return NativePointer::newNativePointer(ll::service::getLevel()); } -Local GlobalNativePointer::getMinecraftPtr(const Arguments &args) { - return NativePointer::newNativePointer(ll::service::getMinecraft()); +Local GlobalNativePointer::getMinecraftPtr(const Arguments& args) { + return NativePointer::newNativePointer(ll::service::getMinecraft()); } -Local -GlobalNativePointer::getServerNetworkHandlerPtr(const Arguments &args) { - return NativePointer::newNativePointer( - ll::service::getServerNetworkHandler()); +Local GlobalNativePointer::getServerNetworkHandlerPtr(const Arguments& args) { + return NativePointer::newNativePointer(ll::service::getServerNetworkHandler()); } -Local -GlobalNativePointer::getMinecraftCommandsPtr(const Arguments &args) { - return NativePointer::newNativePointer( - &ll::service::getMinecraft()->getCommands()); +Local GlobalNativePointer::getMinecraftCommandsPtr(const Arguments& args) { + return NativePointer::newNativePointer(&ll::service::getMinecraft()->getCommands()); } -Local GlobalNativePointer::getLevelStoragePtr(const Arguments &args) { - return NativePointer::newNativePointer( - &ll::service::getLevel()->getLevelStorage()); +Local GlobalNativePointer::getLevelStoragePtr(const Arguments& args) { + return NativePointer::newNativePointer(&ll::service::getLevel()->getLevelStorage()); } -Local GlobalNativePointer::getDBStoragePtr(const Arguments &args) { - return NativePointer::newNativePointer( - &ll::service::getLevel()->getLevelStorage()); +Local GlobalNativePointer::getDBStoragePtr(const Arguments& args) { + return NativePointer::newNativePointer(&ll::service::getLevel()->getLevelStorage()); } -Local -GlobalNativePointer::getRakNetServerLocatorPtr(const Arguments &args) { - return NativePointer::newNativePointer( - &ll::service::getNetworkSystem()->getServerLocator()); +Local GlobalNativePointer::getRakNetServerLocatorPtr(const Arguments& args) { + return NativePointer::newNativePointer(&ll::service::getNetworkSystem()->getServerLocator()); } -Local GlobalNativePointer::getRakNetRakPeerPtr(const Arguments &args) { - return NativePointer::newNativePointer(ll::service::getRakPeer()); +Local GlobalNativePointer::getRakNetRakPeerPtr(const Arguments& args) { + return NativePointer::newNativePointer(ll::service::getRakPeer()); } -Local GlobalNativePointer::getScoreboardPtr(const Arguments &args) { - return NativePointer::newNativePointer( - &ll::service::getLevel()->getScoreboard()); +Local GlobalNativePointer::getScoreboardPtr(const Arguments& args) { + return NativePointer::newNativePointer(&ll::service::getLevel()->getScoreboard()); } -Local GlobalNativePointer::getAllowListFilePtr(const Arguments &args) { - return NativePointer::newNativePointer(AllowListCommand::$mAllowListFile()); +Local GlobalNativePointer::getAllowListFilePtr(const Arguments& args) { + return NativePointer::newNativePointer(AllowListCommand::$mAllowListFile()); } -Local -GlobalNativePointer::getPropertiesSettingsPtr(const Arguments &args) { - return NativePointer::newNativePointer(ll::service::getPropertiesSettings()); +Local GlobalNativePointer::getPropertiesSettingsPtr(const Arguments& args) { + return NativePointer::newNativePointer(ll::service::getPropertiesSettings()); } ClassDefine GlobalNativePointerBuilder = @@ -63,17 +53,13 @@ ClassDefine GlobalNativePointerBuilder = .constructor() .function("Level", &GlobalNativePointer::getLevelPtr) .function("Minecraft", &GlobalNativePointer::getMinecraftPtr) - .function("ServerNetworkHandler", - &GlobalNativePointer::getServerNetworkHandlerPtr) - .function("MinecraftCommands", - &GlobalNativePointer::getMinecraftCommandsPtr) + .function("ServerNetworkHandler", &GlobalNativePointer::getServerNetworkHandlerPtr) + .function("MinecraftCommands", &GlobalNativePointer::getMinecraftCommandsPtr) .function("LevelStorage", &GlobalNativePointer::getLevelStoragePtr) .function("DBStorage", &GlobalNativePointer::getDBStoragePtr) - .function("RakNetServerLocator", - &GlobalNativePointer::getRakNetServerLocatorPtr) + .function("RakNetServerLocator", &GlobalNativePointer::getRakNetServerLocatorPtr) .function("RakNetRakPeer", &GlobalNativePointer::getRakNetRakPeerPtr) .function("Scoreboard", &GlobalNativePointer::getScoreboardPtr) .function("AllowListFile", &GlobalNativePointer::getAllowListFilePtr) - .function("PropertiesSettings", - &GlobalNativePointer::getPropertiesSettingsPtr) + .function("PropertiesSettings", &GlobalNativePointer::getPropertiesSettingsPtr) .build(); diff --git a/src/api/GuiAPI.cpp b/src/api/GuiAPI.cpp index f71086c9..bc7b7c39 100644 --- a/src/api/GuiAPI.cpp +++ b/src/api/GuiAPI.cpp @@ -14,13 +14,12 @@ //////////////////// Class Definition //////////////////// -ClassDefine SimpleFormClassBuilder = - defineClass("LLSE_SimpleForm") - .constructor(nullptr) - .instanceFunction("setTitle", &SimpleFormClass::setTitle) - .instanceFunction("setContent", &SimpleFormClass::setContent) - .instanceFunction("addButton", &SimpleFormClass::addButton) - .build(); +ClassDefine SimpleFormClassBuilder = defineClass("LLSE_SimpleForm") + .constructor(nullptr) + .instanceFunction("setTitle", &SimpleFormClass::setTitle) + .instanceFunction("setContent", &SimpleFormClass::setContent) + .instanceFunction("addButton", &SimpleFormClass::addButton) + .build(); ClassDefine CustomFormClassBuilder = defineClass("LLSE_CustomForm") @@ -36,276 +35,241 @@ ClassDefine CustomFormClassBuilder = //////////////////// Simple Form //////////////////// -SimpleFormClass::SimpleFormClass() - : ScriptClass(ScriptClass::ConstructFromCpp{}), - form("", "") {} +SimpleFormClass::SimpleFormClass() : ScriptClass(ScriptClass::ConstructFromCpp{}), form("", "") {} // 生成函数 Local SimpleFormClass::newForm() { - auto newp = new SimpleFormClass(); - return newp->getScriptObject(); + auto newp = new SimpleFormClass(); + return newp->getScriptObject(); } -ll::form::SimpleForm *SimpleFormClass::extract(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine() - ->getNativeInstance(v) - ->get(); - else - return nullptr; +ll::form::SimpleForm* SimpleFormClass::extract(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v)->get(); + else return nullptr; } -void SimpleFormClass::sendForm(ll::form::SimpleForm *form, Player *player, - script::Local &callback) { - script::Global callbackFunc{callback}; - - form->sendTo(*player, [engine{EngineScope::currentEngine()}, - callback{std::move(callbackFunc)}](Player &pl, - int chosen) { - if ((ll::getServerStatus() != ll::ServerStatus::Running)) - return; - if (!EngineManager::isValid(engine)) - return; - if (callback.isEmpty()) - return; - - EngineScope scope(engine); - try { - if (chosen < 0) - callback.get().call({}, PlayerClass::newPlayer(&pl), Local()); - else - callback.get().call({}, PlayerClass::newPlayer(&pl), - Number::newNumber(chosen)); - } - CATCH_WITHOUT_RETURN("Fail in form callback!") - }); +void SimpleFormClass::sendForm(ll::form::SimpleForm* form, Player* player, script::Local& callback) { + script::Global callbackFunc{callback}; + + form->sendTo( + *player, + [engine{EngineScope::currentEngine()}, callback{std::move(callbackFunc)}](Player& pl, int chosen) { + if ((ll::getServerStatus() != ll::ServerStatus::Running)) return; + if (!EngineManager::isValid(engine)) return; + if (callback.isEmpty()) return; + + EngineScope scope(engine); + try { + if (chosen < 0) callback.get().call({}, PlayerClass::newPlayer(&pl), Local()); + else callback.get().call({}, PlayerClass::newPlayer(&pl), Number::newNumber(chosen)); + } + CATCH_WITHOUT_RETURN("Fail in form callback!") + } + ); } // 成员函数 -Local SimpleFormClass::setTitle(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - form.setTitle(args[0].toStr()); - return this->getScriptObject(); - } - CATCH("Fail in setTitle!") +Local SimpleFormClass::setTitle(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + form.setTitle(args[0].toStr()); + return this->getScriptObject(); + } + CATCH("Fail in setTitle!") } -Local SimpleFormClass::setContent(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local SimpleFormClass::setContent(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - form.setContent(args[0].toStr()); - return this->getScriptObject(); - } - CATCH("Fail in setTitle!") + try { + form.setContent(args[0].toStr()); + return this->getScriptObject(); + } + CATCH("Fail in setTitle!") } -Local SimpleFormClass::addButton(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - if (args.size() >= 2) - CHECK_ARG_TYPE(args[1], ValueKind::kString); - - try { - string image = args.size() >= 2 ? args[1].toStr() : ""; - form.appendButton(args[0].toStr(), image); - return this->getScriptObject(); - } - CATCH("Fail in addButton!") +Local SimpleFormClass::addButton(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + if (args.size() >= 2) CHECK_ARG_TYPE(args[1], ValueKind::kString); + + try { + string image = args.size() >= 2 ? args[1].toStr() : ""; + form.appendButton(args[0].toStr(), image); + return this->getScriptObject(); + } + CATCH("Fail in addButton!") } //////////////////// Custom Form //////////////////// -CustomFormClass::CustomFormClass() - : ScriptClass(ScriptClass::ConstructFromCpp{}), form("") {} +CustomFormClass::CustomFormClass() : ScriptClass(ScriptClass::ConstructFromCpp{}), form("") {} // 生成函数 Local CustomFormClass::newForm() { - auto newp = new CustomFormClass(); - return newp->getScriptObject(); + auto newp = new CustomFormClass(); + return newp->getScriptObject(); } -ll::form::CustomForm *CustomFormClass::extract(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine() - ->getNativeInstance(v) - ->get(); - else - return nullptr; +ll::form::CustomForm* CustomFormClass::extract(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v)->get(); + else return nullptr; } // 成员函数 -void CustomFormClass::sendForm(ll::form::CustomForm *form, Player *player, - script::Local &callback) { - script::Global callbackFunc{callback}; - - form->sendTo(*player, [engine{EngineScope::currentEngine()}, - callback{std::move(callbackFunc)}]( - Player &pl, - ll::form::CustomFormResult const &data) { - if ((ll::getServerStatus() != ll::ServerStatus::Running)) - return; - if (!EngineManager::isValid(engine)) - return; - if (callback.isEmpty()) - return; - - EngineScope scope(engine); +void CustomFormClass::sendForm(ll::form::CustomForm* form, Player* player, script::Local& callback) { + script::Global callbackFunc{callback}; + + form->sendTo( + *player, + [engine{EngineScope::currentEngine()}, + callback{std::move(callbackFunc)}](Player& pl, ll::form::CustomFormResult const& data) { + if ((ll::getServerStatus() != ll::ServerStatus::Running)) return; + if (!EngineManager::isValid(engine)) return; + if (callback.isEmpty()) return; + + EngineScope scope(engine); + try { + nlohmann::ordered_json result; + for (auto& [k, v] : data) { + std::visit( + [&](auto&& val) { + if constexpr (!std::is_same_v, std::monostate>) { + result[k] = val; + } else { + result[k] = nullptr; + } + }, + v + ); + } + callback.get().call({}, PlayerClass::newPlayer(&pl), JsonToValue(result)); + } + CATCH_WITHOUT_RETURN("Fail in form callback!") + } + ); +} + +Local CustomFormClass::setTitle(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + CHECK_ARG_TYPE(args[0], ValueKind::kString) + try { - nlohmann::ordered_json result; - for (auto &[k, v] : data) { - std::visit( - [&](auto &&val) { - if constexpr (!std::is_same_v, - std::monostate>) { - result[k] = val; - } else { - result[k] = nullptr; - } - }, - v); - } - callback.get().call({}, PlayerClass::newPlayer(&pl), JsonToValue(result)); + form.setTitle(args[0].toStr()); + return this->getScriptObject(); } - CATCH_WITHOUT_RETURN("Fail in form callback!") - }); + CATCH("Fail in setTitle!") } -Local CustomFormClass::setTitle(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - CHECK_ARG_TYPE(args[0], ValueKind::kString) +Local CustomFormClass::addLabel(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + CHECK_ARG_TYPE(args[0], ValueKind::kString) - try { - form.setTitle(args[0].toStr()); - return this->getScriptObject(); - } - CATCH("Fail in setTitle!") + try { + form.appendLabel(args[0].toStr()); + return this->getScriptObject(); + } + CATCH("Fail in addLabel!") } -Local CustomFormClass::addLabel(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - CHECK_ARG_TYPE(args[0], ValueKind::kString) +Local CustomFormClass::addInput(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + CHECK_ARG_TYPE(args[0], ValueKind::kString) + if (args.size() >= 2) CHECK_ARG_TYPE(args[1], ValueKind::kString); + if (args.size() >= 3) CHECK_ARG_TYPE(args[2], ValueKind::kString); - try { - form.appendLabel(args[0].toStr()); - return this->getScriptObject(); - } - CATCH("Fail in addLabel!") -} + try { + string placeholder = args.size() >= 2 ? args[1].toStr() : ""; + string def = args.size() >= 3 ? args[2].toStr() : ""; -Local CustomFormClass::addInput(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - CHECK_ARG_TYPE(args[0], ValueKind::kString) - if (args.size() >= 2) - CHECK_ARG_TYPE(args[1], ValueKind::kString); - if (args.size() >= 3) - CHECK_ARG_TYPE(args[2], ValueKind::kString); - - try { - string placeholder = args.size() >= 2 ? args[1].toStr() : ""; - string def = args.size() >= 3 ? args[2].toStr() : ""; - - form.appendInput(args[0].toStr(), args[0].toStr(), placeholder, def); - return this->getScriptObject(); - } - CATCH("Fail in addInput!") + form.appendInput(args[0].toStr(), args[0].toStr(), placeholder, def); + return this->getScriptObject(); + } + CATCH("Fail in addInput!") } -Local CustomFormClass::addSwitch(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - CHECK_ARG_TYPE(args[0], ValueKind::kString) - if (args.size() >= 2) - CHECK_ARG_TYPE(args[1], ValueKind::kBoolean); +Local CustomFormClass::addSwitch(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + CHECK_ARG_TYPE(args[0], ValueKind::kString) + if (args.size() >= 2) CHECK_ARG_TYPE(args[1], ValueKind::kBoolean); - try { - bool def = args.size() >= 2 ? args[1].asBoolean().value() : false; + try { + bool def = args.size() >= 2 ? args[1].asBoolean().value() : false; - form.appendToggle(args[0].toStr(), args[0].toStr(), def); - return this->getScriptObject(); - } - CATCH("Fail in addSwitch!") + form.appendToggle(args[0].toStr(), args[0].toStr(), def); + return this->getScriptObject(); + } + CATCH("Fail in addSwitch!") } -Local CustomFormClass::addDropdown(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2) - CHECK_ARG_TYPE(args[0], ValueKind::kString) - CHECK_ARG_TYPE(args[1], ValueKind::kArray); - if (args.size() >= 3) - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); +Local CustomFormClass::addDropdown(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2) + CHECK_ARG_TYPE(args[0], ValueKind::kString) + CHECK_ARG_TYPE(args[1], ValueKind::kArray); + if (args.size() >= 3) CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - try { - auto optionsArr = args[1].asArray(); - vector options; - for (int i = 0; i < optionsArr.size(); ++i) - options.push_back(optionsArr.get(i).toStr()); + try { + auto optionsArr = args[1].asArray(); + vector options; + for (int i = 0; i < optionsArr.size(); ++i) options.push_back(optionsArr.get(i).toStr()); - int def = args.size() >= 3 ? args[2].asNumber().toInt32() : 0; + int def = args.size() >= 3 ? args[2].asNumber().toInt32() : 0; - form.appendDropdown(args[0].toStr(), args[0].toStr(), options, def); - return this->getScriptObject(); - } - CATCH("Fail in addDropdown!") + form.appendDropdown(args[0].toStr(), args[0].toStr(), options, def); + return this->getScriptObject(); + } + CATCH("Fail in addDropdown!") } -Local CustomFormClass::addSlider(const Arguments &args) { - CHECK_ARGS_COUNT(args, 3) - CHECK_ARG_TYPE(args[0], ValueKind::kString) - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - if (args.size() >= 4) - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - if (args.size() >= 5) - CHECK_ARG_TYPE(args[4], ValueKind::kNumber); - - try { - int minValue = args[1].asNumber().toInt32(); - int maxValue = args[2].asNumber().toInt32(); - if (minValue >= maxValue) - maxValue = minValue + 1; - - int step = args.size() >= 4 ? args[3].asNumber().toInt32() : 1; - int defValue = args.size() >= 5 ? args[4].asNumber().toInt32() : minValue; - if (defValue < minValue || defValue > maxValue) - defValue = minValue; - - form.appendSlider(args[0].toStr(), args[0].toStr(), minValue, maxValue, - step, defValue); - return this->getScriptObject(); - } - CATCH("Fail in addSlider!") +Local CustomFormClass::addSlider(const Arguments& args) { + CHECK_ARGS_COUNT(args, 3) + CHECK_ARG_TYPE(args[0], ValueKind::kString) + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + if (args.size() >= 4) CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + if (args.size() >= 5) CHECK_ARG_TYPE(args[4], ValueKind::kNumber); + + try { + int minValue = args[1].asNumber().toInt32(); + int maxValue = args[2].asNumber().toInt32(); + if (minValue >= maxValue) maxValue = minValue + 1; + + int step = args.size() >= 4 ? args[3].asNumber().toInt32() : 1; + int defValue = args.size() >= 5 ? args[4].asNumber().toInt32() : minValue; + if (defValue < minValue || defValue > maxValue) defValue = minValue; + + form.appendSlider(args[0].toStr(), args[0].toStr(), minValue, maxValue, step, defValue); + return this->getScriptObject(); + } + CATCH("Fail in addSlider!") } -Local CustomFormClass::addStepSlider(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2) - CHECK_ARG_TYPE(args[0], ValueKind::kString) - CHECK_ARG_TYPE(args[1], ValueKind::kArray); - if (args.size() >= 3) - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); +Local CustomFormClass::addStepSlider(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2) + CHECK_ARG_TYPE(args[0], ValueKind::kString) + CHECK_ARG_TYPE(args[1], ValueKind::kArray); + if (args.size() >= 3) CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - try { - auto stepsArr = args[1].asArray(); - vector steps; - for (int i = 0; i < stepsArr.size(); ++i) - steps.push_back(stepsArr.get(i).toStr()); + try { + auto stepsArr = args[1].asArray(); + vector steps; + for (int i = 0; i < stepsArr.size(); ++i) steps.push_back(stepsArr.get(i).toStr()); - int defIndex = args.size() >= 3 ? args[2].asNumber().toInt32() : 0; + int defIndex = args.size() >= 3 ? args[2].asNumber().toInt32() : 0; - form.appendStepSlider(args[0].toStr(), args[0].toStr(), steps, defIndex); - return this->getScriptObject(); - } - CATCH("Fail in addStepSlider!") + form.appendStepSlider(args[0].toStr(), args[0].toStr(), steps, defIndex); + return this->getScriptObject(); + } + CATCH("Fail in addStepSlider!") } //////////////////// APIs //////////////////// -Local McClass::newSimpleForm(const Arguments &args) { - return SimpleFormClass::newForm(); -} +Local McClass::newSimpleForm(const Arguments& args) { return SimpleFormClass::newForm(); } -Local McClass::newCustomForm(const Arguments &args) { - return CustomFormClass::newForm(); -} +Local McClass::newCustomForm(const Arguments& args) { return CustomFormClass::newForm(); } diff --git a/src/api/GuiAPI.h b/src/api/GuiAPI.h index db5840bf..0a40004c 100644 --- a/src/api/GuiAPI.h +++ b/src/api/GuiAPI.h @@ -9,44 +9,42 @@ class SimpleFormClass : public ScriptClass { private: - ll::form::SimpleForm form; + ll::form::SimpleForm form; public: - SimpleFormClass(); + SimpleFormClass(); - ll::form::SimpleForm *get() { return &form; } + ll::form::SimpleForm* get() { return &form; } - static Local newForm(); - static ll::form::SimpleForm *extract(Local v); - static void sendForm(ll::form::SimpleForm *form, Player *player, - script::Local &callback); + static Local newForm(); + static ll::form::SimpleForm* extract(Local v); + static void sendForm(ll::form::SimpleForm* form, Player* player, script::Local& callback); - Local setTitle(const Arguments &args); - Local setContent(const Arguments &args); - Local addButton(const Arguments &args); + Local setTitle(const Arguments& args); + Local setContent(const Arguments& args); + Local addButton(const Arguments& args); }; extern ClassDefine SimpleFormClassBuilder; class CustomFormClass : public ScriptClass { private: - ll::form::CustomForm form; + ll::form::CustomForm form; public: - CustomFormClass(); - - ll::form::CustomForm *get() { return &form; } - - static Local newForm(); - static ll::form::CustomForm *extract(Local v); - static void sendForm(ll::form::CustomForm *form, Player *player, - script::Local &callback); - - Local setTitle(const Arguments &args); - Local addLabel(const Arguments &args); - Local addInput(const Arguments &args); - Local addSwitch(const Arguments &args); - Local addDropdown(const Arguments &args); - Local addSlider(const Arguments &args); - Local addStepSlider(const Arguments &args); + CustomFormClass(); + + ll::form::CustomForm* get() { return &form; } + + static Local newForm(); + static ll::form::CustomForm* extract(Local v); + static void sendForm(ll::form::CustomForm* form, Player* player, script::Local& callback); + + Local setTitle(const Arguments& args); + Local addLabel(const Arguments& args); + Local addInput(const Arguments& args); + Local addSwitch(const Arguments& args); + Local addDropdown(const Arguments& args); + Local addSlider(const Arguments& args); + Local addStepSlider(const Arguments& args); }; extern ClassDefine CustomFormClassBuilder; \ No newline at end of file diff --git a/src/api/InternationalAPI.cpp b/src/api/InternationalAPI.cpp index a6edc667..6e1f6bb4 100644 --- a/src/api/InternationalAPI.cpp +++ b/src/api/InternationalAPI.cpp @@ -3,127 +3,129 @@ #include #include -void FormatHelper(std::vector> &args, - const std::vector &names, bool enableObject, - fmt::dynamic_format_arg_store &s, - std::vector &delList) { - for (auto i = 0; i < args.size(); ++i) { - auto &arg = args[i]; - char *name = nullptr; - if (i < names.size()) { - name = names[i]; - } - switch (arg.getKind()) { - case ValueKind::kBoolean: { - if (!name) { - s.push_back(arg.asBoolean().value()); - } else { - s.push_back(fmt::arg(name, arg.asBoolean().value())); - } - break; - } - case ValueKind::kNumber: { - if (CheckIsFloat(arg)) { - if (!name) { - s.push_back(arg.asNumber().toDouble()); - } else { - s.push_back(fmt::arg(name, arg.asNumber().toDouble())); +void FormatHelper( + std::vector>& args, + const std::vector& names, + bool enableObject, + fmt::dynamic_format_arg_store& s, + std::vector& delList +) { + for (auto i = 0; i < args.size(); ++i) { + auto& arg = args[i]; + char* name = nullptr; + if (i < names.size()) { + name = names[i]; + } + switch (arg.getKind()) { + case ValueKind::kBoolean: { + if (!name) { + s.push_back(arg.asBoolean().value()); + } else { + s.push_back(fmt::arg(name, arg.asBoolean().value())); + } + break; + } + case ValueKind::kNumber: { + if (CheckIsFloat(arg)) { + if (!name) { + s.push_back(arg.asNumber().toDouble()); + } else { + s.push_back(fmt::arg(name, arg.asNumber().toDouble())); + } + } else { + if (!name) { + s.push_back(arg.asNumber().toInt64()); + } else { + s.push_back(fmt::arg(name, arg.asNumber().toInt64())); + } + } + break; + } + case ValueKind::kString: { + if (!name) { + s.push_back(arg.toStr()); + } else { + s.push_back(fmt::arg(name, arg.toStr())); + } + break; + } + case ValueKind::kArray: { + if (enableObject) { + auto arr = arg.asArray(); + std::vector> vals; + for (auto j = 0ULL; j < arr.size(); ++j) { + vals.push_back(arr.get(j)); + } + FormatHelper(vals, {}, false, s, delList); + break; + } + // Follow + } + case ValueKind::kObject: { + if (enableObject) { + auto obj = arg.asObject(); + auto keys = obj.getKeys(); + std::vector> vals; + std::vector nextNames; + for (auto j = 0ULL; j < keys.size(); ++j) { + auto key = keys[j].toString(); + // #if __cplusplus <= 201703L + char* cName = new char[key.size() + 1]; + std::memset(cName, 0, key.size() + 1); + // #else + // char *cName = new char[key.size() + 1](0); + // #endif + std::copy(key.begin(), key.end(), cName); + delList.push_back(cName); + nextNames.push_back(cName); + vals.push_back(obj.get(keys[j])); + } + FormatHelper(vals, nextNames, false, s, delList); + break; + } + // Follow + } + default: { + auto str = ValueToString(arg); + if (!name) { + s.push_back(str); + } else { + s.push_back(fmt::arg(name, str)); + } + break; } - } else { - if (!name) { - s.push_back(arg.asNumber().toInt64()); - } else { - s.push_back(fmt::arg(name, arg.asNumber().toInt64())); } - } - break; - } - case ValueKind::kString: { - if (!name) { - s.push_back(arg.toStr()); - } else { - s.push_back(fmt::arg(name, arg.toStr())); - } - break; - } - case ValueKind::kArray: { - if (enableObject) { - auto arr = arg.asArray(); - std::vector> vals; - for (auto j = 0ULL; j < arr.size(); ++j) { - vals.push_back(arr.get(j)); - } - FormatHelper(vals, {}, false, s, delList); - break; - } - // Follow - } - case ValueKind::kObject: { - if (enableObject) { - auto obj = arg.asObject(); - auto keys = obj.getKeys(); - std::vector> vals; - std::vector nextNames; - for (auto j = 0ULL; j < keys.size(); ++j) { - auto key = keys[j].toString(); - // #if __cplusplus <= 201703L - char *cName = new char[key.size() + 1]; - std::memset(cName, 0, key.size() + 1); - // #else - // char *cName = new char[key.size() + 1](0); - // #endif - std::copy(key.begin(), key.end(), cName); - delList.push_back(cName); - nextNames.push_back(cName); - vals.push_back(obj.get(keys[j])); - } - FormatHelper(vals, nextNames, false, s, delList); - break; - } - // Follow - } - default: { - auto str = ValueToString(arg); - if (!name) { - s.push_back(str); - } else { - s.push_back(fmt::arg(name, str)); - } - break; - } } - } } -Local TrFormat(const Arguments &args, size_t offset, std::string key, - const std::string &localeName = "") { - try { - size_t argsLength = args.size() - offset; - auto i18n = ENGINE_OWN_DATA()->i18n; - if (i18n) { - key = i18n->get(key, localeName); - } - // realFormatStr = FixCurlyBracket(realFormatStr); - if (0ULL == argsLength) { - // Avoid fmt if only one argument - return String::newString(key); - } else { - fmt::dynamic_format_arg_store s; - std::vector delList; - std::vector> vals; - for (auto i = offset; i < args.size(); ++i) { - vals.push_back(args[i]); - } - FormatHelper(vals, {}, true, s, delList); - auto result = String::newString(fmt::vformat(key, s)); - for (auto &ptr : delList) { - delete[] ptr; - } - return result; +Local TrFormat(const Arguments& args, size_t offset, std::string key, const std::string& localeName = "") { + try { + size_t argsLength = args.size() - offset; + auto i18n = ENGINE_OWN_DATA()->i18n; + if (i18n) { + key = i18n->get(key, localeName); + } + // realFormatStr = FixCurlyBracket(realFormatStr); + if (0ULL == argsLength) { + // Avoid fmt if only one argument + return String::newString(key); + } else { + fmt::dynamic_format_arg_store s; + std::vector delList; + std::vector> vals; + for (auto i = offset; i < args.size(); ++i) { + vals.push_back(args[i]); + } + FormatHelper(vals, {}, true, s, delList); + auto result = String::newString(fmt::vformat(key, s)); + for (auto& ptr : delList) { + delete[] ptr; + } + return result; + } + } catch (const fmt::format_error&) { + return String::newString(key); } - } catch (const fmt::format_error &) { - return String::newString(key); - } } ClassDefine I18nClassBuilder = defineClass("i18n") @@ -133,105 +135,102 @@ ClassDefine I18nClassBuilder = defineClass("i18n") .function("load", &I18nClass::load) .build(); -Local I18nClass::tr(const Arguments &args) { - CHECK_ARGS_LEAST_COUNT(1); // At least 1 - CHECK_ARG_TYPE(0, kString); +Local I18nClass::tr(const Arguments& args) { + CHECK_ARGS_LEAST_COUNT(1); // At least 1 + CHECK_ARG_TYPE(0, kString); - try { - return TrFormat(args, 1ULL, args[0].toStr()); - } - CATCH_AND_THROW; + try { + return TrFormat(args, 1ULL, args[0].toStr()); + } + CATCH_AND_THROW; } -Local I18nClass::trl(const Arguments &args) { - CHECK_ARGS_LEAST_COUNT(2); - CHECK_ARG_TYPE(0, kString); - CHECK_ARG_TYPE(1, kString); +Local I18nClass::trl(const Arguments& args) { + CHECK_ARGS_LEAST_COUNT(2); + CHECK_ARG_TYPE(0, kString); + CHECK_ARG_TYPE(1, kString); - try { - return TrFormat(args, 2ULL, args[1].toStr(), args[0].toStr()); - } - CATCH_AND_THROW; + try { + return TrFormat(args, 2ULL, args[1].toStr(), args[0].toStr()); + } + CATCH_AND_THROW; } -Local I18nClass::get(const Arguments &args) { - CHECK_ARGS_LEAST_COUNT(1); - CHECK_ARG_TYPE(0, kString); - if (args.size() == 2) { - CHECK_ARG_TYPE(1, kString); - } else { - CHECK_ARGS_COUNT(1); - } - - try { - auto key = args[0].toStr(); - std::string localeName{}; +Local I18nClass::get(const Arguments& args) { + CHECK_ARGS_LEAST_COUNT(1); + CHECK_ARG_TYPE(0, kString); if (args.size() == 2) { - localeName = args[1].toStr(); + CHECK_ARG_TYPE(1, kString); + } else { + CHECK_ARGS_COUNT(1); } - auto i18n = ENGINE_OWN_DATA()->i18n; - if (!i18n) { - throw Exception("I18n data has not been loaded yet!"); + + try { + auto key = args[0].toStr(); + std::string localeName{}; + if (args.size() == 2) { + localeName = args[1].toStr(); + } + auto i18n = ENGINE_OWN_DATA()->i18n; + if (!i18n) { + throw Exception("I18n data has not been loaded yet!"); + } + return String::newString(i18n->get(key, localeName)); } - return String::newString(i18n->get(key, localeName)); - } - CATCH_AND_THROW; + CATCH_AND_THROW; } -Local I18nClass::load(const Arguments &args) { - CHECK_ARGS_LEAST_COUNT(1); - CHECK_ARG_TYPE(0, kString); - if (args.size() > 1) { - CHECK_ARG_TYPE(1, kString); - } - if (args.size() > 2) { - CHECK_ARG_TYPE(2, kObject); - } - - try { - auto path = args[0].toStr(); - ll::i18n::I18N::LangData defaultLangData; - std::string defaultLocaleName; +Local I18nClass::load(const Arguments& args) { + CHECK_ARGS_LEAST_COUNT(1); + CHECK_ARG_TYPE(0, kString); if (args.size() > 1) { - defaultLocaleName = args[1].toStr(); + CHECK_ARG_TYPE(1, kString); } if (args.size() > 2) { - auto rawLangData = args[2].asObject(); - auto rawLangDataKeys = rawLangData.getKeys(); - for (auto i = 0ULL; i < rawLangDataKeys.size(); ++i) { - auto localeName = rawLangDataKeys[i].toString(); - auto val = rawLangData.get(rawLangDataKeys[i]); - if (val.getKind() != ValueKind::kObject) { - throw Exception("Value in LangData must be object"); - } - auto obj = val.asObject(); - ll::i18n::I18N::SubLangData data; - auto objKeys = obj.getKeys(); - for (auto j = 0ULL; j < objKeys.size(); ++j) { - auto str = obj.get(objKeys[j]); - if (str.getKind() != ValueKind::kString) { - throw Exception("Value in SubLangData must be string"); - } - data.emplace(objKeys[j].toString(), str.toStr()); - } - defaultLangData.emplace(localeName, data); - } + CHECK_ARG_TYPE(2, kObject); } - ll::i18n::I18N *res = nullptr; - if (path.ends_with('/') || path.ends_with('\\') || - std::filesystem::is_directory(path)) { // Directory - res = - new ll::i18n::MultiFileI18N(path, defaultLocaleName, defaultLangData); - } else { - res = new ll::i18n::SingleFileI18N(path, defaultLocaleName, - defaultLangData); - } - ENGINE_OWN_DATA()->i18n = res; - if (res) { - return Boolean::newBoolean(true); + try { + auto path = args[0].toStr(); + ll::i18n::I18N::LangData defaultLangData; + std::string defaultLocaleName; + if (args.size() > 1) { + defaultLocaleName = args[1].toStr(); + } + if (args.size() > 2) { + auto rawLangData = args[2].asObject(); + auto rawLangDataKeys = rawLangData.getKeys(); + for (auto i = 0ULL; i < rawLangDataKeys.size(); ++i) { + auto localeName = rawLangDataKeys[i].toString(); + auto val = rawLangData.get(rawLangDataKeys[i]); + if (val.getKind() != ValueKind::kObject) { + throw Exception("Value in LangData must be object"); + } + auto obj = val.asObject(); + ll::i18n::I18N::SubLangData data; + auto objKeys = obj.getKeys(); + for (auto j = 0ULL; j < objKeys.size(); ++j) { + auto str = obj.get(objKeys[j]); + if (str.getKind() != ValueKind::kString) { + throw Exception("Value in SubLangData must be string"); + } + data.emplace(objKeys[j].toString(), str.toStr()); + } + defaultLangData.emplace(localeName, data); + } + } + + ll::i18n::I18N* res = nullptr; + if (path.ends_with('/') || path.ends_with('\\') || std::filesystem::is_directory(path)) { // Directory + res = new ll::i18n::MultiFileI18N(path, defaultLocaleName, defaultLangData); + } else { + res = new ll::i18n::SingleFileI18N(path, defaultLocaleName, defaultLangData); + } + ENGINE_OWN_DATA()->i18n = res; + if (res) { + return Boolean::newBoolean(true); + } + return Boolean::newBoolean(false); } - return Boolean::newBoolean(false); - } - CATCH_AND_THROW; + CATCH_AND_THROW; } diff --git a/src/api/ItemAPI.cpp b/src/api/ItemAPI.cpp index 6f49c5eb..b1dd4d41 100644 --- a/src/api/ItemAPI.cpp +++ b/src/api/ItemAPI.cpp @@ -17,524 +17,509 @@ //////////////////// Class Definition //////////////////// -ClassDefine ItemClassBuilder = - defineClass("LLSE_Item") - .constructor(nullptr) - .instanceFunction("asPointer", &ItemClass::asPointer) - - .instanceProperty("name", &ItemClass::getName) - .instanceProperty("type", &ItemClass::getType) - .instanceProperty("id", &ItemClass::getId) - .instanceProperty("count", &ItemClass::getCount) - .instanceProperty("aux", &ItemClass::getAux) - .instanceProperty("damage", &ItemClass::getDamage) - .instanceProperty("lore", &ItemClass::getLore) - .instanceProperty("attackDamage", &ItemClass::getAttackDamage) - .instanceProperty("maxDamage", &ItemClass::getMaxDamage) - .instanceProperty("maxStackSize", &ItemClass::getMaxStackSize) - .instanceProperty("isArmorItem", &ItemClass::isArmorItem) - .instanceProperty("isBlock", &ItemClass::isBlock) - .instanceProperty("isDamageableItem", &ItemClass::isDamageableItem) - .instanceProperty("isDamaged", &ItemClass::isDamaged) - .instanceProperty("isEnchanted", &ItemClass::isEnchanted) - .instanceProperty("isEnchantingBook", &ItemClass::isEnchantingBook) - .instanceProperty("isFireResistant", &ItemClass::isFireResistant) - .instanceProperty("isFullStack", &ItemClass::isFullStack) - .instanceProperty("isGlint", &ItemClass::isGlint) - .instanceProperty("isHorseArmorItem", &ItemClass::isHorseArmorItem) - .instanceProperty("isLiquidClipItem", &ItemClass::isLiquidClipItem) - .instanceProperty("isMusicDiscItem", &ItemClass::isMusicDiscItem) - .instanceProperty("isOffhandItem", &ItemClass::isOffhandItem) - .instanceProperty("isPotionItem", &ItemClass::isPotionItem) - .instanceProperty("isStackable", &ItemClass::isStackable) - .instanceProperty("isWearableItem", &ItemClass::isWearableItem) - - .instanceFunction("set", &ItemClass::set) - .instanceFunction("clone", &ItemClass::clone) - .instanceFunction("isNull", &ItemClass::isNull) - .instanceFunction("setNull", &ItemClass::setNull) - .instanceFunction("setAux", &ItemClass::setAux) - .instanceFunction("setLore", &ItemClass::setLore) - .instanceFunction("setDisplayName", &ItemClass::setDisplayName) - .instanceFunction("setDamage", &ItemClass::setDamage) - .instanceFunction("setNbt", &ItemClass::setNbt) - .instanceFunction("getNbt", &ItemClass::getNbt) - - .instanceFunction("match", &ItemClass::match) - - // For Compatibility - .instanceFunction("setTag", &ItemClass::setNbt) - .instanceFunction("getTag", &ItemClass::getNbt) - .build(); +ClassDefine ItemClassBuilder = defineClass("LLSE_Item") + .constructor(nullptr) + .instanceFunction("asPointer", &ItemClass::asPointer) + + .instanceProperty("name", &ItemClass::getName) + .instanceProperty("type", &ItemClass::getType) + .instanceProperty("id", &ItemClass::getId) + .instanceProperty("count", &ItemClass::getCount) + .instanceProperty("aux", &ItemClass::getAux) + .instanceProperty("damage", &ItemClass::getDamage) + .instanceProperty("lore", &ItemClass::getLore) + .instanceProperty("attackDamage", &ItemClass::getAttackDamage) + .instanceProperty("maxDamage", &ItemClass::getMaxDamage) + .instanceProperty("maxStackSize", &ItemClass::getMaxStackSize) + .instanceProperty("isArmorItem", &ItemClass::isArmorItem) + .instanceProperty("isBlock", &ItemClass::isBlock) + .instanceProperty("isDamageableItem", &ItemClass::isDamageableItem) + .instanceProperty("isDamaged", &ItemClass::isDamaged) + .instanceProperty("isEnchanted", &ItemClass::isEnchanted) + .instanceProperty("isEnchantingBook", &ItemClass::isEnchantingBook) + .instanceProperty("isFireResistant", &ItemClass::isFireResistant) + .instanceProperty("isFullStack", &ItemClass::isFullStack) + .instanceProperty("isGlint", &ItemClass::isGlint) + .instanceProperty("isHorseArmorItem", &ItemClass::isHorseArmorItem) + .instanceProperty("isLiquidClipItem", &ItemClass::isLiquidClipItem) + .instanceProperty("isMusicDiscItem", &ItemClass::isMusicDiscItem) + .instanceProperty("isOffhandItem", &ItemClass::isOffhandItem) + .instanceProperty("isPotionItem", &ItemClass::isPotionItem) + .instanceProperty("isStackable", &ItemClass::isStackable) + .instanceProperty("isWearableItem", &ItemClass::isWearableItem) + + .instanceFunction("set", &ItemClass::set) + .instanceFunction("clone", &ItemClass::clone) + .instanceFunction("isNull", &ItemClass::isNull) + .instanceFunction("setNull", &ItemClass::setNull) + .instanceFunction("setAux", &ItemClass::setAux) + .instanceFunction("setLore", &ItemClass::setLore) + .instanceFunction("setDisplayName", &ItemClass::setDisplayName) + .instanceFunction("setDamage", &ItemClass::setDamage) + .instanceFunction("setNbt", &ItemClass::setNbt) + .instanceFunction("getNbt", &ItemClass::getNbt) + + .instanceFunction("match", &ItemClass::match) + + // For Compatibility + .instanceFunction("setTag", &ItemClass::setNbt) + .instanceFunction("getTag", &ItemClass::getNbt) + .build(); //////////////////// Classes //////////////////// -ItemClass::ItemClass(ItemStack *p) - : ScriptClass(ScriptClass::ConstructFromCpp{}), item(p) { - preloadData(); -} +ItemClass::ItemClass(ItemStack* p) : ScriptClass(ScriptClass::ConstructFromCpp{}), item(p) { preloadData(); } // 生成函数 -Local ItemClass::newItem(ItemStack *p) { - auto newp = new ItemClass(p); - return newp->getScriptObject(); +Local ItemClass::newItem(ItemStack* p) { + auto newp = new ItemClass(p); + return newp->getScriptObject(); } -ItemStack *ItemClass::extract(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine()->getNativeInstance(v)->get(); - else - return nullptr; +ItemStack* ItemClass::extract(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v)->get(); + else return nullptr; } // 成员函数 void ItemClass::preloadData() { - name = item->getCustomName(); - if (name.empty()) - name = item->getName(); + name = item->getCustomName(); + if (name.empty()) name = item->getName(); - type = item->getTypeName(); - id = item->getId(); - count = item->mCount; - aux = item->getAuxValue(); + type = item->getTypeName(); + id = item->getId(); + count = item->mCount; + aux = item->getAuxValue(); } Local ItemClass::getName() { - try { - // 已预加载 - return String::newString(name); - } - CATCH("Fail in GetItemName!"); + try { + // 已预加载 + return String::newString(name); + } + CATCH("Fail in GetItemName!"); } Local ItemClass::getType() { - try { - // 已预加载 - return String::newString(type); - } - CATCH("Fail in GetType!"); + try { + // 已预加载 + return String::newString(type); + } + CATCH("Fail in GetType!"); } Local ItemClass::getId() { - try { - // 已预加载 - return Number::newNumber(id); - } - CATCH("Fail in GetType!"); + try { + // 已预加载 + return Number::newNumber(id); + } + CATCH("Fail in GetType!"); } Local ItemClass::getCount() { - try { - // 已预加载 - return Number::newNumber(count); - } - CATCH("Fail in GetCount!"); + try { + // 已预加载 + return Number::newNumber(count); + } + CATCH("Fail in GetCount!"); } Local ItemClass::getAux() { - try { - // 已预加载 - return Number::newNumber(aux); - } - CATCH("Fail in GetAux!"); + try { + // 已预加载 + return Number::newNumber(aux); + } + CATCH("Fail in GetAux!"); } Local ItemClass::getDamage() { - try { - return Number::newNumber(item->getDamageValue()); - } - CATCH("Fail in GetDamage!"); + try { + return Number::newNumber(item->getDamageValue()); + } + CATCH("Fail in GetDamage!"); } Local ItemClass::getAttackDamage() { - try { - return Number::newNumber(item->getAttackDamage()); - } - CATCH("Fail in GetAttackDamage!"); + try { + return Number::newNumber(item->getAttackDamage()); + } + CATCH("Fail in GetAttackDamage!"); } Local ItemClass::getMaxDamage() { - try { - return Number::newNumber(item->getMaxDamage()); - } - CATCH("Fail in GetMaxDamage!"); + try { + return Number::newNumber(item->getMaxDamage()); + } + CATCH("Fail in GetMaxDamage!"); } Local ItemClass::getMaxStackSize() { - try { - return Number::newNumber(item->getMaxStackSize()); - } - CATCH("Fail in GetMaxStackSize!"); + try { + return Number::newNumber(item->getMaxStackSize()); + } + CATCH("Fail in GetMaxStackSize!"); } Local ItemClass::getLore() { - try { - std::vector loreArray = item->getCustomLore(); + try { + std::vector loreArray = item->getCustomLore(); - Local loreValueList = Array::newArray(); + Local loreValueList = Array::newArray(); - for (std::string lore : loreArray) { - loreValueList.add(String::newString(lore)); - } + for (std::string lore : loreArray) { + loreValueList.add(String::newString(lore)); + } - return loreValueList; - } - CATCH("Fail in GetLore!"); + return loreValueList; + } + CATCH("Fail in GetLore!"); } Local ItemClass::isArmorItem() { - try { - return Boolean::newBoolean(item->isArmorItem()); - } - CATCH("Fail in isArmorItem!"); + try { + return Boolean::newBoolean(item->isArmorItem()); + } + CATCH("Fail in isArmorItem!"); } Local ItemClass::isBlock() { - try { - return Boolean::newBoolean(item->isBlock()); - } - CATCH("Fail in isBlock!"); + try { + return Boolean::newBoolean(item->isBlock()); + } + CATCH("Fail in isBlock!"); } Local ItemClass::isDamageableItem() { - try { - return Boolean::newBoolean(item->isDamageableItem()); - } - CATCH("Fail in isDamageableItem!"); + try { + return Boolean::newBoolean(item->isDamageableItem()); + } + CATCH("Fail in isDamageableItem!"); } Local ItemClass::isDamaged() { - try { - return Boolean::newBoolean(item->isDamaged()); - } - CATCH("Fail in isDamaged!"); + try { + return Boolean::newBoolean(item->isDamaged()); + } + CATCH("Fail in isDamaged!"); } Local ItemClass::isEnchanted() { - try { - return Boolean::newBoolean(item->isEnchanted()); - } - CATCH("Fail in isEnchanted!"); + try { + return Boolean::newBoolean(item->isEnchanted()); + } + CATCH("Fail in isEnchanted!"); } Local ItemClass::isEnchantingBook() { - try { - return Boolean::newBoolean(item->isEnchantingBook()); - } - CATCH("Fail in isEnchantingBook!"); + try { + return Boolean::newBoolean(item->isEnchantingBook()); + } + CATCH("Fail in isEnchantingBook!"); } Local ItemClass::isFireResistant() { - try { - return Boolean::newBoolean(item->isFireResistant()); - } - CATCH("Fail in isFireResistant!"); + try { + return Boolean::newBoolean(item->isFireResistant()); + } + CATCH("Fail in isFireResistant!"); } Local ItemClass::isFullStack() { - try { - return Boolean::newBoolean(item->isFullStack()); - } - CATCH("Fail in isFullStack!"); + try { + return Boolean::newBoolean(item->isFullStack()); + } + CATCH("Fail in isFullStack!"); } Local ItemClass::isGlint() { - try { - return Boolean::newBoolean(item->isGlint()); - } - CATCH("Fail in isGlint!"); + try { + return Boolean::newBoolean(item->isGlint()); + } + CATCH("Fail in isGlint!"); } Local ItemClass::isHorseArmorItem() { - try { - return Boolean::newBoolean(item->isHorseArmorItem()); - } - CATCH("Fail in isHorseArmorItem!"); + try { + return Boolean::newBoolean(item->isHorseArmorItem()); + } + CATCH("Fail in isHorseArmorItem!"); } Local ItemClass::isLiquidClipItem() { - try { - return Boolean::newBoolean(item->isLiquidClipItem()); - } - CATCH("Fail in isLiquidClipItem!"); + try { + return Boolean::newBoolean(item->isLiquidClipItem()); + } + CATCH("Fail in isLiquidClipItem!"); } Local ItemClass::isMusicDiscItem() { - try { - return Boolean::newBoolean(item->getItem()->isMusicDisk()); - } - CATCH("Fail in isMusicDiscItem!"); + try { + return Boolean::newBoolean(item->getItem()->isMusicDisk()); + } + CATCH("Fail in isMusicDiscItem!"); } Local ItemClass::isOffhandItem() { - try { - return Boolean::newBoolean(item->isOffhandItem()); - } - CATCH("Fail in isOffhandItem!"); + try { + return Boolean::newBoolean(item->isOffhandItem()); + } + CATCH("Fail in isOffhandItem!"); } Local ItemClass::isPotionItem() { - try { - return Boolean::newBoolean(item->isPotionItem()); - } - CATCH("Fail in isPotionItem!"); + try { + return Boolean::newBoolean(item->isPotionItem()); + } + CATCH("Fail in isPotionItem!"); } Local ItemClass::isStackable() { - try { - return Boolean::newBoolean(item->isStackable()); - } - CATCH("Fail in isStackable!"); + try { + return Boolean::newBoolean(item->isStackable()); + } + CATCH("Fail in isStackable!"); } Local ItemClass::isWearableItem() { - try { - return Boolean::newBoolean(item->isWearableItem()); - } - CATCH("Fail in isWearableItem!"); + try { + return Boolean::newBoolean(item->isWearableItem()); + } + CATCH("Fail in isWearableItem!"); } -Local ItemClass::asPointer(const Arguments &args) { - try { - return NativePointer::newNativePointer(item); - } - CATCH("Fail in asPointer!"); +Local ItemClass::asPointer(const Arguments& args) { + try { + return NativePointer::newNativePointer(item); + } + CATCH("Fail in asPointer!"); } -Local ItemClass::set(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); +Local ItemClass::set(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); - try { - auto itemNew = ItemClass::extract(args[0]); - if (!itemNew) - return Local(); // Null + try { + auto itemNew = ItemClass::extract(args[0]); + if (!itemNew) return Local(); // Null - return Boolean::newBoolean(item = itemNew); - } - CATCH("Fail in set!"); + return Boolean::newBoolean(item = itemNew); + } + CATCH("Fail in set!"); } -Local ItemClass::clone(const Arguments &args) { - try { - auto item = get(); - if (!item) - return Local(); // Null - auto itemNew = new ItemStack(*item); - return ItemClass::newItem(itemNew); - } - CATCH("Fail in cloneItem!"); +Local ItemClass::clone(const Arguments& args) { + try { + auto item = get(); + if (!item) return Local(); // Null + auto itemNew = new ItemStack(*item); + return ItemClass::newItem(itemNew); + } + CATCH("Fail in cloneItem!"); } -Local ItemClass::isNull(const Arguments &args) { - try { - return Boolean::newBoolean(item->isNull()); - } - CATCH("Fail in isNull!"); +Local ItemClass::isNull(const Arguments& args) { + try { + return Boolean::newBoolean(item->isNull()); + } + CATCH("Fail in isNull!"); } -Local ItemClass::setNull(const Arguments &args) { - try { - item->setNull({}); - return Boolean::newBoolean(true); - } - CATCH("Fail in setNull!"); -} - -Local ItemClass::setAux(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - - try { - item->setAuxValue(args[0].toInt()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setAux!"); -} - -Local ItemClass::setLore(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kArray); - - try { - auto arr = args[0].asArray(); - std::vector lores; - for (int i = 0; i < arr.size(); ++i) { - auto value = arr.get(i); - if (value.getKind() == ValueKind::kString) - lores.push_back(value.asString().toString()); - } - if (lores.empty()) - return Boolean::newBoolean(false); - - item->setCustomLore(lores); - return Boolean::newBoolean(true); - } - CATCH("Fail in SetLore!"); -} - -Local ItemClass::setDisplayName(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - item->setCustomName(args[0].asString().toString()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setDisplayName!"); -} - -Local ItemClass::setDamage(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - - try { - if (item->isDamageableItem() && args[0].toInt() <= 32767) { - item->setDamageValue(args[0].toInt()); - return Boolean::newBoolean(true); - } else { - return Boolean::newBoolean(false); - } - } - CATCH("Fail in setDamage!"); -} - -Local ItemClass::getNbt(const Arguments &args) { - try { - return NbtCompoundClass::pack(std::move(item->save())); - } - CATCH("Fail in getNbt!"); -} - -Local ItemClass::setNbt(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - - try { - auto nbt = NbtCompoundClass::extract(args[0]); - if (!nbt) - return Local(); // Null - auto item = get(); - item->load(*nbt); - // update Pre Data - preloadData(); - return Boolean::newBoolean(true); - } - CATCH("Fail in setNbt!"); -} - -Local McClass::newItem(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - - try { - if (args[0].isString()) { - // name & count - if (args.size() >= 2 && args[1].isNumber()) { - string type = args[0].toStr(); - int cnt = args[1].toInt(); - - ItemStack *item = new ItemStack{type, cnt}; - if (!item) - return Local(); // Null - else - return ItemClass::newItem(item); - } else { - LOG_TOO_FEW_ARGS(); - return Local(); - } - } else { - CompoundTag *nbt = (CompoundTag *)NbtCompoundClass::extract(args[0]); - if (nbt) { - auto newItem = new ItemStack{ItemStack::EMPTY_ITEM}; - newItem->load(*nbt); - if (!newItem) - return Local(); // Null - else - return ItemClass::newItem(newItem); - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - } - } - CATCH("Fail in NewItem!"); -} - -Local McClass::spawnItem(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - - try { - FloatVec4 pos; - if (args.size() == 2) { - if (IsInstanceOf(args[1])) { - // IntPos - IntPos *posObj = IntPos::extractPos(args[1]); - if (posObj->dim < 0) - return Boolean::newBoolean(false); - else { - pos.x = posObj->x; - pos.y = posObj->y; - pos.z = posObj->z; - pos.dim = posObj->dim; +Local ItemClass::setNull(const Arguments& args) { + try { + item->setNull({}); + return Boolean::newBoolean(true); + } + CATCH("Fail in setNull!"); +} + +Local ItemClass::setAux(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + + try { + item->setAuxValue(args[0].toInt()); + return Boolean::newBoolean(true); + } + CATCH("Fail in setAux!"); +} + +Local ItemClass::setLore(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kArray); + + try { + auto arr = args[0].asArray(); + std::vector lores; + for (int i = 0; i < arr.size(); ++i) { + auto value = arr.get(i); + if (value.getKind() == ValueKind::kString) lores.push_back(value.asString().toString()); } - } else if (IsInstanceOf(args[1])) { - // FloatPos - FloatPos *posObj = FloatPos::extractPos(args[1]); - if (posObj->dim < 0) - return Boolean::newBoolean(false); - else { - pos = *posObj; + if (lores.empty()) return Boolean::newBoolean(false); + + item->setCustomLore(lores); + return Boolean::newBoolean(true); + } + CATCH("Fail in SetLore!"); +} + +Local ItemClass::setDisplayName(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + item->setCustomName(args[0].asString().toString()); + return Boolean::newBoolean(true); + } + CATCH("Fail in setDisplayName!"); +} + +Local ItemClass::setDamage(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + + try { + if (item->isDamageableItem() && args[0].toInt() <= 32767) { + item->setDamageValue(args[0].toInt()); + return Boolean::newBoolean(true); + } else { + return Boolean::newBoolean(false); } - } else { + } + CATCH("Fail in setDamage!"); +} + +Local ItemClass::getNbt(const Arguments& args) { + try { + return NbtCompoundClass::pack(std::move(item->save())); + } + CATCH("Fail in getNbt!"); +} + +Local ItemClass::setNbt(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + + try { + auto nbt = NbtCompoundClass::extract(args[0]); + if (!nbt) return Local(); // Null + auto item = get(); + item->load(*nbt); + // update Pre Data + preloadData(); + return Boolean::newBoolean(true); + } + CATCH("Fail in setNbt!"); +} + +Local McClass::newItem(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + + try { + if (args[0].isString()) { + // name & count + if (args.size() >= 2 && args[1].isNumber()) { + string type = args[0].toStr(); + int cnt = args[1].toInt(); + + ItemStack* item = new ItemStack{type, cnt}; + if (!item) return Local(); // Null + else return ItemClass::newItem(item); + } else { + LOG_TOO_FEW_ARGS(); + return Local(); + } + } else { + CompoundTag* nbt = (CompoundTag*)NbtCompoundClass::extract(args[0]); + if (nbt) { + auto newItem = new ItemStack{ItemStack::EMPTY_ITEM}; + newItem->load(*nbt); + if (!newItem) return Local(); // Null + else return ItemClass::newItem(newItem); + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + } + } + CATCH("Fail in NewItem!"); +} + +Local McClass::spawnItem(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + + try { + FloatVec4 pos; + if (args.size() == 2) { + if (IsInstanceOf(args[1])) { + // IntPos + IntPos* posObj = IntPos::extractPos(args[1]); + if (posObj->dim < 0) return Boolean::newBoolean(false); + else { + pos.x = posObj->x; + pos.y = posObj->y; + pos.z = posObj->z; + pos.dim = posObj->dim; + } + } else if (IsInstanceOf(args[1])) { + // FloatPos + FloatPos* posObj = FloatPos::extractPos(args[1]); + if (posObj->dim < 0) return Boolean::newBoolean(false); + else { + pos = *posObj; + } + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + } else if (args.size() == 5) { + // Number Pos + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + CHECK_ARG_TYPE(args[4], ValueKind::kNumber); + pos = { + args[1].asNumber().toFloat(), + args[2].asNumber().toFloat(), + args[3].asNumber().toFloat(), + args[4].toInt()}; + } else { + LOG_WRONG_ARGS_COUNT(); + return Local(); + } + + ItemStack* it = ItemClass::extract(args[0]); + if (it) { + // By Item + ; + ItemActor* entity = ll::service::getLevel()->getSpawner().spawnItem( + ll::service::getLevel()->getDimension(pos.dim)->getBlockSourceFromMainChunkSource(), + *it, + 0, + pos.getVec3(), + pos.dim + ); + if (!entity) return Local(); // Null + else return EntityClass::newEntity((Actor*)entity); + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + } + CATCH("Fail in SpawnItem!"); +} + +Local ItemClass::match(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kObject) + if (!IsInstanceOf(args[0])) { LOG_WRONG_ARG_TYPE(); - return Local(); - } - } else if (args.size() == 5) { - // Number Pos - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - CHECK_ARG_TYPE(args[4], ValueKind::kNumber); - pos = {args[1].asNumber().toFloat(), args[2].asNumber().toFloat(), - args[3].asNumber().toFloat(), args[4].toInt()}; - } else { - LOG_WRONG_ARGS_COUNT(); - return Local(); - } - - ItemStack *it = ItemClass::extract(args[0]); - if (it) { - // By Item - ; - ItemActor *entity = ll::service::getLevel()->getSpawner().spawnItem( - ll::service::getLevel() - ->getDimension(pos.dim) - ->getBlockSourceFromMainChunkSource(), - *it, 0, pos.getVec3(), pos.dim); - if (!entity) - return Local(); // Null - else - return EntityClass::newEntity((Actor *)entity); - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - } - CATCH("Fail in SpawnItem!"); -} - -Local ItemClass::match(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kObject) - if (!IsInstanceOf(args[0])) { - LOG_WRONG_ARG_TYPE(); - return Boolean::newBoolean(false); - } - - try { - ItemStackBase itemNew = *ItemClass::extract(args[0]); - if (!itemNew) - return Boolean::newBoolean(false); - - return Boolean::newBoolean(item->matchesItem(itemNew)); - } - CATCH("Fail in MatchItem!"); + return Boolean::newBoolean(false); + } + + try { + ItemStackBase itemNew = *ItemClass::extract(args[0]); + if (!itemNew) return Boolean::newBoolean(false); + + return Boolean::newBoolean(item->matchesItem(itemNew)); + } + CATCH("Fail in MatchItem!"); } diff --git a/src/api/ItemAPI.h b/src/api/ItemAPI.h index 8e2486b6..5e746c40 100644 --- a/src/api/ItemAPI.h +++ b/src/api/ItemAPI.h @@ -1,6 +1,6 @@ #pragma once -#include #include "api/APIHelp.h" +#include //////////////////// Classes //////////////////// @@ -12,19 +12,17 @@ class ItemClass : public ScriptClass { // Pre data std::string name, type; - int id, count, aux; + int id, count, aux; public: explicit ItemClass(ItemStack* p); void preloadData(); - ItemStack* get() { - return item; - } + ItemStack* get() { return item; } static Local newItem(ItemStack* p); - static ItemStack* extract(Local v); - Local asPointer(const Arguments& args); + static ItemStack* extract(Local v); + Local asPointer(const Arguments& args); Local getName(); Local getType(); diff --git a/src/api/LlAPI.cpp b/src/api/LlAPI.cpp index adeaf53c..94e0a2a8 100644 --- a/src/api/LlAPI.cpp +++ b/src/api/LlAPI.cpp @@ -11,224 +11,219 @@ //////////////////// Classes //////////////////// -ClassDefine LlClassBuilder = - defineClass("ll") - .property("major", &LlClass::getMajorVersion) - .property("minor", &LlClass::getMinorVersion) - .property("revision", &LlClass::getRevisionVersion) - .property("status", &LlClass::getVersionStatus) - .property("scriptEngineVersion", &LlClass::getScriptEngineVersion) - .property("language", &LlClass::getLanguage) - .property("isWine", &LlClass::isWine) - .property("isDebugMode", &LlClass::isDebugMode) - .property("isRelease", &LlClass::isRelease) - .property("isBeta", &LlClass::isBeta) - .property("isDev", &LlClass::isDev) - - .function("versionString", &LlClass::versionString) - .function("requireVersion", &LlClass::requireVersion) - .function("listPlugins", &LlClass::listPlugins) - .function("getAllPluginInfo", &LlClass::getAllPluginInfo) - .function("imports", &LlClass::importFunc) - .function("exports", &LlClass::exportFunc) - .function("hasExported", &LlClass::hasFuncExported) - .function("require", &LlClass::require) - .function("eval", &LlClass::eval) - .function("registerPlugin", &LlClass::registerPlugin) - .function("getPluginInfo", &LlClass::getPluginInfo) - .function("checkVersion", &LlClass::requireVersion) - - // For Compatibility - .function("version", &LlClass::version) - .function("isDebugMode", &LlClass::isDebugModeFunction) - .function("versionStatus", &LlClass::getVersionStatusFunction) - .function("scriptEngineVersion", - &LlClass::getScriptEngineVersionFunction) - - .build(); - -ClassDefine VersionClassBuilder = - defineClass("Version") - // wait for: constructor, setter, converter(toString, toArray, - // toObject)... - .property("Dev", []() { return Number::newNumber(0); }) - .property("Beta", []() { return Number::newNumber(1); }) - .property("Release", []() { return Number::newNumber(2); }) - .build(); +ClassDefine LlClassBuilder = defineClass("ll") + .property("major", &LlClass::getMajorVersion) + .property("minor", &LlClass::getMinorVersion) + .property("revision", &LlClass::getRevisionVersion) + .property("status", &LlClass::getVersionStatus) + .property("scriptEngineVersion", &LlClass::getScriptEngineVersion) + .property("language", &LlClass::getLanguage) + .property("isWine", &LlClass::isWine) + .property("isDebugMode", &LlClass::isDebugMode) + .property("isRelease", &LlClass::isRelease) + .property("isBeta", &LlClass::isBeta) + .property("isDev", &LlClass::isDev) + + .function("versionString", &LlClass::versionString) + .function("requireVersion", &LlClass::requireVersion) + .function("listPlugins", &LlClass::listPlugins) + .function("getAllPluginInfo", &LlClass::getAllPluginInfo) + .function("imports", &LlClass::importFunc) + .function("exports", &LlClass::exportFunc) + .function("hasExported", &LlClass::hasFuncExported) + .function("require", &LlClass::require) + .function("eval", &LlClass::eval) + .function("registerPlugin", &LlClass::registerPlugin) + .function("getPluginInfo", &LlClass::getPluginInfo) + .function("checkVersion", &LlClass::requireVersion) + + // For Compatibility + .function("version", &LlClass::version) + .function("isDebugMode", &LlClass::isDebugModeFunction) + .function("versionStatus", &LlClass::getVersionStatusFunction) + .function("scriptEngineVersion", &LlClass::getScriptEngineVersionFunction) + + .build(); + +ClassDefine VersionClassBuilder = defineClass("Version") + // wait for: constructor, setter, converter(toString, toArray, + // toObject)... + .property("Dev", []() { return Number::newNumber(0); }) + .property("Beta", []() { return Number::newNumber(1); }) + .property("Release", []() { return Number::newNumber(2); }) + .build(); Local LlClass::getLanguage() { - try { - return String::newString(ll::win_utils::getSystemLocaleName()); - } - CATCH("Fail in LLSEGetLanguage") + try { + return String::newString(ll::win_utils::getSystemLocaleName()); + } + CATCH("Fail in LLSEGetLanguage") } Local LlClass::isWine() { - try { - return Boolean::newBoolean(ll::win_utils::isWine()); - } - CATCH("Fail in LLSEIsWine") + try { + return Boolean::newBoolean(ll::win_utils::isWine()); + } + CATCH("Fail in LLSEIsWine") } Local LlClass::isDebugMode() { - try { + try { #ifdef LL_DEBUG - return Boolean::newBoolean(true); + return Boolean::newBoolean(true); #else - return Boolean::newBoolean(false); + return Boolean::newBoolean(false); #endif - } - CATCH("Fail in LLSEIsDebugMode") + } + CATCH("Fail in LLSEIsDebugMode") } Local LlClass::isRelease() { - try { - return Boolean::newBoolean(true); - } - CATCH("Fail in LLSEIsRelease") + try { + return Boolean::newBoolean(true); + } + CATCH("Fail in LLSEIsRelease") } Local LlClass::isBeta() { - try { - return Boolean::newBoolean(false); - } - CATCH("Fail in LLSEIsBeta") + try { + return Boolean::newBoolean(false); + } + CATCH("Fail in LLSEIsBeta") } Local LlClass::isDev() { - try { - return Boolean::newBoolean(false); - } - CATCH("Fail in LLSEIsDev") + try { + return Boolean::newBoolean(false); + } + CATCH("Fail in LLSEIsDev") } Local LlClass::getMajorVersion() { - try { - return Number::newNumber(3); - } - CATCH("Fail in LLSEGetMajorVersion") + try { + return Number::newNumber(3); + } + CATCH("Fail in LLSEGetMajorVersion") } Local LlClass::getMinorVersion() { - try { - return Number::newNumber(0); - } - CATCH("Fail in LLSEGetMinorVersion") + try { + return Number::newNumber(0); + } + CATCH("Fail in LLSEGetMinorVersion") } Local LlClass::getRevisionVersion() { - try { - return Number::newNumber(0); - } - CATCH("Fail in LLSEGetRevisionVersion") + try { + return Number::newNumber(0); + } + CATCH("Fail in LLSEGetRevisionVersion") } Local LlClass::getScriptEngineVersion() { - try { - return String::newString(EngineScope::currentEngine()->getEngineVersion()); - } - CATCH("Fail in LLSEGetScriptEngineVerison") + try { + return String::newString(EngineScope::currentEngine()->getEngineVersion()); + } + CATCH("Fail in LLSEGetScriptEngineVerison") } Local LlClass::getVersionStatus() { - try { - return Number::newNumber(0); - } - CATCH("Fail in LLSEGetVersionStatus") + try { + return Number::newNumber(0); + } + CATCH("Fail in LLSEGetVersionStatus") } -Local LlClass::registerPlugin(const Arguments &args) { - try { - return {}; - } - CATCH("Fail in LLAPI"); +Local LlClass::registerPlugin(const Arguments& args) { + try { + return {}; + } + CATCH("Fail in LLAPI"); } -Local LlClass::getPluginInfo(const Arguments &args) { - try { - return {}; - } - CATCH("Fail in LLAPI"); +Local LlClass::getPluginInfo(const Arguments& args) { + try { + return {}; + } + CATCH("Fail in LLAPI"); } -Local LlClass::versionString(const Arguments &args) { - try { - return String::newString("3.0.0"); - } - CATCH("Fail in LLSEGetVersionString!") +Local LlClass::versionString(const Arguments& args) { + try { + return String::newString("3.0.0"); + } + CATCH("Fail in LLSEGetVersionString!") } -Local LlClass::requireVersion(const Arguments &args) { +Local LlClass::requireVersion(const Arguments& args) { - try { - return Boolean::newBoolean(true); - } - CATCH("Fail in LLSERequireVersion!") + try { + return Boolean::newBoolean(true); + } + CATCH("Fail in LLSERequireVersion!") } -Local LlClass::getAllPluginInfo(const Arguments &args) { - try { - return {}; - } - CATCH("Fail in LLAPI"); +Local LlClass::getAllPluginInfo(const Arguments& args) { + try { + return {}; + } + CATCH("Fail in LLAPI"); } // For Compatibility -Local LlClass::listPlugins(const Arguments &args) { - try { - return {}; - } - CATCH("Fail in LLAPI"); +Local LlClass::listPlugins(const Arguments& args) { + try { + return {}; + } + CATCH("Fail in LLAPI"); } -Local LlClass::require(const Arguments &args) { - try { - return {}; - } - CATCH("Fail in LLAPI"); +Local LlClass::require(const Arguments& args) { + try { + return {}; + } + CATCH("Fail in LLAPI"); } -Local LlClass::eval(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - return EngineScope::currentEngine()->eval(args[0].toStr()); - } - CATCH("Fail in LLSEEval!") +Local LlClass::eval(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + try { + return EngineScope::currentEngine()->eval(args[0].toStr()); + } + CATCH("Fail in LLSEEval!") } // For Compatibility -Local LlClass::getVersionStatusFunction(const Arguments &args) { - return Number::newNumber(0); -} +Local LlClass::getVersionStatusFunction(const Arguments& args) { return Number::newNumber(0); } // For Compatibility -Local LlClass::version(const Arguments &args) { - try { - Local ver = Object::newObject(); - ver.set("major", 3); - ver.set("minor", 0); - ver.set("revision", 0); - ver.set("isBeta", false); - ver.set("isRelease", true); - ver.set("isDev", false); - return ver; - } - CATCH("Fail in LLSEGetVersion!") +Local LlClass::version(const Arguments& args) { + try { + Local ver = Object::newObject(); + ver.set("major", 3); + ver.set("minor", 0); + ver.set("revision", 0); + ver.set("isBeta", false); + ver.set("isRelease", true); + ver.set("isDev", false); + return ver; + } + CATCH("Fail in LLSEGetVersion!") } // For Compatibility -Local LlClass::isDebugModeFunction(const Arguments &args) { - try { +Local LlClass::isDebugModeFunction(const Arguments& args) { + try { #ifdef LL_DEBUG - return Boolean::newBoolean(true); + return Boolean::newBoolean(true); #else - return Boolean::newBoolean(false); + return Boolean::newBoolean(false); #endif - } - CATCH("Fail in LLSEGetIsDebugModeFunction") + } + CATCH("Fail in LLSEGetIsDebugModeFunction") } // For Compatibility -Local LlClass::getScriptEngineVersionFunction(const Arguments &args) { - try { - return String::newString(EngineScope::currentEngine()->getEngineVersion()); - } - CATCH("Fail in LLSEGetScriptEngineVerison") +Local LlClass::getScriptEngineVersionFunction(const Arguments& args) { + try { + return String::newString(EngineScope::currentEngine()->getEngineVersion()); + } + CATCH("Fail in LLSEGetScriptEngineVerison") } \ No newline at end of file diff --git a/src/api/LlAPI.h b/src/api/LlAPI.h index 784a9c6b..f34f016d 100644 --- a/src/api/LlAPI.h +++ b/src/api/LlAPI.h @@ -16,7 +16,7 @@ class LlClass { static Local isBeta(); static Local isDev(); static Local isWine(); - static Local isDebugMode(); + static Local isDebugMode(); static Local registerPlugin(const Arguments& args); static Local versionString(const Arguments& args); diff --git a/src/api/LoggerAPI.cpp b/src/api/LoggerAPI.cpp index 92dccf6f..e3fc9ecb 100644 --- a/src/api/LoggerAPI.cpp +++ b/src/api/LoggerAPI.cpp @@ -11,189 +11,179 @@ //////////////////// Classes //////////////////// -ClassDefine LoggerClassBuilder = - defineClass("logger") - .function("log", &LoggerClass::log) - .function("debug", &LoggerClass::debug) - .function("info", &LoggerClass::info) - .function("warn", &LoggerClass::warn) - .function("warning", &LoggerClass::warn) - .function("error", &LoggerClass::error) - .function("fatal", &LoggerClass::fatal) - - .function("setTitle", &LoggerClass::setTitle) - .function("setConsole", &LoggerClass::setConsole) - .function("setFile", &LoggerClass::setFile) - .function("setPlayer", &LoggerClass::setPlayer) - .function("setLogLevel", &LoggerClass::setLogLevel) - .build(); +ClassDefine LoggerClassBuilder = defineClass("logger") + .function("log", &LoggerClass::log) + .function("debug", &LoggerClass::debug) + .function("info", &LoggerClass::info) + .function("warn", &LoggerClass::warn) + .function("warning", &LoggerClass::warn) + .function("error", &LoggerClass::error) + .function("fatal", &LoggerClass::fatal) + + .function("setTitle", &LoggerClass::setTitle) + .function("setConsole", &LoggerClass::setConsole) + .function("setFile", &LoggerClass::setFile) + .function("setPlayer", &LoggerClass::setPlayer) + .function("setLogLevel", &LoggerClass::setLogLevel) + .build(); ////////////////// Helper ////////////////// string inline GetTimeStrHelper() { return Raw_GetDateTimeStr(); } -string &StrReplace(string &str, const string &to_replaced, - const string &new_str) { - for (string::size_type pos(0); pos != string::npos; pos += new_str.length()) { - pos = str.find(to_replaced, pos); - if (pos != string::npos) - str.replace(pos, to_replaced.length(), new_str); - else - break; - } - return str; +string& StrReplace(string& str, const string& to_replaced, const string& new_str) { + for (string::size_type pos(0); pos != string::npos; pos += new_str.length()) { + pos = str.find(to_replaced, pos); + if (pos != string::npos) str.replace(pos, to_replaced.length(), new_str); + else break; + } + return str; } ////////////////// Helper ////////////////// -void inline LogDataHelper(ll::Logger::OutputStream *outStream, - const Arguments &args) { - std::string res; - for (int i = 0; i < args.size(); ++i) - res += ValueToString(args[i]); - (*outStream)(res); +void inline LogDataHelper(ll::Logger::OutputStream* outStream, const Arguments& args) { + std::string res; + for (int i = 0; i < args.size(); ++i) res += ValueToString(args[i]); + (*outStream)(res); } -Local LoggerClass::log(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) +Local LoggerClass::log(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) - try { - auto globalConf = ENGINE_OWN_DATA(); - LogDataHelper(&globalConf->logger.info, args); - return Boolean::newBoolean(true); - } - CATCH("Fail in LoggerLog!") + try { + auto globalConf = ENGINE_OWN_DATA(); + LogDataHelper(&globalConf->logger.info, args); + return Boolean::newBoolean(true); + } + CATCH("Fail in LoggerLog!") } -Local LoggerClass::debug(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) +Local LoggerClass::debug(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) - try { - auto globalConf = ENGINE_OWN_DATA(); - LogDataHelper(&globalConf->logger.debug, args); - return Boolean::newBoolean(true); - } - CATCH("Fail in LoggerDebug!") + try { + auto globalConf = ENGINE_OWN_DATA(); + LogDataHelper(&globalConf->logger.debug, args); + return Boolean::newBoolean(true); + } + CATCH("Fail in LoggerDebug!") } -Local LoggerClass::info(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) +Local LoggerClass::info(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) - try { - auto globalConf = ENGINE_OWN_DATA(); - LogDataHelper(&globalConf->logger.info, args); - return Boolean::newBoolean(true); - } - CATCH("Fail in LoggerInfo!") + try { + auto globalConf = ENGINE_OWN_DATA(); + LogDataHelper(&globalConf->logger.info, args); + return Boolean::newBoolean(true); + } + CATCH("Fail in LoggerInfo!") } -Local LoggerClass::warn(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) +Local LoggerClass::warn(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) - try { - auto globalConf = ENGINE_OWN_DATA(); - LogDataHelper(&globalConf->logger.warn, args); - return Boolean::newBoolean(true); - } - CATCH("Fail in LoggerWarn!") + try { + auto globalConf = ENGINE_OWN_DATA(); + LogDataHelper(&globalConf->logger.warn, args); + return Boolean::newBoolean(true); + } + CATCH("Fail in LoggerWarn!") } -Local LoggerClass::error(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) +Local LoggerClass::error(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) - try { - auto globalConf = ENGINE_OWN_DATA(); - LogDataHelper(&globalConf->logger.error, args); - return Boolean::newBoolean(true); - } - CATCH("Fail in LoggerError!") + try { + auto globalConf = ENGINE_OWN_DATA(); + LogDataHelper(&globalConf->logger.error, args); + return Boolean::newBoolean(true); + } + CATCH("Fail in LoggerError!") } -Local LoggerClass::fatal(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) +Local LoggerClass::fatal(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) - try { - auto globalConf = ENGINE_OWN_DATA(); - LogDataHelper(&globalConf->logger.fatal, args); - return Boolean::newBoolean(true); - } - CATCH("Fail in LoggerFatal!") + try { + auto globalConf = ENGINE_OWN_DATA(); + LogDataHelper(&globalConf->logger.fatal, args); + return Boolean::newBoolean(true); + } + CATCH("Fail in LoggerFatal!") } -Local LoggerClass::setTitle(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - CHECK_ARG_TYPE(args[0], ValueKind::kString) +Local LoggerClass::setTitle(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + CHECK_ARG_TYPE(args[0], ValueKind::kString) - try { - ENGINE_OWN_DATA()->logger.title = args[0].asString().toString(); - return Boolean::newBoolean(true); - } - CATCH("Fail in LoggerSetTitle!") + try { + ENGINE_OWN_DATA()->logger.title = args[0].asString().toString(); + return Boolean::newBoolean(true); + } + CATCH("Fail in LoggerSetTitle!") } ///////////////// Helper ///////////////// void UpdateMaxLogLevel() { - auto data = ENGINE_OWN_DATA(); - data->maxLogLevel = data->logger.consoleLevel; - if (data->maxLogLevel < data->logger.fileLevel) - data->maxLogLevel = data->logger.fileLevel; - if (data->maxLogLevel < data->logger.playerLevel) - data->maxLogLevel = data->logger.playerLevel; + auto data = ENGINE_OWN_DATA(); + data->maxLogLevel = data->logger.consoleLevel; + if (data->maxLogLevel < data->logger.fileLevel) data->maxLogLevel = data->logger.fileLevel; + if (data->maxLogLevel < data->logger.playerLevel) data->maxLogLevel = data->logger.playerLevel; } ///////////////// Helper ///////////////// -Local LoggerClass::setConsole(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - CHECK_ARG_TYPE(args[0], ValueKind::kBoolean) - if (args.size() >= 2) - CHECK_ARG_TYPE(args[1], ValueKind::kNumber) - - try { - if (args.size() >= 2) { - ENGINE_OWN_DATA()->logger.consoleLevel = args[1].toInt(); - } - if (!args[0].asBoolean().value()) { - ENGINE_OWN_DATA()->logger.consoleLevel = 0; +Local LoggerClass::setConsole(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + CHECK_ARG_TYPE(args[0], ValueKind::kBoolean) + if (args.size() >= 2) CHECK_ARG_TYPE(args[1], ValueKind::kNumber) + + try { + if (args.size() >= 2) { + ENGINE_OWN_DATA()->logger.consoleLevel = args[1].toInt(); + } + if (!args[0].asBoolean().value()) { + ENGINE_OWN_DATA()->logger.consoleLevel = 0; + } + UpdateMaxLogLevel(); + return Boolean::newBoolean(true); } - UpdateMaxLogLevel(); - return Boolean::newBoolean(true); - } - CATCH("Fail in LoggerSetConsole!") + CATCH("Fail in LoggerSetConsole!") } -Local LoggerClass::setFile(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - CHECK_ARG_TYPE(args[0], ValueKind::kString) - if (args.size() >= 2) - CHECK_ARG_TYPE(args[1], ValueKind::kNumber) +Local LoggerClass::setFile(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + CHECK_ARG_TYPE(args[0], ValueKind::kString) + if (args.size() >= 2) CHECK_ARG_TYPE(args[1], ValueKind::kNumber) - try { - string newFile = args[0].asString().toString(); - ENGINE_OWN_DATA()->logger.setFile(newFile, std::ios::app); + try { + string newFile = args[0].asString().toString(); + ENGINE_OWN_DATA()->logger.setFile(newFile, std::ios::app); - if (args.size() >= 2) { - ENGINE_OWN_DATA()->logger.fileLevel = args[1].toInt(); - UpdateMaxLogLevel(); + if (args.size() >= 2) { + ENGINE_OWN_DATA()->logger.fileLevel = args[1].toInt(); + UpdateMaxLogLevel(); + } + return Boolean::newBoolean(ENGINE_OWN_DATA()->logger.ofs.value().is_open()); } - return Boolean::newBoolean(ENGINE_OWN_DATA()->logger.ofs.value().is_open()); - } - CATCH("Fail in LoggerSetFile!") + CATCH("Fail in LoggerSetFile!") } -Local LoggerClass::setPlayer(const Arguments &args) { - try { - return Boolean::newBoolean(false); - } - CATCH("Fail in LoggerSetPlayer!") +Local LoggerClass::setPlayer(const Arguments& args) { + try { + return Boolean::newBoolean(false); + } + CATCH("Fail in LoggerSetPlayer!") } -Local LoggerClass::setLogLevel(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - CHECK_ARG_TYPE(args[0], ValueKind::kNumber) - - try { - auto conf = ENGINE_OWN_DATA(); - conf->maxLogLevel = conf->logger.consoleLevel = conf->logger.fileLevel = - conf->logger.playerLevel = args[0].toInt(); - return Boolean::newBoolean(true); - } - CATCH("Fail in SetLogLevel!") +Local LoggerClass::setLogLevel(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + CHECK_ARG_TYPE(args[0], ValueKind::kNumber) + + try { + auto conf = ENGINE_OWN_DATA(); + conf->maxLogLevel = conf->logger.consoleLevel = conf->logger.fileLevel = conf->logger.playerLevel = + args[0].toInt(); + return Boolean::newBoolean(true); + } + CATCH("Fail in SetLogLevel!") } diff --git a/src/api/McAPI.cpp b/src/api/McAPI.cpp index d31a89b0..ddb93181 100644 --- a/src/api/McAPI.cpp +++ b/src/api/McAPI.cpp @@ -1,60 +1,59 @@ #include "api/McAPI.h" -ClassDefine McClassBuilder = - defineClass("mc") - .function("getBDSVersion", &McClass::getBDSVersion) - .function("getServerProtocolVersion", &McClass::getServerProtocolVersion) - .function("runcmd", &McClass::runcmd) - .function("runcmdEx", &McClass::runcmdEx) - .function("regPlayerCmd", &McClass::regPlayerCmd) - .function("newCommand", &McClass::newCommand) - .function("broadcast", &McClass::broadcast) - .function("listen", &McClass::listen) - .function("getPlayer", &McClass::getPlayer) - .function("getOnlinePlayers", &McClass::getOnlinePlayers) - .function("getAllEntities", McClass::getAllEntities) - .function("getEntities", McClass::getEntities) - .function("newItem", &McClass::newItem) - .function("spawnMob", &McClass::spawnMob) - .function("cloneMob", &McClass::cloneMob) - .function("spawnItem", &McClass::spawnItem) - .function("spawnSimulatedPlayer", &McClass::spawnSimulatedPlayer) - .function("explode", &McClass::explode) - .function("getBlock", &McClass::getBlock) - .function("setBlock", &McClass::setBlock) - .function("spawnParticle", &McClass::spawnParticle) - .function("newSimpleForm", &McClass::newSimpleForm) - .function("newCustomForm", &McClass::newCustomForm) - .function("regConsoleCmd", &McClass::regConsoleCmd) - .function("setMotd", &McClass::setMotd) - .function("sendCmdOutput", &McClass::sendCmdOutput) - .function("newIntPos", &McClass::newIntPos) - .function("newFloatPos", &McClass::newFloatPos) - .function("getDisplayObjective", &McClass::getDisplayObjective) - .function("clearDisplayObjective", &McClass::clearDisplayObjective) - .function("getScoreObjective", &McClass::getScoreObjective) - .function("newScoreObjective", &McClass::newScoreObjective) - .function("removeScoreObjective", &McClass::removeScoreObjective) - .function("getAllScoreObjectives", &McClass::getAllScoreObjectives) - .function("setStructure", &McClass::setStructure) - .function("getStructure", &McClass::getStructure) - .function("newParticleSpawner", &McClass::newParticleSpawner) - .function("getPlayerNbt", &McClass::getPlayerNbt) - .function("setPlayerNbt", &McClass::setPlayerNbt) - .function("setPlayerNbtTags", &McClass::setPlayerNbtTags) - .function("deletePlayerNbt", &McClass::deletePlayerNbt) - .function("getPlayerScore", &McClass::getPlayerScore) - .function("setPlayerScore", &McClass::setPlayerScore) - .function("addPlayerScore", &McClass::addPlayerScore) - .function("reducePlayerScore", &McClass::reducePlayerScore) - .function("deletePlayerScore", &McClass::deletePlayerScore) - .function("getTime", &McClass::getTime) - .function("setTime", &McClass::setTime) - .function("getWeather", &McClass::getWeather) - .function("setWeather", &McClass::setWeather) - // For Compatity - .function("getAllScoreObjective", &McClass::getAllScoreObjectives) - .function("getDisplayObjectives", &McClass::getDisplayObjective) - .function("crash", &McClass::crashBDS) - .function("setMaxPlayers", &McClass::setMaxNumPlayers) - .build(); +ClassDefine McClassBuilder = defineClass("mc") + .function("getBDSVersion", &McClass::getBDSVersion) + .function("getServerProtocolVersion", &McClass::getServerProtocolVersion) + .function("runcmd", &McClass::runcmd) + .function("runcmdEx", &McClass::runcmdEx) + .function("regPlayerCmd", &McClass::regPlayerCmd) + .function("newCommand", &McClass::newCommand) + .function("broadcast", &McClass::broadcast) + .function("listen", &McClass::listen) + .function("getPlayer", &McClass::getPlayer) + .function("getOnlinePlayers", &McClass::getOnlinePlayers) + .function("getAllEntities", McClass::getAllEntities) + .function("getEntities", McClass::getEntities) + .function("newItem", &McClass::newItem) + .function("spawnMob", &McClass::spawnMob) + .function("cloneMob", &McClass::cloneMob) + .function("spawnItem", &McClass::spawnItem) + .function("spawnSimulatedPlayer", &McClass::spawnSimulatedPlayer) + .function("explode", &McClass::explode) + .function("getBlock", &McClass::getBlock) + .function("setBlock", &McClass::setBlock) + .function("spawnParticle", &McClass::spawnParticle) + .function("newSimpleForm", &McClass::newSimpleForm) + .function("newCustomForm", &McClass::newCustomForm) + .function("regConsoleCmd", &McClass::regConsoleCmd) + .function("setMotd", &McClass::setMotd) + .function("sendCmdOutput", &McClass::sendCmdOutput) + .function("newIntPos", &McClass::newIntPos) + .function("newFloatPos", &McClass::newFloatPos) + .function("getDisplayObjective", &McClass::getDisplayObjective) + .function("clearDisplayObjective", &McClass::clearDisplayObjective) + .function("getScoreObjective", &McClass::getScoreObjective) + .function("newScoreObjective", &McClass::newScoreObjective) + .function("removeScoreObjective", &McClass::removeScoreObjective) + .function("getAllScoreObjectives", &McClass::getAllScoreObjectives) + .function("setStructure", &McClass::setStructure) + .function("getStructure", &McClass::getStructure) + .function("newParticleSpawner", &McClass::newParticleSpawner) + .function("getPlayerNbt", &McClass::getPlayerNbt) + .function("setPlayerNbt", &McClass::setPlayerNbt) + .function("setPlayerNbtTags", &McClass::setPlayerNbtTags) + .function("deletePlayerNbt", &McClass::deletePlayerNbt) + .function("getPlayerScore", &McClass::getPlayerScore) + .function("setPlayerScore", &McClass::setPlayerScore) + .function("addPlayerScore", &McClass::addPlayerScore) + .function("reducePlayerScore", &McClass::reducePlayerScore) + .function("deletePlayerScore", &McClass::deletePlayerScore) + .function("getTime", &McClass::getTime) + .function("setTime", &McClass::setTime) + .function("getWeather", &McClass::getWeather) + .function("setWeather", &McClass::setWeather) + // For Compatity + .function("getAllScoreObjective", &McClass::getAllScoreObjectives) + .function("getDisplayObjectives", &McClass::getDisplayObjective) + .function("crash", &McClass::crashBDS) + .function("setMaxPlayers", &McClass::setMaxNumPlayers) + .build(); diff --git a/src/api/MoreGlobal.cpp b/src/api/MoreGlobal.cpp index 0f443be0..d4e79b92 100644 --- a/src/api/MoreGlobal.cpp +++ b/src/api/MoreGlobal.cpp @@ -3,15 +3,20 @@ #include "mc/world/level/storage/DBStorage.h" #include "mc/world/level/storage/DBStorageConfig.h" -LL_TYPE_INSTANCE_HOOK(DBStorageHook, HookPriority::Normal, DBStorage, - "??0DBStorage@@QEAA@UDBStorageConfig@@V?$not_null@V?$" - "NonOwnerPointer@VLevelDbEnv@@@Bedrock@@@gsl@@@Z", - DBStorage, struct DBStorageConfig cfg, - Bedrock::NotNullNonOwnerPtr dbEnv) { +LL_TYPE_INSTANCE_HOOK( + DBStorageHook, + HookPriority::Normal, + DBStorage, + "??0DBStorage@@QEAA@UDBStorageConfig@@V?$not_null@V?$" + "NonOwnerPointer@VLevelDbEnv@@@Bedrock@@@gsl@@@Z", + DBStorage, + struct DBStorageConfig cfg, + Bedrock::NotNullNonOwnerPtr dbEnv +) { - DBStorage ori = origin(cfg, dbEnv); - MoreGlobal::setDBStorage(&ori); - return ori; + DBStorage ori = origin(cfg, dbEnv); + MoreGlobal::setDBStorage(&ori); + return ori; }; void MoreGlobal::Init() { DBStorageHook::hook(); } \ No newline at end of file diff --git a/src/api/MoreGlobal.h b/src/api/MoreGlobal.h index aff8ddc6..2a3f643b 100644 --- a/src/api/MoreGlobal.h +++ b/src/api/MoreGlobal.h @@ -1,10 +1,10 @@ class DBStorage; class MoreGlobal { private: - static DBStorage *db; + static DBStorage* db; public: - static void Init(); - static DBStorage *getDBStorage() { return db; }; - static void setDBStorage(DBStorage *dbs) { db = dbs; }; + static void Init(); + static DBStorage* getDBStorage() { return db; }; + static void setDBStorage(DBStorage* dbs) { db = dbs; }; }; \ No newline at end of file diff --git a/src/api/NativeAPI.cpp b/src/api/NativeAPI.cpp index cf38a5d8..b000662d 100644 --- a/src/api/NativeAPI.cpp +++ b/src/api/NativeAPI.cpp @@ -1,26 +1,26 @@ #include "api/NativeAPI.h" +#include "demangler/MicrosoftDemangle.h" #include "ll/api/memory/Hook.h" #include -#include "demangler/MicrosoftDemangle.h" Concurrency::concurrent_unordered_map NativeFunction::parsedSymbol; -#define NATIVE_CHECK_ARG_TYPE(TYPE) \ - if (args[i].getKind() != TYPE) { \ - logger.error("Wrong type of argument!"); \ - logger.error("In Symbol: " + funcSymbol->mSymbol); \ - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); \ - return Local(); \ +#define NATIVE_CHECK_ARG_TYPE(TYPE) \ + if (args[i].getKind() != TYPE) { \ + logger.error("Wrong type of argument!"); \ + logger.error("In Symbol: " + funcSymbol->mSymbol); \ + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); \ + return Local(); \ } -#define NATIVE_CHECK_ARG_CLASS(TYPE) \ - if (!IsInstanceOf(args[i])) { \ - logger.error("Wrong type of argument!"); \ - logger.error("In Symbol: " + funcSymbol->mSymbol); \ - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); \ - return Local(); \ +#define NATIVE_CHECK_ARG_CLASS(TYPE) \ + if (!IsInstanceOf(args[i])) { \ + logger.error("Wrong type of argument!"); \ + logger.error("In Symbol: " + funcSymbol->mSymbol); \ + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); \ + return Local(); \ } Local NativeFunction::callNativeFunction(DCCallVM* vm, NativeFunction* funcSymbol, const Arguments& args) { @@ -35,163 +35,163 @@ Local NativeFunction::callNativeFunction(DCCallVM* vm, NativeFunction* fu dcReset(vm); for (int i = 0; i < funcSymbol->mParams.size(); ++i) { switch (funcSymbol->mParams[i]) { - case NativeFunction::Types::Bool: - NATIVE_CHECK_ARG_TYPE(ValueKind::kBoolean); - dcArgChar(vm, args[i].asBoolean().value()); - break; - case NativeFunction::Types::Char: - case NativeFunction::Types::UnsignedChar: - NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber); - dcArgChar(vm, (char)args[i].asNumber().toInt32()); - break; - case NativeFunction::Types::Short: - case NativeFunction::Types::UnsignedShort: - NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber); - dcArgShort(vm, (short)args[i].asNumber().toInt32()); - break; - case NativeFunction::Types::Int: - case NativeFunction::Types::UnsignedInt: - NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber); - dcArgInt(vm, (int)args[i].asNumber().toInt32()); - break; - case NativeFunction::Types::Long: - case NativeFunction::Types::UnsignedLong: - NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber); - dcArgLong(vm, (long)args[i].asNumber().toInt32()); - break; - case NativeFunction::Types::LongLong: - case NativeFunction::Types::UnsignedLongLong: - NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber); - dcArgLongLong(vm, args[i].asNumber().toInt64()); - break; - case NativeFunction::Types::Float: - NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber); - dcArgFloat(vm, args[i].asNumber().toFloat()); - break; - case NativeFunction::Types::Double: - NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber); - dcArgDouble(vm, args[i].asNumber().toDouble()); - break; - case NativeFunction::Types::Pointer: - switch (args[i].getKind()) { - case ValueKind::kObject: - NATIVE_CHECK_ARG_CLASS(NativePointer); - dcArgPointer(vm, NativePointer::extract(args[i])); - break; - case ValueKind::kNumber: - NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber); - dcArgPointer(vm, (void*)args[i].asNumber().toInt64()); - break; - case ValueKind::kNull: - default: - dcArgPointer(vm, nullptr); - break; - } - break; - default: - break; - } - } - Local res; - DCpointer func = (DCpointer)funcSymbol->mFunction; - switch (funcSymbol->mReturnVal) { - case NativeFunction::Types::Void: - dcCallVoid(vm, func); - break; - case NativeFunction::Types::Bool: { - // in c, bool is the alias of int - // [c]#define bool int, sizeof(bool) == 4 - // but in cpp, bool represent a true/false value - // it'a a builtin type, sizeof(bool) == sizeof(char) == 1 - res = Boolean::newBoolean(dcCallChar(vm, func)); + case NativeFunction::Types::Bool: + NATIVE_CHECK_ARG_TYPE(ValueKind::kBoolean); + dcArgChar(vm, args[i].asBoolean().value()); break; - } case NativeFunction::Types::Char: case NativeFunction::Types::UnsignedChar: - res = Number::newNumber(dcCallChar(vm, func)); + NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber); + dcArgChar(vm, (char)args[i].asNumber().toInt32()); break; case NativeFunction::Types::Short: case NativeFunction::Types::UnsignedShort: - res = Number::newNumber(dcCallShort(vm, func)); + NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber); + dcArgShort(vm, (short)args[i].asNumber().toInt32()); break; case NativeFunction::Types::Int: case NativeFunction::Types::UnsignedInt: - res = Number::newNumber(dcCallInt(vm, func)); + NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber); + dcArgInt(vm, (int)args[i].asNumber().toInt32()); break; case NativeFunction::Types::Long: case NativeFunction::Types::UnsignedLong: - res = Number::newNumber((int)dcCallLong(vm, func)); + NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber); + dcArgLong(vm, (long)args[i].asNumber().toInt32()); break; case NativeFunction::Types::LongLong: case NativeFunction::Types::UnsignedLongLong: - res = Number::newNumber(dcCallLongLong(vm, func)); + NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber); + dcArgLongLong(vm, args[i].asNumber().toInt64()); break; case NativeFunction::Types::Float: - res = Number::newNumber(dcCallFloat(vm, func)); + NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber); + dcArgFloat(vm, args[i].asNumber().toFloat()); break; case NativeFunction::Types::Double: - res = Number::newNumber(dcCallDouble(vm, func)); + NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber); + dcArgDouble(vm, args[i].asNumber().toDouble()); break; case NativeFunction::Types::Pointer: - res = NativePointer::newNativePointer((NativePointer*)dcCallPointer(vm, func)); + switch (args[i].getKind()) { + case ValueKind::kObject: + NATIVE_CHECK_ARG_CLASS(NativePointer); + dcArgPointer(vm, NativePointer::extract(args[i])); + break; + case ValueKind::kNumber: + NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber); + dcArgPointer(vm, (void*)args[i].asNumber().toInt64()); + break; + case ValueKind::kNull: + default: + dcArgPointer(vm, nullptr); + break; + } break; default: break; + } + } + Local res; + DCpointer func = (DCpointer)funcSymbol->mFunction; + switch (funcSymbol->mReturnVal) { + case NativeFunction::Types::Void: + dcCallVoid(vm, func); + break; + case NativeFunction::Types::Bool: { + // in c, bool is the alias of int + // [c]#define bool int, sizeof(bool) == 4 + // but in cpp, bool represent a true/false value + // it'a a builtin type, sizeof(bool) == sizeof(char) == 1 + res = Boolean::newBoolean(dcCallChar(vm, func)); + break; + } + case NativeFunction::Types::Char: + case NativeFunction::Types::UnsignedChar: + res = Number::newNumber(dcCallChar(vm, func)); + break; + case NativeFunction::Types::Short: + case NativeFunction::Types::UnsignedShort: + res = Number::newNumber(dcCallShort(vm, func)); + break; + case NativeFunction::Types::Int: + case NativeFunction::Types::UnsignedInt: + res = Number::newNumber(dcCallInt(vm, func)); + break; + case NativeFunction::Types::Long: + case NativeFunction::Types::UnsignedLong: + res = Number::newNumber((int)dcCallLong(vm, func)); + break; + case NativeFunction::Types::LongLong: + case NativeFunction::Types::UnsignedLongLong: + res = Number::newNumber(dcCallLongLong(vm, func)); + break; + case NativeFunction::Types::Float: + res = Number::newNumber(dcCallFloat(vm, func)); + break; + case NativeFunction::Types::Double: + res = Number::newNumber(dcCallDouble(vm, func)); + break; + case NativeFunction::Types::Pointer: + res = NativePointer::newNativePointer((NativePointer*)dcCallPointer(vm, func)); + break; + default: + break; } return res; } char NativeFunction::getTypeSignature(NativeFunction::Types type) { switch (type) { - case NativeFunction::Types::Bool: - return 'B'; - break; - case NativeFunction::Types::Char: - return 'c'; - break; - case NativeFunction::Types::UnsignedChar: - return 'C'; - break; - case NativeFunction::Types::Short: - return 's'; - break; - case NativeFunction::Types::UnsignedShort: - return 'S'; - break; - case NativeFunction::Types::Int: - return 'i'; - break; - case NativeFunction::Types::UnsignedInt: - return 'I'; - break; - case NativeFunction::Types::Long: - return 'j'; - break; - case NativeFunction::Types::UnsignedLong: - return 'J'; - break; - case NativeFunction::Types::LongLong: - return 'l'; - break; - case NativeFunction::Types::UnsignedLongLong: - return 'L'; - break; - case NativeFunction::Types::Float: - return 'f'; - break; - case NativeFunction::Types::Double: - return 'd'; - break; - case NativeFunction::Types::Pointer: - return 'p'; - break; - default: - return 'v'; - break; + case NativeFunction::Types::Bool: + return 'B'; + break; + case NativeFunction::Types::Char: + return 'c'; + break; + case NativeFunction::Types::UnsignedChar: + return 'C'; + break; + case NativeFunction::Types::Short: + return 's'; + break; + case NativeFunction::Types::UnsignedShort: + return 'S'; + break; + case NativeFunction::Types::Int: + return 'i'; + break; + case NativeFunction::Types::UnsignedInt: + return 'I'; + break; + case NativeFunction::Types::Long: + return 'j'; + break; + case NativeFunction::Types::UnsignedLong: + return 'J'; + break; + case NativeFunction::Types::LongLong: + return 'l'; + break; + case NativeFunction::Types::UnsignedLongLong: + return 'L'; + break; + case NativeFunction::Types::Float: + return 'f'; + break; + case NativeFunction::Types::Double: + return 'd'; + break; + case NativeFunction::Types::Pointer: + return 'p'; + break; + default: + return 'v'; + break; } } inline std::string NativeFunction::buildDynCallbackSig() { std::string result; - size_t params_size = mParams.size(); + size_t params_size = mParams.size(); result.reserve(params_size + 2); for (int i = 0; i < params_size; ++i) { result[i] = getTypeSignature(mParams[i]); @@ -205,56 +205,56 @@ NativeFunction::Types NativeFunction::getNativeType(demangler::ms_demangle::Node if (type) { if (type->kind() == NodeKind::PrimitiveType) { switch (((PrimitiveTypeNode*)type)->PrimKind) { - case PrimitiveKind::Bool: - return NativeFunction::Types::Bool; - break; - case PrimitiveKind::Char: - return NativeFunction::Types::Char; - break; - case PrimitiveKind::Uchar: - return NativeFunction::Types::UnsignedChar; - break; - case PrimitiveKind::Short: - return NativeFunction::Types::Short; - break; - case PrimitiveKind::Ushort: - return NativeFunction::Types::UnsignedShort; - break; - case PrimitiveKind::Int: - return NativeFunction::Types::Int; - break; - case PrimitiveKind::Uint: - return NativeFunction::Types::UnsignedInt; - break; - case PrimitiveKind::Long: - return NativeFunction::Types::Long; - break; - case PrimitiveKind::Ulong: - return NativeFunction::Types::UnsignedLong; - break; - case PrimitiveKind::Int64: - return NativeFunction::Types::LongLong; - break; - case PrimitiveKind::Uint64: - return NativeFunction::Types::UnsignedLongLong; - break; - case PrimitiveKind::Float: - return NativeFunction::Types::Float; - break; - case PrimitiveKind::Double: - return NativeFunction::Types::Double; - break; - default: - return NativeFunction::Types::Void; + case PrimitiveKind::Bool: + return NativeFunction::Types::Bool; + break; + case PrimitiveKind::Char: + return NativeFunction::Types::Char; + break; + case PrimitiveKind::Uchar: + return NativeFunction::Types::UnsignedChar; + break; + case PrimitiveKind::Short: + return NativeFunction::Types::Short; + break; + case PrimitiveKind::Ushort: + return NativeFunction::Types::UnsignedShort; + break; + case PrimitiveKind::Int: + return NativeFunction::Types::Int; + break; + case PrimitiveKind::Uint: + return NativeFunction::Types::UnsignedInt; + break; + case PrimitiveKind::Long: + return NativeFunction::Types::Long; + break; + case PrimitiveKind::Ulong: + return NativeFunction::Types::UnsignedLong; + break; + case PrimitiveKind::Int64: + return NativeFunction::Types::LongLong; + break; + case PrimitiveKind::Uint64: + return NativeFunction::Types::UnsignedLongLong; + break; + case PrimitiveKind::Float: + return NativeFunction::Types::Float; + break; + case PrimitiveKind::Double: + return NativeFunction::Types::Double; + break; + default: + return NativeFunction::Types::Void; } } else if (type->kind() == NodeKind::PointerType || type->kind() == NodeKind::NamedIdentifier) { return NativeFunction::Types::Pointer; } else if (type->kind() == NodeKind::TagType) { switch (((TagTypeNode*)type)->Tag) { - case TagKind::Enum: - return NativeFunction::Types::Int; - default: - return NativeFunction::Types::Pointer; + case TagKind::Enum: + return NativeFunction::Types::Int; + default: + return NativeFunction::Types::Pointer; } } } @@ -271,19 +271,16 @@ NativeFunction NativeFunction::getOrParse(const std::string& symbol) { NativeFunction result; result.mFunction = ll::memory::resolveSymbol(symbol.c_str()); - result.mSymbol = symbol; + result.mSymbol = symbol; - Demangler demangler; - StringView symbolView{symbol.c_str()}; + Demangler demangler; + StringView symbolView{symbol.c_str()}; SymbolNode* AST = demangler.parse(symbolView); - if (demangler.Error) - throw std::runtime_error("failed to demangle symbol"); - if (AST->kind() != NodeKind::FunctionSymbol) - throw std::runtime_error("mangled name is not a function"); - auto funcAST = static_cast(AST); + if (demangler.Error) throw std::runtime_error("failed to demangle symbol"); + if (AST->kind() != NodeKind::FunctionSymbol) throw std::runtime_error("mangled name is not a function"); + auto funcAST = static_cast(AST); result.mReturnVal = getNativeType(funcAST->Signature->ReturnType); - if (funcAST->Signature->Quals & Q_Pointer64) - result.mParams.push_back(NativeFunction::Types::Pointer); + if (funcAST->Signature->Quals & Q_Pointer64) result.mParams.push_back(NativeFunction::Types::Pointer); if (funcAST->Signature->Params) { result.mParams.reserve(funcAST->Signature->Params->Count + 1); @@ -303,43 +300,53 @@ Local ScriptNativeFunction::fromSymbol(const Arguments& args) { CHECK_ARG_TYPE(args[0], ValueKind::kString); const std::string symbol = args[0].toStr(); - auto scriptResult = args.engine()->newNativeClass(); - ScriptNativeFunction* result = args.engine()->getNativeInstance(scriptResult); + auto scriptResult = args.engine()->newNativeClass(); + ScriptNativeFunction* result = args.engine()->getNativeInstance(scriptResult); result->cloneFrom(getOrParse(symbol)); return scriptResult; } Local ScriptNativeFunction::fromDescription(const Arguments& args) { - auto scriptResult = args.engine()->newNativeClass(); - ScriptNativeFunction* result = args.engine()->getNativeInstance(scriptResult); + auto scriptResult = args.engine()->newNativeClass(); + ScriptNativeFunction* result = args.engine()->getNativeInstance(scriptResult); CHECK_ARGS_COUNT(args, 1); CHECK_ARG_TYPE(args[0], ValueKind::kNumber); size_t argsSize = args.size(); - result->mReturnVal = magic_enum::enum_cast(args[0].toInt()).value_or(NativeFunction::Types::Void); + result->mReturnVal = + magic_enum::enum_cast(args[0].toInt()).value_or(NativeFunction::Types::Void); for (size_t i = 1; i < argsSize; i++) { CHECK_ARG_TYPE(args[i], ValueKind::kNumber); - result->mParams.push_back(magic_enum::enum_cast(args[i].toInt()).value_or(NativeFunction::Types::Void)); + result->mParams.push_back( + magic_enum::enum_cast(args[i].toInt()).value_or(NativeFunction::Types::Void) + ); } return scriptResult; } Local ScriptNativeFunction::fromScript(const Arguments& args) { CHECK_ARG_TYPE(args[args.size() - 1], ValueKind::kFunction); - auto scriptResult = args.engine()->newNativeClass(args.thiz()); + auto scriptResult = args.engine()->newNativeClass(args.thiz()); DynamicHookData* nativeScriptFunction = args.engine()->getNativeInstance(scriptResult); CHECK_ARG_TYPE(args[0], ValueKind::kNumber); size_t argsSize = args.size(); - nativeScriptFunction->mReturnVal = magic_enum::enum_cast(args[0].toInt()).value_or(NativeFunction::Types::Void); + nativeScriptFunction->mReturnVal = + magic_enum::enum_cast(args[0].toInt()).value_or(NativeFunction::Types::Void); for (size_t i = 1; i < argsSize - 1; i++) { CHECK_ARG_TYPE(args[i], ValueKind::kNumber); - nativeScriptFunction->mParams.push_back(magic_enum::enum_cast(args[i].toInt()).value_or(NativeFunction::Types::Void)); + nativeScriptFunction->mParams.push_back( + magic_enum::enum_cast(args[i].toInt()).value_or(NativeFunction::Types::Void) + ); } - nativeScriptFunction->mEngine = args.engine(); - nativeScriptFunction->mNativeCallack = dcbNewCallback(nativeScriptFunction->buildDynCallbackSig().c_str(), &nativeCallbackHandler, nativeScriptFunction); - nativeScriptFunction->mFunction = nativeScriptFunction->mNativeCallack; + nativeScriptFunction->mEngine = args.engine(); + nativeScriptFunction->mNativeCallack = dcbNewCallback( + nativeScriptFunction->buildDynCallbackSig().c_str(), + &nativeCallbackHandler, + nativeScriptFunction + ); + nativeScriptFunction->mFunction = nativeScriptFunction->mNativeCallack; nativeScriptFunction->mScriptCallback = args[args.size() - 1].asFunction(); return scriptResult; @@ -358,115 +365,115 @@ char NativeFunction::nativeCallbackHandler(DCCallback* cb, DCArgs* args, DCValue vector> paras; for (int i = 0; i < hookInfo->mParams.size(); ++i) { switch (hookInfo->mParams[i]) { - case NativeFunction::Types::Bool: - paras.emplace_back(Boolean::newBoolean(dcbArgBool(args))); - break; - case NativeFunction::Types::Char: - paras.emplace_back(Number::newNumber(dcbArgChar(args))); - break; - case NativeFunction::Types::UnsignedChar: - paras.emplace_back(Number::newNumber(dcbArgUChar(args))); - break; - case NativeFunction::Types::Short: - paras.emplace_back(Number::newNumber(dcbArgShort(args))); - break; - case NativeFunction::Types::UnsignedShort: - paras.emplace_back(Number::newNumber(dcbArgUShort(args))); - break; - case NativeFunction::Types::Int: - paras.emplace_back(Number::newNumber(dcbArgInt(args))); - break; - case NativeFunction::Types::UnsignedInt: - paras.emplace_back(Number::newNumber((int)dcbArgUInt(args))); - break; - case NativeFunction::Types::Long: - paras.emplace_back(Number::newNumber((int)dcbArgLong(args))); - break; - case NativeFunction::Types::UnsignedLong: - paras.emplace_back(Number::newNumber((int)dcbArgULong(args))); - break; - case NativeFunction::Types::LongLong: - paras.emplace_back(Number::newNumber(dcbArgLongLong(args))); - break; - case NativeFunction::Types::UnsignedLongLong: - paras.emplace_back(Number::newNumber((long long)dcbArgULongLong(args))); - break; - case NativeFunction::Types::Float: - paras.emplace_back(Number::newNumber(dcbArgFloat(args))); - break; - case NativeFunction::Types::Double: - paras.emplace_back(Number::newNumber(dcbArgDouble(args))); - break; - case NativeFunction::Types::Pointer: - paras.emplace_back(NativePointer::newNativePointer((NativePointer*)dcbArgPointer(args))); - break; - default: - break; - } - } - - Local res = hookInfo->mScriptCallback.get().call({}, paras); - - switch (hookInfo->mReturnVal) { case NativeFunction::Types::Bool: - result->c = res.asBoolean().value();// pass bool by char + paras.emplace_back(Boolean::newBoolean(dcbArgBool(args))); break; case NativeFunction::Types::Char: - result->c = (char)res.toInt(); + paras.emplace_back(Number::newNumber(dcbArgChar(args))); break; case NativeFunction::Types::UnsignedChar: - result->C = (unsigned char)res.toInt(); + paras.emplace_back(Number::newNumber(dcbArgUChar(args))); break; case NativeFunction::Types::Short: - result->s = (short)res.toInt(); + paras.emplace_back(Number::newNumber(dcbArgShort(args))); break; case NativeFunction::Types::UnsignedShort: - result->S = (unsigned short)res.toInt(); + paras.emplace_back(Number::newNumber(dcbArgUShort(args))); break; case NativeFunction::Types::Int: - result->i = (int)res.toInt(); + paras.emplace_back(Number::newNumber(dcbArgInt(args))); break; case NativeFunction::Types::UnsignedInt: - result->I = (unsigned int)res.toInt(); + paras.emplace_back(Number::newNumber((int)dcbArgUInt(args))); break; case NativeFunction::Types::Long: - result->j = (long)res.toInt(); + paras.emplace_back(Number::newNumber((int)dcbArgLong(args))); break; case NativeFunction::Types::UnsignedLong: - result->J = (unsigned long)res.toInt(); + paras.emplace_back(Number::newNumber((int)dcbArgULong(args))); break; case NativeFunction::Types::LongLong: - result->l = (long long)res.asNumber().toInt64(); + paras.emplace_back(Number::newNumber(dcbArgLongLong(args))); break; case NativeFunction::Types::UnsignedLongLong: - result->L = (unsigned long long)res.asNumber().toInt64(); + paras.emplace_back(Number::newNumber((long long)dcbArgULongLong(args))); break; case NativeFunction::Types::Float: - result->f = res.asNumber().toFloat(); + paras.emplace_back(Number::newNumber(dcbArgFloat(args))); break; case NativeFunction::Types::Double: - result->d = res.asNumber().toDouble(); + paras.emplace_back(Number::newNumber(dcbArgDouble(args))); break; case NativeFunction::Types::Pointer: - switch (res.getKind()) { - case ValueKind::kObject: - result->p = NativePointer::extract(res); - break; - case ValueKind::kNumber: - result->p = (void*)res.asNumber().toInt64(); - break; - case ValueKind::kNull: - default: - result->p = nullptr; - break; - } + paras.emplace_back(NativePointer::newNativePointer((NativePointer*)dcbArgPointer(args))); + break; + default: + break; + } + } + + Local res = hookInfo->mScriptCallback.get().call({}, paras); + + switch (hookInfo->mReturnVal) { + case NativeFunction::Types::Bool: + result->c = res.asBoolean().value(); // pass bool by char + break; + case NativeFunction::Types::Char: + result->c = (char)res.toInt(); + break; + case NativeFunction::Types::UnsignedChar: + result->C = (unsigned char)res.toInt(); + break; + case NativeFunction::Types::Short: + result->s = (short)res.toInt(); + break; + case NativeFunction::Types::UnsignedShort: + result->S = (unsigned short)res.toInt(); + break; + case NativeFunction::Types::Int: + result->i = (int)res.toInt(); + break; + case NativeFunction::Types::UnsignedInt: + result->I = (unsigned int)res.toInt(); + break; + case NativeFunction::Types::Long: + result->j = (long)res.toInt(); + break; + case NativeFunction::Types::UnsignedLong: + result->J = (unsigned long)res.toInt(); + break; + case NativeFunction::Types::LongLong: + result->l = (long long)res.asNumber().toInt64(); + break; + case NativeFunction::Types::UnsignedLongLong: + result->L = (unsigned long long)res.asNumber().toInt64(); + break; + case NativeFunction::Types::Float: + result->f = res.asNumber().toFloat(); + break; + case NativeFunction::Types::Double: + result->d = res.asNumber().toDouble(); + break; + case NativeFunction::Types::Pointer: + switch (res.getKind()) { + case ValueKind::kObject: + result->p = NativePointer::extract(res); + break; + case ValueKind::kNumber: + result->p = (void*)res.asNumber().toInt64(); break; + case ValueKind::kNull: default: + result->p = nullptr; break; + } + break; + default: + break; } } catch (const Exception& e) { logger.error("Hook Callback Failed!"); - logger.error("Message: {}",e.message()); + logger.error("Message: {}", e.message()); logger.error("StackTrace: {}", e.stacktrace()); logger.error("In Symbol: " + hookInfo->mSymbol); logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); @@ -477,12 +484,12 @@ char NativeFunction::nativeCallbackHandler(DCCallback* cb, DCArgs* args, DCValue Local ScriptNativeFunction::setAddress(const Local& value) { - auto engine = this->getScriptEngine(); + auto engine = this->getScriptEngine(); bool isNativePointer = engine->isInstanceOf(value); - bool isInt64 = value.getKind() == ValueKind::kNumber; + bool isInt64 = value.getKind() == ValueKind::kNumber; if (isNativePointer) { NativePointer* ptr = engine->getNativeInstance(value); - this->mFunction = ptr->unwrap(); + this->mFunction = ptr->unwrap(); return Local(); } if (isInt64) { @@ -502,14 +509,20 @@ Local ScriptNativeFunction::getAddress() { Local ScriptNativeFunction::hook(const Arguments& args) { CHECK_ARGS_COUNT(args, 1); CHECK_ARG_TYPE(args[0], ValueKind::kFunction); - auto scriptResult = args.engine()->newNativeClass(args.thiz()); - DynamicHookData* hookSymbol = args.engine()->getNativeInstance(scriptResult); + auto scriptResult = args.engine()->newNativeClass(args.thiz()); + DynamicHookData* hookSymbol = args.engine()->getNativeInstance(scriptResult); hookSymbol->cloneFrom(NativeFunction(*args.engine()->getNativeInstance(args.thiz()))); hookSymbol->mEngine = args.engine(); - hookSymbol->mNativeCallack = dcbNewCallback(hookSymbol->buildDynCallbackSig().c_str(), &nativeCallbackHandler, hookSymbol); + hookSymbol->mNativeCallack = + dcbNewCallback(hookSymbol->buildDynCallbackSig().c_str(), &nativeCallbackHandler, hookSymbol); hookSymbol->mScriptCallback = args[0].asFunction(); - void* hookOriginl = nullptr; - int hookResult = ll::memory::hook(hookSymbol->mFunction, &hookOriginl, (ll::memory::FuncPtr*)hookSymbol->mNativeCallack,ll::memory::HookPriority::Low); + void* hookOriginl = nullptr; + int hookResult = ll::memory::hook( + hookSymbol->mFunction, + &hookOriginl, + (ll::memory::FuncPtr*)hookSymbol->mNativeCallack, + ll::memory::HookPriority::Low + ); hookSymbol->mFunction = hookOriginl; return scriptResult; } diff --git a/src/api/NativeAPI.h b/src/api/NativeAPI.h index 59387367..94343af3 100644 --- a/src/api/NativeAPI.h +++ b/src/api/NativeAPI.h @@ -8,223 +8,214 @@ class NativeFunction { public: - // TypesEnum - enum class Types : int { - Void, - Bool, - Char, - UnsignedChar, - Short, - UnsignedShort, - Int, - UnsignedInt, - Long, - UnsignedLong, - LongLong, - UnsignedLongLong, - Float, - Double, - Pointer, - }; - - template static Local getType() { - return Number::newNumber((int)T); - } - // Data Members - NativeFunction::Types mReturnVal = NativeFunction::Types::Void; - vector mParams = {}; - std::string mSymbol = "unknown"; - void *mFunction = nullptr; - - // Dyncall Helper - - /* get dynamic call signature char for Type*/ - static char getTypeSignature(NativeFunction::Types type); - /* get NativeFunction::Type from LLVM Ast Node*/ - static NativeFunction::Types - getNativeType(demangler::ms_demangle::Node *type); - /* get dynamic call signature string for this function*/ - std::string buildDynCallbackSig(); - - // Script Helper - /* get a script::Function instance for scripts to call*/ - Local getCallableFunction(); - /* call NativeFunction by using DynamicCallVM, internel api*/ - static Local callNativeFunction(DCCallVM *vm, - NativeFunction *funcSymbol, - const Arguments &args); - /* shared Hook Callback function that wrap script callback*/ - static char nativeCallbackHandler(DCCallback *cb, DCArgs *args, - DCValue *result, void *userdata); - - // Cache Helper - static Concurrency::concurrent_unordered_map - parsedSymbol; - static NativeFunction getOrParse(const std::string &symbol); - - /* clone from other NativeFunction instance*/ - inline void cloneFrom(const NativeFunction &i) { - this->mReturnVal = i.mReturnVal; - this->mParams = i.mParams; - this->mSymbol = i.mSymbol; - this->mFunction = i.mFunction; - } + // TypesEnum + enum class Types : int { + Void, + Bool, + Char, + UnsignedChar, + Short, + UnsignedShort, + Int, + UnsignedInt, + Long, + UnsignedLong, + LongLong, + UnsignedLongLong, + Float, + Double, + Pointer, + }; + + template + static Local getType() { + return Number::newNumber((int)T); + } + // Data Members + NativeFunction::Types mReturnVal = NativeFunction::Types::Void; + vector mParams = {}; + std::string mSymbol = "unknown"; + void* mFunction = nullptr; + + // Dyncall Helper + + /* get dynamic call signature char for Type*/ + static char getTypeSignature(NativeFunction::Types type); + /* get NativeFunction::Type from LLVM Ast Node*/ + static NativeFunction::Types getNativeType(demangler::ms_demangle::Node* type); + /* get dynamic call signature string for this function*/ + std::string buildDynCallbackSig(); + + // Script Helper + /* get a script::Function instance for scripts to call*/ + Local getCallableFunction(); + /* call NativeFunction by using DynamicCallVM, internel api*/ + static Local callNativeFunction(DCCallVM* vm, NativeFunction* funcSymbol, const Arguments& args); + /* shared Hook Callback function that wrap script callback*/ + static char nativeCallbackHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata); + + // Cache Helper + static Concurrency::concurrent_unordered_map parsedSymbol; + static NativeFunction getOrParse(const std::string& symbol); + + /* clone from other NativeFunction instance*/ + inline void cloneFrom(const NativeFunction& i) { + this->mReturnVal = i.mReturnVal; + this->mParams = i.mParams; + this->mSymbol = i.mSymbol; + this->mFunction = i.mFunction; + } }; class ScriptNativeFunction : public NativeFunction, public ScriptClass { public: - explicit ScriptNativeFunction(const Local &scriptObj) - : ScriptClass(scriptObj) {} - explicit ScriptNativeFunction(const Local &scriptObj, - const NativeFunction &symbol) - : NativeFunction(symbol), ScriptClass(scriptObj) {} - - /* create NativeFunction instance from mangled symbol - * dlsym will be called to query the address - * > NativeFunction.fromSymbol(string"?xxx@xxx") - */ - static Local fromSymbol(const Arguments &args); - - /* create NativeFunction by describe the arguments - * you should set address manually before you call or hook it - * > NativeFunction.fromDescribe(RetuenValue: NativeTypes.Void, Params: - * [NativeType.Int......]) - */ - static Local fromDescription(const Arguments &args); - - /* create NativeFunction that wrap Script Function by describe the arguments - * > NativeFunction.fromScript(RetuenValue: NativeTypes.Void, Params: - * [NativeType.Int......], Callback: func(Params...){}) - */ - static Local fromScript(const Arguments &args); - Local setAddress(const Local &value); - Local getAddress(); - - /* Hook current NativeFunction by passing a fuction - * > NativeFunction.hook(CallBack: func(a1,a2,a3...){}) - */ - Local hook(const Arguments &args); + explicit ScriptNativeFunction(const Local& scriptObj) : ScriptClass(scriptObj) {} + explicit ScriptNativeFunction(const Local& scriptObj, const NativeFunction& symbol) + : NativeFunction(symbol), + ScriptClass(scriptObj) {} + + /* create NativeFunction instance from mangled symbol + * dlsym will be called to query the address + * > NativeFunction.fromSymbol(string"?xxx@xxx") + */ + static Local fromSymbol(const Arguments& args); + + /* create NativeFunction by describe the arguments + * you should set address manually before you call or hook it + * > NativeFunction.fromDescribe(RetuenValue: NativeTypes.Void, Params: + * [NativeType.Int......]) + */ + static Local fromDescription(const Arguments& args); + + /* create NativeFunction that wrap Script Function by describe the arguments + * > NativeFunction.fromScript(RetuenValue: NativeTypes.Void, Params: + * [NativeType.Int......], Callback: func(Params...){}) + */ + static Local fromScript(const Arguments& args); + Local setAddress(const Local& value); + Local getAddress(); + + /* Hook current NativeFunction by passing a fuction + * > NativeFunction.hook(CallBack: func(a1,a2,a3...){}) + */ + Local hook(const Arguments& args); }; class DynamicHookData : public ScriptNativeFunction { public: - script::ScriptEngine *mEngine = nullptr; - DCCallback *mNativeCallack = nullptr; - script::Global mScriptCallback; - explicit DynamicHookData(const Local &scriptObj) - : ScriptNativeFunction(scriptObj) {} - explicit DynamicHookData(const Local &scriptObj, - const NativeFunction &symbol) - : ScriptNativeFunction(scriptObj, symbol) {} + script::ScriptEngine* mEngine = nullptr; + DCCallback* mNativeCallack = nullptr; + script::Global mScriptCallback; + explicit DynamicHookData(const Local& scriptObj) : ScriptNativeFunction(scriptObj) {} + explicit DynamicHookData(const Local& scriptObj, const NativeFunction& symbol) + : ScriptNativeFunction(scriptObj, symbol) {} }; class NativePointer : public ScriptClass { private: - void *mPtr; + void* mPtr; public: - explicit NativePointer(void *); + explicit NativePointer(void*); - static void *extract(Local v); + static void* extract(Local v); - static Local newNativePointer(void *); + static Local newNativePointer(void*); - void *wrap() { return ll::memory::dAccess(this, 0); } + void* wrap() { return ll::memory::dAccess(this, 0); } - void *unwrap() { return (void *)&(*((int *)mPtr)); } + void* unwrap() { return (void*)&(*((int*)mPtr)); } - void *get() { return mPtr; } + void* get() { return mPtr; } - void set(void *ptr) { mPtr = ptr; }; + void set(void* ptr) { mPtr = ptr; }; - static Local fromAddress(const Arguments &args); + static Local fromAddress(const Arguments& args); - static Local fromSymbol(const Arguments &args); + static Local fromSymbol(const Arguments& args); - static Local mallocMem(const Arguments &args); + static Local mallocMem(const Arguments& args); - static Local freeMem(const Arguments &args); + static Local freeMem(const Arguments& args); - Local asRawAddress(const Arguments &args); + Local asRawAddress(const Arguments& args); - Local asHexAddress(const Arguments &args); + Local asHexAddress(const Arguments& args); - Local offset(const Arguments &args); + Local offset(const Arguments& args); - Local isNull(const Arguments &args); + Local isNull(const Arguments& args); - Local asRef(const Arguments &args); + Local asRef(const Arguments& args); - Local deRef(const Arguments &args); + Local deRef(const Arguments& args); - void setMemByte(const Local &value); - void setChar(const Local &value); - void setUchar(const Local &value); - void setShort(const Local &value); - void setUshort(const Local &value); - void setInt(const Local &value); - void setUint(const Local &value); - void setLong(const Local &value); - void setUlong(const Local &value); - void setLonglong(const Local &value); - void setUlonglong(const Local &value); - void setFloat(const Local &value); - void setDouble(const Local &value); - void setString(const Local &value); - void setBool(const Local &value); + void setMemByte(const Local& value); + void setChar(const Local& value); + void setUchar(const Local& value); + void setShort(const Local& value); + void setUshort(const Local& value); + void setInt(const Local& value); + void setUint(const Local& value); + void setLong(const Local& value); + void setUlong(const Local& value); + void setLonglong(const Local& value); + void setUlonglong(const Local& value); + void setFloat(const Local& value); + void setDouble(const Local& value); + void setString(const Local& value); + void setBool(const Local& value); - Local getMemByte(); - Local getChar(); - Local getUchar(); - Local getShort(); - Local getUshort(); - Local getInt(); - Local getUint(); - Local getLong(); - Local getUlong(); - Local getLonglong(); - Local getUlonglong(); - Local getFloat(); - Local getDouble(); - Local getString(); - Local getBool(); + Local getMemByte(); + Local getChar(); + Local getUchar(); + Local getShort(); + Local getUshort(); + Local getInt(); + Local getUint(); + Local getLong(); + Local getUlong(); + Local getLonglong(); + Local getUlonglong(); + Local getFloat(); + Local getDouble(); + Local getString(); + Local getBool(); - Local asStdString(); - Local asEntity(); - Local asItem(); - Local asPlayer(); - Local asContainer(); + Local asStdString(); + Local asEntity(); + Local asItem(); + Local asPlayer(); + Local asContainer(); }; class NativePatch : public ScriptClass { public: - explicit NativePatch(const Local &scriptObj) - : ScriptClass(scriptObj) {} - static Local search(const Arguments &args); - static Local patch(const Arguments &args); - static Local dump(const Arguments &args); + explicit NativePatch(const Local& scriptObj) : ScriptClass(scriptObj) {} + static Local search(const Arguments& args); + static Local patch(const Arguments& args); + static Local dump(const Arguments& args); }; class GlobalNativePointer : public ScriptClass { public: - explicit GlobalNativePointer(const Local &scriptObj) - : ScriptClass(scriptObj) {} - static Local getLevelPtr(const Arguments &args); - static Local getMinecraftPtr(const Arguments &args); - static Local getServerNetworkHandlerPtr(const Arguments &args); - static Local getMinecraftCommandsPtr(const Arguments &args); - static Local getLevelStoragePtr(const Arguments &args); - static Local getDBStoragePtr(const Arguments &args); - static Local getRakNetServerLocatorPtr(const Arguments &args); - static Local getRakNetRakPeerPtr(const Arguments &args); - static Local getScoreboardPtr(const Arguments &args); - static Local getAllowListFilePtr(const Arguments &args); - static Local getPropertiesSettingsPtr(const Arguments &args); + explicit GlobalNativePointer(const Local& scriptObj) : ScriptClass(scriptObj) {} + static Local getLevelPtr(const Arguments& args); + static Local getMinecraftPtr(const Arguments& args); + static Local getServerNetworkHandlerPtr(const Arguments& args); + static Local getMinecraftCommandsPtr(const Arguments& args); + static Local getLevelStoragePtr(const Arguments& args); + static Local getDBStoragePtr(const Arguments& args); + static Local getRakNetServerLocatorPtr(const Arguments& args); + static Local getRakNetRakPeerPtr(const Arguments& args); + static Local getScoreboardPtr(const Arguments& args); + static Local getAllowListFilePtr(const Arguments& args); + static Local getPropertiesSettingsPtr(const Arguments& args); }; // export apis -extern ClassDefine NativeTypeEnumBuilder; +extern ClassDefine NativeTypeEnumBuilder; extern ClassDefine NativeCallBuilder; -extern ClassDefine NativeHookBuilder; -extern ClassDefine NativePointerBuilder; -extern ClassDefine NativePatchBuilder; -extern ClassDefine GlobalNativePointerBuilder; +extern ClassDefine NativeHookBuilder; +extern ClassDefine NativePointerBuilder; +extern ClassDefine NativePatchBuilder; +extern ClassDefine GlobalNativePointerBuilder; diff --git a/src/api/NativePointer.cpp b/src/api/NativePointer.cpp index 20345f10..3c64daeb 100644 --- a/src/api/NativePointer.cpp +++ b/src/api/NativePointer.cpp @@ -22,36 +22,21 @@ ClassDefine NativePointerBuilder = .instanceFunction("deRef", &NativePointer::deRef) .instanceFunction("isNull", &NativePointer::isNull) .instanceFunction("offset", &NativePointer::offset) - .instanceProperty("byte", &NativePointer::getMemByte, - &NativePointer::setMemByte) - .instanceProperty("int8", &NativePointer::getChar, - &NativePointer::setChar) - .instanceProperty("uint8", &NativePointer::getUchar, - &NativePointer::setUchar) - .instanceProperty("int16", &NativePointer::getShort, - &NativePointer::setShort) - .instanceProperty("uint16", &NativePointer::getUshort, - &NativePointer::setUshort) - .instanceProperty("int32", &NativePointer::getInt, - &NativePointer::setInt) - .instanceProperty("uint32", &NativePointer::getUint, - &NativePointer::setUint) - .instanceProperty("long", &NativePointer::getLong, - &NativePointer::setLong) - .instanceProperty("ulong", &NativePointer::getUlong, - &NativePointer::setUlong) - .instanceProperty("int64", &NativePointer::getLonglong, - &NativePointer::setLonglong) - .instanceProperty("uint64", &NativePointer::getUlonglong, - &NativePointer::setUlonglong) - .instanceProperty("float", &NativePointer::getFloat, - &NativePointer::setFloat) - .instanceProperty("double", &NativePointer::getDouble, - &NativePointer::setDouble) - .instanceProperty("string", &NativePointer::getString, - &NativePointer::setString) - .instanceProperty("bool", &NativePointer::getBool, - &NativePointer::setBool) + .instanceProperty("byte", &NativePointer::getMemByte, &NativePointer::setMemByte) + .instanceProperty("int8", &NativePointer::getChar, &NativePointer::setChar) + .instanceProperty("uint8", &NativePointer::getUchar, &NativePointer::setUchar) + .instanceProperty("int16", &NativePointer::getShort, &NativePointer::setShort) + .instanceProperty("uint16", &NativePointer::getUshort, &NativePointer::setUshort) + .instanceProperty("int32", &NativePointer::getInt, &NativePointer::setInt) + .instanceProperty("uint32", &NativePointer::getUint, &NativePointer::setUint) + .instanceProperty("long", &NativePointer::getLong, &NativePointer::setLong) + .instanceProperty("ulong", &NativePointer::getUlong, &NativePointer::setUlong) + .instanceProperty("int64", &NativePointer::getLonglong, &NativePointer::setLonglong) + .instanceProperty("uint64", &NativePointer::getUlonglong, &NativePointer::setUlonglong) + .instanceProperty("float", &NativePointer::getFloat, &NativePointer::setFloat) + .instanceProperty("double", &NativePointer::getDouble, &NativePointer::setDouble) + .instanceProperty("string", &NativePointer::getString, &NativePointer::setString) + .instanceProperty("bool", &NativePointer::getBool, &NativePointer::setBool) .instanceFunction("asStdString", &NativePointer::asStdString) .instanceFunction("asEntity", &NativePointer::asEntity) @@ -60,387 +45,375 @@ ClassDefine NativePointerBuilder = .instanceFunction("asContainer", &NativePointer::asContainer) .build(); -NativePointer::NativePointer(void *p) - : ScriptClass(ScriptClass::ConstructFromCpp{}) { - set(p); -} +NativePointer::NativePointer(void* p) : ScriptClass(ScriptClass::ConstructFromCpp{}) { set(p); } -Local NativePointer::fromAddress(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - if (args[0].isString()) { - std::stringstream ss; - ss << std::hex << args[0].asString().toString(); - uintptr_t res; - ss >> res; - return newNativePointer((void *)res); +Local NativePointer::fromAddress(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + if (args[0].isString()) { + std::stringstream ss; + ss << std::hex << args[0].asString().toString(); + uintptr_t res; + ss >> res; + return newNativePointer((void*)res); - } else if (args[0].isNumber()) { - return newNativePointer((void *)args[0].asNumber().toInt64()); - } - LOG_WRONG_ARG_TYPE(); - return Local(); + } else if (args[0].isNumber()) { + return newNativePointer((void*)args[0].asNumber().toInt64()); + } + LOG_WRONG_ARG_TYPE(); + return Local(); } -Local NativePointer::fromSymbol(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local NativePointer::fromSymbol(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - return newNativePointer( - ll::memory::resolveSymbol(args[0].asString().toStringHolder().c_str())); + return newNativePointer(ll::memory::resolveSymbol(args[0].asString().toStringHolder().c_str())); } -Local NativePointer::mallocMem(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - size_t size = args[0].asNumber().toInt64(); - return newNativePointer(malloc(size)); +Local NativePointer::mallocMem(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + size_t size = args[0].asNumber().toInt64(); + return newNativePointer(malloc(size)); } // directly free memblock in c runtime -Local NativePointer::freeMem(const Arguments &args) { - void *memObj = nullptr; - CHECK_ARGS_COUNT(args, 1); - if (args[0].isObject()) { - memObj = NativePointer::extract(args[0]); - } else if (args[0].isNumber()) { - *((__int64 *)&memObj) = args[0].asNumber().toInt64(); - } - - if (!memObj) { - throw std::runtime_error("free(nullptr)"); - } - free(memObj); - return Local(); -} - -Local NativePointer::newNativePointer(void *ptr) { - auto out = new NativePointer(ptr); - return out->getScriptObject(); -} - -void *NativePointer::extract(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine() - ->getNativeInstance(v) - ->get(); - else - return nullptr; -} - -Local NativePointer::asRawAddress(const Arguments &args) { - try { - void *pkt = unwrap(); - if (!pkt) - return Local(); - return Number::newNumber((intptr_t)pkt); - } - CATCH("Fail in NativePointer::asPointer!") -} - -Local NativePointer::asHexAddress(const Arguments &args) { - try { - void *pkt = unwrap(); - if (!pkt) - return Local(); - std::stringstream ss; - ss << std::hex << (intptr_t)pkt; - return String::newString(ss.str()); - } - CATCH("Fail in NativePointer::asHexStr!") -} - -Local NativePointer::asRef(const Arguments &args) { - try { - return newNativePointer((void *)&mPtr); - } - CATCH("Fail in NativePointer::asRef!") -} - -Local NativePointer::deRef(const Arguments &args) { - try { - return newNativePointer(*(void **)mPtr); - } - CATCH("Fail in NativePointer::deRef!") -} - -Local NativePointer::isNull(const Arguments &args) { - try { - return script::Boolean::newBoolean(mPtr == nullptr); - } - CATCH("Fail in NativePointer::isNull!") -} - -Local NativePointer::offset(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - auto ptr = get(); - if (!ptr) - return Local(); - return newNativePointer( - (void *)((uintptr_t)ptr + args[0].asNumber().toInt32())); - } - CATCH("Fail in NativePointer::offset!") +Local NativePointer::freeMem(const Arguments& args) { + void* memObj = nullptr; + CHECK_ARGS_COUNT(args, 1); + if (args[0].isObject()) { + memObj = NativePointer::extract(args[0]); + } else if (args[0].isNumber()) { + *((__int64*)&memObj) = args[0].asNumber().toInt64(); + } + + if (!memObj) { + throw std::runtime_error("free(nullptr)"); + } + free(memObj); + return Local(); +} + +Local NativePointer::newNativePointer(void* ptr) { + auto out = new NativePointer(ptr); + return out->getScriptObject(); +} + +void* NativePointer::extract(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v)->get(); + else return nullptr; +} + +Local NativePointer::asRawAddress(const Arguments& args) { + try { + void* pkt = unwrap(); + if (!pkt) return Local(); + return Number::newNumber((intptr_t)pkt); + } + CATCH("Fail in NativePointer::asPointer!") +} + +Local NativePointer::asHexAddress(const Arguments& args) { + try { + void* pkt = unwrap(); + if (!pkt) return Local(); + std::stringstream ss; + ss << std::hex << (intptr_t)pkt; + return String::newString(ss.str()); + } + CATCH("Fail in NativePointer::asHexStr!") +} + +Local NativePointer::asRef(const Arguments& args) { + try { + return newNativePointer((void*)&mPtr); + } + CATCH("Fail in NativePointer::asRef!") +} + +Local NativePointer::deRef(const Arguments& args) { + try { + return newNativePointer(*(void**)mPtr); + } + CATCH("Fail in NativePointer::deRef!") +} + +Local NativePointer::isNull(const Arguments& args) { + try { + return script::Boolean::newBoolean(mPtr == nullptr); + } + CATCH("Fail in NativePointer::isNull!") +} + +Local NativePointer::offset(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + try { + auto ptr = get(); + if (!ptr) return Local(); + return newNativePointer((void*)((uintptr_t)ptr + args[0].asNumber().toInt32())); + } + CATCH("Fail in NativePointer::offset!") } Local NativePointer::getMemByte() { - try { - return String::newString("0"); - } - CATCH("Fail in NativePointer::getMemByte!") + try { + return String::newString("0"); + } + CATCH("Fail in NativePointer::getMemByte!") } -void NativePointer::setMemByte(const Local &value) { +void NativePointer::setMemByte(const Local& value) { - logger.error("Fail to set mem!"); - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); + logger.error("Fail to set mem!"); + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); } Local NativePointer::getChar() { - try { - return Number::newNumber(*(char *)get()); - } - CATCH("Fail in NativePointer::getChar!") + try { + return Number::newNumber(*(char*)get()); + } + CATCH("Fail in NativePointer::getChar!") } -void NativePointer::setChar(const Local &value) { - try { - *(char *)get() = (char)value.asNumber().toInt32(); - } catch (...) { - logger.error("Fail to set char!"); - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); - } +void NativePointer::setChar(const Local& value) { + try { + *(char*)get() = (char)value.asNumber().toInt32(); + } catch (...) { + logger.error("Fail to set char!"); + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); + } } Local NativePointer::getUchar() { - try { - return Number::newNumber(*(unsigned char *)get()); - } - CATCH("Fail in NativePointer::getUchar!") -} -void NativePointer::setUchar(const Local &value) { - try { - *(unsigned char *)get() = (unsigned char)value.asNumber().toInt32(); - } catch (...) { - logger.error("Fail to set uchar!"); - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); - } + try { + return Number::newNumber(*(unsigned char*)get()); + } + CATCH("Fail in NativePointer::getUchar!") +} +void NativePointer::setUchar(const Local& value) { + try { + *(unsigned char*)get() = (unsigned char)value.asNumber().toInt32(); + } catch (...) { + logger.error("Fail to set uchar!"); + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); + } } Local NativePointer::getShort() { - try { - return Number::newNumber(*(short *)get()); - } - CATCH("Fail in NativePointer::getShort!") -} -void NativePointer::setShort(const Local &value) { - try { - *(short *)get() = (short)value.asNumber().toInt32(); - } catch (...) { - logger.error("Fail to set short!"); - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); - } + try { + return Number::newNumber(*(short*)get()); + } + CATCH("Fail in NativePointer::getShort!") +} +void NativePointer::setShort(const Local& value) { + try { + *(short*)get() = (short)value.asNumber().toInt32(); + } catch (...) { + logger.error("Fail to set short!"); + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); + } } Local NativePointer::getUshort() { - try { - return Number::newNumber(*(unsigned short *)get()); - } - CATCH("Fail in NativePointer::getUshort!") -} -void NativePointer::setUshort(const Local &value) { - try { - *(unsigned short *)get() = (unsigned short)value.asNumber().toInt32(); - } catch (...) { - logger.error("Fail to set ushort!"); - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); - } + try { + return Number::newNumber(*(unsigned short*)get()); + } + CATCH("Fail in NativePointer::getUshort!") +} +void NativePointer::setUshort(const Local& value) { + try { + *(unsigned short*)get() = (unsigned short)value.asNumber().toInt32(); + } catch (...) { + logger.error("Fail to set ushort!"); + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); + } } Local NativePointer::getInt() { - try { - return Number::newNumber(*(int *)get()); - } - CATCH("Fail in NativePointer::getInt!") -} -void NativePointer::setInt(const Local &value) { - try { - *(int *)get() = (int)value.asNumber().toInt32(); - } catch (...) { - logger.error("Fail to set int!"); - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); - } + try { + return Number::newNumber(*(int*)get()); + } + CATCH("Fail in NativePointer::getInt!") +} +void NativePointer::setInt(const Local& value) { + try { + *(int*)get() = (int)value.asNumber().toInt32(); + } catch (...) { + logger.error("Fail to set int!"); + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); + } } Local NativePointer::getUint() { - try { - return Number::newNumber(*(long long *)get()); - } - CATCH("Fail in NativePointer::getUint!") -} -void NativePointer::setUint(const Local &value) { - try { - *(unsigned int *)get() = (unsigned int)value.asNumber().toInt64(); - } catch (...) { - logger.error("Fail to set uint!"); - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); - } + try { + return Number::newNumber(*(long long*)get()); + } + CATCH("Fail in NativePointer::getUint!") +} +void NativePointer::setUint(const Local& value) { + try { + *(unsigned int*)get() = (unsigned int)value.asNumber().toInt64(); + } catch (...) { + logger.error("Fail to set uint!"); + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); + } } Local NativePointer::getLong() { - try { - return Number::newNumber(*(long long *)get()); - } - CATCH("Fail in NativePointer::getLong!") -} -void NativePointer::setLong(const Local &value) { - try { - *(long *)get() = (long)value.asNumber().toInt64(); - } catch (...) { - logger.error("Fail to set long!"); - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); - } + try { + return Number::newNumber(*(long long*)get()); + } + CATCH("Fail in NativePointer::getLong!") +} +void NativePointer::setLong(const Local& value) { + try { + *(long*)get() = (long)value.asNumber().toInt64(); + } catch (...) { + logger.error("Fail to set long!"); + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); + } } Local NativePointer::getUlong() { - try { - return Number::newNumber(*(long long *)get()); - } - CATCH("Fail in NativePointer::getUlong!") -} -void NativePointer::setUlong(const Local &value) { - try { - *(unsigned long *)get() = (unsigned long)value.asNumber().toInt64(); - } catch (...) { - logger.error("Fail to set ulong!"); - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); - } + try { + return Number::newNumber(*(long long*)get()); + } + CATCH("Fail in NativePointer::getUlong!") +} +void NativePointer::setUlong(const Local& value) { + try { + *(unsigned long*)get() = (unsigned long)value.asNumber().toInt64(); + } catch (...) { + logger.error("Fail to set ulong!"); + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); + } } Local NativePointer::getLonglong() { - try { - return Number::newNumber(*(long long *)get()); - } - CATCH("Fail in NativePointer::getLonglong!") + try { + return Number::newNumber(*(long long*)get()); + } + CATCH("Fail in NativePointer::getLonglong!") } -void NativePointer::setLonglong(const Local &value) { - try { - *(long long *)get() = (long long)value.asNumber().toInt64(); - } catch (...) { - logger.error("Fail to set longlong!"); - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); - } +void NativePointer::setLonglong(const Local& value) { + try { + *(long long*)get() = (long long)value.asNumber().toInt64(); + } catch (...) { + logger.error("Fail to set longlong!"); + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); + } } Local NativePointer::getUlonglong() { - try { - return Number::newNumber(*(long long *)get()); - } - CATCH("Fail in NativePointer::getUlonglong!") -} -void NativePointer::setUlonglong(const Local &value) { - try { - *(unsigned long long *)get() = - (unsigned long long)value.asNumber().toInt64(); - } catch (...) { - logger.error("Fail to set ulonglong!"); - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); - } + try { + return Number::newNumber(*(long long*)get()); + } + CATCH("Fail in NativePointer::getUlonglong!") +} +void NativePointer::setUlonglong(const Local& value) { + try { + *(unsigned long long*)get() = (unsigned long long)value.asNumber().toInt64(); + } catch (...) { + logger.error("Fail to set ulonglong!"); + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); + } } Local NativePointer::getFloat() { - try { - return Number::newNumber(*(float *)get()); - } - CATCH("Fail in NativePointer::getFloat!") -} -void NativePointer::setFloat(const Local &value) { - try { - *(float *)get() = (float)value.asNumber().toFloat(); - } catch (...) { - logger.error("Fail to set float!"); - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); - } + try { + return Number::newNumber(*(float*)get()); + } + CATCH("Fail in NativePointer::getFloat!") +} +void NativePointer::setFloat(const Local& value) { + try { + *(float*)get() = (float)value.asNumber().toFloat(); + } catch (...) { + logger.error("Fail to set float!"); + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); + } } Local NativePointer::getDouble() { - try { - return Number::newNumber(*(double *)get()); - } - CATCH("Fail in NativePointer::getDouble!") -} -void NativePointer::setDouble(const Local &value) { - try { - *(double *)get() = (double)value.asNumber().toFloat(); - } catch (...) { - logger.error("Fail to set double!"); - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); - } + try { + return Number::newNumber(*(double*)get()); + } + CATCH("Fail in NativePointer::getDouble!") +} +void NativePointer::setDouble(const Local& value) { + try { + *(double*)get() = (double)value.asNumber().toFloat(); + } catch (...) { + logger.error("Fail to set double!"); + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); + } } Local NativePointer::getString() { - try { - return String::newString(*(string *)get()); - } - CATCH("Fail in NativePointer::getString!") -} -void NativePointer::setString(const Local &value) { - try { - *(string *)get() = value.asString().toString(); - } catch (...) { - logger.error("Fail to set string!"); - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); - } + try { + return String::newString(*(string*)get()); + } + CATCH("Fail in NativePointer::getString!") +} +void NativePointer::setString(const Local& value) { + try { + *(string*)get() = value.asString().toString(); + } catch (...) { + logger.error("Fail to set string!"); + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); + } } Local NativePointer::getBool() { - try { - return Boolean::newBoolean(*(bool *)get()); - } - CATCH("Fail in NativePointer::getBool!") + try { + return Boolean::newBoolean(*(bool*)get()); + } + CATCH("Fail in NativePointer::getBool!") } -void NativePointer::setBool(const Local &value) { - try { - *(bool *)get() = value.asBoolean().value(); - } catch (...) { - logger.error("Fail to set bool!"); - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); - } +void NativePointer::setBool(const Local& value) { + try { + *(bool*)get() = value.asBoolean().value(); + } catch (...) { + logger.error("Fail to set bool!"); + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); + } } Local NativePointer::asStdString() { - try { - return NativeStdString::newNativeStdString((std::string *)mPtr); - } - CATCH("Fail in NativePointer::asStdString!") + try { + return NativeStdString::newNativeStdString((std::string*)mPtr); + } + CATCH("Fail in NativePointer::asStdString!") } Local NativePointer::asEntity() { - try { - return EntityClass::newEntity((Actor *)mPtr); - } - CATCH("Fail in NativePointer::asEntity!") + try { + return EntityClass::newEntity((Actor*)mPtr); + } + CATCH("Fail in NativePointer::asEntity!") } Local NativePointer::asItem() { - try { - return ItemClass::newItem((ItemStack *)mPtr); - } - CATCH("Fail in NativePointer::asItem!") + try { + return ItemClass::newItem((ItemStack*)mPtr); + } + CATCH("Fail in NativePointer::asItem!") } Local NativePointer::asPlayer() { - try { - return PlayerClass::newPlayer((Player *)mPtr); - } - CATCH("Fail in NativePointer::asPlayer!") + try { + return PlayerClass::newPlayer((Player*)mPtr); + } + CATCH("Fail in NativePointer::asPlayer!") } Local NativePointer::asContainer() { - try { - return ContainerClass::newContainer((Container *)mPtr); - } - CATCH("Fail in NativePointer::asContaine!") + try { + return ContainerClass::newContainer((Container*)mPtr); + } + CATCH("Fail in NativePointer::asContaine!") } \ No newline at end of file diff --git a/src/api/NativeStdString.cpp b/src/api/NativeStdString.cpp index 810b6cd3..cd23793b 100644 --- a/src/api/NativeStdString.cpp +++ b/src/api/NativeStdString.cpp @@ -39,298 +39,284 @@ ClassDefine NativeStdStringBuilder = //////////////////// Classes //////////////////// -NativeStdString::NativeStdString(const Local &scriptObj, - std::string *ptr) - : ScriptClass(scriptObj) { - set(ptr); +NativeStdString::NativeStdString(const Local& scriptObj, std::string* ptr) : ScriptClass(scriptObj) { + set(ptr); } -NativeStdString::NativeStdString(std::string *ptr) - : ScriptClass(ScriptClass::ConstructFromCpp{}) { - set(ptr); +NativeStdString::NativeStdString(std::string* ptr) : ScriptClass(ScriptClass::ConstructFromCpp{}) { + set(ptr); } -std::string *NativeStdString::extract(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return (std::string *)(EngineScope::currentEngine() - ->getNativeInstance(v) - ->get()); - else - return nullptr; +std::string* NativeStdString::extract(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return (std::string*)(EngineScope::currentEngine()->getNativeInstance(v)->get()); + else return nullptr; } -Local NativeStdString::newNativeStdString(std::string *ptr) { - auto out = new NativeStdString(ptr); - return out->getScriptObject(); +Local NativeStdString::newNativeStdString(std::string* ptr) { + auto out = new NativeStdString(ptr); + return out->getScriptObject(); } -NativeStdString *NativeStdString::constructor(const Arguments &args) { - CHECK_ARGS_COUNT_C(args, 1); - - try { - if (args[0].getKind() == ValueKind::kString) { - return new NativeStdString(args.thiz(), - new std::string(std::move(args[0].toStr()))); - } - if (args[0].getKind() == ValueKind::kObject) { - std::string *strPointer = - static_cast(NativePointer::extract(args[0])); - if (strPointer) // != nullptr - return new NativeStdString(args.thiz(), strPointer); +NativeStdString* NativeStdString::constructor(const Arguments& args) { + CHECK_ARGS_COUNT_C(args, 1); + + try { + if (args[0].getKind() == ValueKind::kString) { + return new NativeStdString(args.thiz(), new std::string(std::move(args[0].toStr()))); + } + if (args[0].getKind() == ValueKind::kObject) { + std::string* strPointer = static_cast(NativePointer::extract(args[0])); + if (strPointer) // != nullptr + return new NativeStdString(args.thiz(), strPointer); + } + LOG_WRONG_ARG_TYPE(); + return nullptr; } - LOG_WRONG_ARG_TYPE(); - return nullptr; - } - CATCH_C("Fail in NativeStdString::create NativeStdString!"); + CATCH_C("Fail in NativeStdString::create NativeStdString!"); } Local NativeStdString::getNpos() { - try { - return Number::newNumber((int64_t)std::string::npos); - } - CATCH("Fail in NativeStdString::getNpos!"); + try { + return Number::newNumber((int64_t)std::string::npos); + } + CATCH("Fail in NativeStdString::getNpos!"); } Local NativeStdString::clear() { - try { - mStr->clear(); - return Local(); - } - CATCH("Fail in NativeStdString::clear!"); + try { + mStr->clear(); + return Local(); + } + CATCH("Fail in NativeStdString::clear!"); } Local NativeStdString::size() { - try { - return Number::newNumber((int64_t)mStr->size()); - } - CATCH("Fail in NativeStdString::size!"); + try { + return Number::newNumber((int64_t)mStr->size()); + } + CATCH("Fail in NativeStdString::size!"); } Local NativeStdString::length() { - try { - return Number::newNumber((int64_t)mStr->length()); - } - CATCH("Fail in NativeStdString::length!"); + try { + return Number::newNumber((int64_t)mStr->length()); + } + CATCH("Fail in NativeStdString::length!"); } Local NativeStdString::capacity() { - try { - return Number::newNumber((int64_t)mStr->capacity()); - } - CATCH("Fail in NativeStdString::capacity!"); + try { + return Number::newNumber((int64_t)mStr->capacity()); + } + CATCH("Fail in NativeStdString::capacity!"); } Local NativeStdString::empty() { - try { - return Boolean::newBoolean(mStr->empty()); - } - CATCH("Fail in NativeStdString::empty!"); + try { + return Boolean::newBoolean(mStr->empty()); + } + CATCH("Fail in NativeStdString::empty!"); } Local NativeStdString::front() { - try { - return String::newString(std::string(mStr->front(), 1)); - } - CATCH("Fail in NativeStdString::front!"); + try { + return String::newString(std::string(mStr->front(), 1)); + } + CATCH("Fail in NativeStdString::front!"); } Local NativeStdString::back() { - try { - return String::newString(std::string(mStr->back(), 1)); - } - CATCH("Fail in NativeStdString::back!"); + try { + return String::newString(std::string(mStr->back(), 1)); + } + CATCH("Fail in NativeStdString::back!"); } Local NativeStdString::shrink_to_fit() { - try { - mStr->shrink_to_fit(); - return Local(); - } - CATCH("Fail in NativeStdString::shrink_to_fit!"); + try { + mStr->shrink_to_fit(); + return Local(); + } + CATCH("Fail in NativeStdString::shrink_to_fit!"); } Local NativeStdString::pop_back() { - try { - mStr->pop_back(); - return Local(); - } - CATCH("Fail in NativeStdString::pop_back!"); + try { + mStr->pop_back(); + return Local(); + } + CATCH("Fail in NativeStdString::pop_back!"); } -Local NativeStdString::at(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local NativeStdString::at(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - return String::newString(std::string(mStr->at(args[0].toInt()), 1)); - } catch (std::out_of_range e) { - throw Exception(e.what()); - } - CATCH("Fail in NativeStdString::at!"); + try { + return String::newString(std::string(mStr->at(args[0].toInt()), 1)); + } catch (std::out_of_range e) { + throw Exception(e.what()); + } + CATCH("Fail in NativeStdString::at!"); } -Local NativeStdString::append(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local NativeStdString::append(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - mStr->append(args[0].toStr()); - return args.thiz(); - } - CATCH("Fail in NativeStdString::append!"); + try { + mStr->append(args[0].toStr()); + return args.thiz(); + } + CATCH("Fail in NativeStdString::append!"); } -Local NativeStdString::push_back(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local NativeStdString::push_back(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - mStr->push_back(args[0].toStr()[0]); - return Local(); - } - CATCH("Fail in NativeStdString::push_back!"); + try { + mStr->push_back(args[0].toStr()[0]); + return Local(); + } + CATCH("Fail in NativeStdString::push_back!"); } -Local NativeStdString::assign(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local NativeStdString::assign(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - mStr->assign(args[0].toStr()); - return args.thiz(); - } - CATCH("Fail in NativeStdString::assign!"); + try { + mStr->assign(args[0].toStr()); + return args.thiz(); + } + CATCH("Fail in NativeStdString::assign!"); } -Local NativeStdString::insert(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kString); +Local NativeStdString::insert(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kString); - try { - mStr->insert(args[0].toInt(), args[1].toStr()); - return args.thiz(); - } - CATCH("Fail in NativeStdString::insert!"); + try { + mStr->insert(args[0].toInt(), args[1].toStr()); + return args.thiz(); + } + CATCH("Fail in NativeStdString::insert!"); } -Local NativeStdString::erase(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - - try { - if (args.size() >= 2) { - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - mStr->erase(args[0].toInt(), args[1].toInt()); - } else - mStr->erase(args[0].toInt()); - return args.thiz(); - } - CATCH("Fail in NativeStdString::erase!"); +Local NativeStdString::erase(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + + try { + if (args.size() >= 2) { + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + mStr->erase(args[0].toInt(), args[1].toInt()); + } else mStr->erase(args[0].toInt()); + return args.thiz(); + } + CATCH("Fail in NativeStdString::erase!"); } -Local NativeStdString::find(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - if (args.size() >= 2) { - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - return Number::newNumber( - (int64_t)mStr->find(args[0].toStr(), args[1].toInt())); - } else - return Number::newNumber((int64_t)mStr->find(args[0].toStr())); - } - CATCH("Fail in NativeStdString::find!"); +Local NativeStdString::find(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + if (args.size() >= 2) { + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + return Number::newNumber((int64_t)mStr->find(args[0].toStr(), args[1].toInt())); + } else return Number::newNumber((int64_t)mStr->find(args[0].toStr())); + } + CATCH("Fail in NativeStdString::find!"); } -Local NativeStdString::rfind(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - if (args.size() >= 2) { - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - return Number::newNumber( - (int64_t)mStr->rfind(args[0].toStr(), args[1].toInt())); - } else - return Number::newNumber((int64_t)mStr->rfind(args[0].toStr())); - } - CATCH("Fail in NativeStdString::rfind!"); +Local NativeStdString::rfind(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + if (args.size() >= 2) { + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + return Number::newNumber((int64_t)mStr->rfind(args[0].toStr(), args[1].toInt())); + } else return Number::newNumber((int64_t)mStr->rfind(args[0].toStr())); + } + CATCH("Fail in NativeStdString::rfind!"); } -Local NativeStdString::substr(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - - try { - std::string res; - if (args.size() >= 2) { - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - res = std::move(mStr->substr(args[0].toInt(), args[1].toInt())); - } else - res = std::move(mStr->substr(args[0].toInt())); - return newNativeStdString(new std::string(std::move(res))); - } - CATCH("Fail in NativeStdString::substr!"); +Local NativeStdString::substr(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + + try { + std::string res; + if (args.size() >= 2) { + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + res = std::move(mStr->substr(args[0].toInt(), args[1].toInt())); + } else res = std::move(mStr->substr(args[0].toInt())); + return newNativeStdString(new std::string(std::move(res))); + } + CATCH("Fail in NativeStdString::substr!"); } -Local NativeStdString::compare(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local NativeStdString::compare(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - return Number::newNumber(mStr->compare(args[0].toStr())); - } - CATCH("Fail in NativeStdString::compare!"); + try { + return Number::newNumber(mStr->compare(args[0].toStr())); + } + CATCH("Fail in NativeStdString::compare!"); } -Local NativeStdString::reserve(const Arguments &args) { - try { +Local NativeStdString::reserve(const Arguments& args) { + try { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + mStr->reserve(args[0].toInt()); + return Local(); + } + CATCH("Fail in NativeStdString::reserve!"); +} +Local NativeStdString::resize(const Arguments& args) { CHECK_ARGS_COUNT(args, 1); CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - mStr->reserve(args[0].toInt()); - return Local(); - } - CATCH("Fail in NativeStdString::reserve!"); -} -Local NativeStdString::resize(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - - try { - mStr->resize(args[0].toInt()); - return Local(); - } - CATCH("Fail in NativeStdString::resize!"); + + try { + mStr->resize(args[0].toInt()); + return Local(); + } + CATCH("Fail in NativeStdString::resize!"); } Local NativeStdString::asPointer() { - try { - return NativePointer::newNativePointer(mStr); - } - CATCH("Fail in NativeStdString::asPointer!"); + try { + return NativePointer::newNativePointer(mStr); + } + CATCH("Fail in NativeStdString::asPointer!"); } Local NativeStdString::toString() { - try { - return String::newString(*mStr); - } - CATCH("Fail in NativeStdString::toString!"); + try { + return String::newString(*mStr); + } + CATCH("Fail in NativeStdString::toString!"); } Local NativeStdString::clone() { - try { - return NativeStdString::newNativeStdString(new std::string(*mStr)); - } - CATCH("Fail in NativeStdString::clone!") + try { + return NativeStdString::newNativeStdString(new std::string(*mStr)); + } + CATCH("Fail in NativeStdString::clone!") } Local NativeStdString::destroy() { - try { - delete mStr; - mStr = nullptr; - return Local(); - } - CATCH("Fail in NativeStdString::destroy!"); + try { + delete mStr; + mStr = nullptr; + return Local(); + } + CATCH("Fail in NativeStdString::destroy!"); } \ No newline at end of file diff --git a/src/api/NativeStdString.h b/src/api/NativeStdString.h index b49c5691..a543f63a 100644 --- a/src/api/NativeStdString.h +++ b/src/api/NativeStdString.h @@ -8,17 +8,13 @@ class NativeStdString : public ScriptClass { public: explicit NativeStdString(const Local& scriptObj, std::string* ptr); explicit NativeStdString(std::string* ptr); - static std::string* extract(Local v); - static Local newNativeStdString(std::string* ptr); + static std::string* extract(Local v); + static Local newNativeStdString(std::string* ptr); static NativeStdString* constructor(const Arguments& args); - void* get() { - return mStr; - } + void* get() { return mStr; } - void set(std::string* ptr) { - mStr = ptr; - }; + void set(std::string* ptr) { mStr = ptr; }; Local getNpos(); diff --git a/src/api/NbtAPI.cpp b/src/api/NbtAPI.cpp index 83c85ecc..dc376824 100644 --- a/src/api/NbtAPI.cpp +++ b/src/api/NbtAPI.cpp @@ -2,7 +2,7 @@ #include "api/APIHelp.h" #include "api/BlockAPI.h" #include "api/ItemAPI.h" -#include "legacyapi/Base64.hpp" +#include "legacyapi/Base64.h" #include "mc/nbt/ByteArrayTag.h" #include "mc/nbt/ByteTag.h" #include "mc/nbt/DoubleTag.h" @@ -24,98 +24,89 @@ using magic_enum::enum_cast; //////////////////// Class Definition //////////////////// -ClassDefine NbtStaticBuilder = - defineClass("NBT") - .function("parseSNBT", &NbtStatic::parseSNBT) - .function("parseBinaryNBT", &NbtStatic::parseBinaryNBT) - .property("End", &NbtStatic::getType) - .property("Byte", &NbtStatic::getType) - .property("Short", &NbtStatic::getType) - .property("Int", &NbtStatic::getType) - .property("Long", &NbtStatic::getType) - .property("Float", &NbtStatic::getType) - .property("Double", &NbtStatic::getType) - .property("ByteArray", &NbtStatic::getType) - .property("String", &NbtStatic::getType) - .property("List", &NbtStatic::getType) - .property("Compound", &NbtStatic::getType) - - // For Compatibility - .function("createTag", &NbtStatic::newTag) - .function("newTag", &NbtStatic::newTag) - .build(); - -ClassDefine NbtEndClassBuilder = - defineClass("NbtEnd") - .constructor(&NbtEndClass::constructor) - .instanceFunction("getType", &NbtEndClass::getType) - .instanceFunction("toString", &NbtEndClass::toString) - .instanceFunction("set", &NbtEndClass::set) - .instanceFunction("get", &NbtEndClass::get) - .build(); - -ClassDefine NbtByteClassBuilder = - defineClass("NbtByte") - .constructor(&NbtByteClass::constructor) - .instanceFunction("getType", &NbtByteClass::getType) - .instanceFunction("toString", &NbtByteClass::toString) - .instanceFunction("set", &NbtByteClass::set) - .instanceFunction("get", &NbtByteClass::get) - .build(); - -ClassDefine NbtShortClassBuilder = - defineClass("NbtShort") - .constructor(&NbtShortClass::constructor) - .instanceFunction("getType", &NbtShortClass::getType) - .instanceFunction("toString", &NbtShortClass::toString) - .instanceFunction("set", &NbtShortClass::set) - .instanceFunction("get", &NbtShortClass::get) - .build(); - -ClassDefine NbtIntClassBuilder = - defineClass("NbtInt") - .constructor(&NbtIntClass::constructor) - .instanceFunction("getType", &NbtIntClass::getType) - .instanceFunction("toString", &NbtIntClass::toString) - .instanceFunction("set", &NbtIntClass::set) - .instanceFunction("get", &NbtIntClass::get) - .build(); - -ClassDefine NbtLongClassBuilder = - defineClass("NbtLong") - .constructor(&NbtLongClass::constructor) - .instanceFunction("getType", &NbtLongClass::getType) - .instanceFunction("toString", &NbtLongClass::toString) - .instanceFunction("set", &NbtLongClass::set) - .instanceFunction("get", &NbtLongClass::get) - .build(); - -ClassDefine NbtFloatClassBuilder = - defineClass("NbtFloat") - .constructor(&NbtFloatClass::constructor) - .instanceFunction("getType", &NbtFloatClass::getType) - .instanceFunction("toString", &NbtFloatClass::toString) - .instanceFunction("set", &NbtFloatClass::set) - .instanceFunction("get", &NbtFloatClass::get) - .build(); - -ClassDefine NbtDoubleClassBuilder = - defineClass("NbtDouble") - .constructor(&NbtDoubleClass::constructor) - .instanceFunction("getType", &NbtDoubleClass::getType) - .instanceFunction("toString", &NbtDoubleClass::toString) - .instanceFunction("set", &NbtDoubleClass::set) - .instanceFunction("get", &NbtDoubleClass::get) - .build(); - -ClassDefine NbtStringClassBuilder = - defineClass("NbtString") - .constructor(&NbtStringClass::constructor) - .instanceFunction("getType", &NbtStringClass::getType) - .instanceFunction("toString", &NbtStringClass::toString) - .instanceFunction("set", &NbtStringClass::set) - .instanceFunction("get", &NbtStringClass::get) - .build(); +ClassDefine NbtStaticBuilder = defineClass("NBT") + .function("parseSNBT", &NbtStatic::parseSNBT) + .function("parseBinaryNBT", &NbtStatic::parseBinaryNBT) + .property("End", &NbtStatic::getType) + .property("Byte", &NbtStatic::getType) + .property("Short", &NbtStatic::getType) + .property("Int", &NbtStatic::getType) + .property("Long", &NbtStatic::getType) + .property("Float", &NbtStatic::getType) + .property("Double", &NbtStatic::getType) + .property("ByteArray", &NbtStatic::getType) + .property("String", &NbtStatic::getType) + .property("List", &NbtStatic::getType) + .property("Compound", &NbtStatic::getType) + + // For Compatibility + .function("createTag", &NbtStatic::newTag) + .function("newTag", &NbtStatic::newTag) + .build(); + +ClassDefine NbtEndClassBuilder = defineClass("NbtEnd") + .constructor(&NbtEndClass::constructor) + .instanceFunction("getType", &NbtEndClass::getType) + .instanceFunction("toString", &NbtEndClass::toString) + .instanceFunction("set", &NbtEndClass::set) + .instanceFunction("get", &NbtEndClass::get) + .build(); + +ClassDefine NbtByteClassBuilder = defineClass("NbtByte") + .constructor(&NbtByteClass::constructor) + .instanceFunction("getType", &NbtByteClass::getType) + .instanceFunction("toString", &NbtByteClass::toString) + .instanceFunction("set", &NbtByteClass::set) + .instanceFunction("get", &NbtByteClass::get) + .build(); + +ClassDefine NbtShortClassBuilder = defineClass("NbtShort") + .constructor(&NbtShortClass::constructor) + .instanceFunction("getType", &NbtShortClass::getType) + .instanceFunction("toString", &NbtShortClass::toString) + .instanceFunction("set", &NbtShortClass::set) + .instanceFunction("get", &NbtShortClass::get) + .build(); + +ClassDefine NbtIntClassBuilder = defineClass("NbtInt") + .constructor(&NbtIntClass::constructor) + .instanceFunction("getType", &NbtIntClass::getType) + .instanceFunction("toString", &NbtIntClass::toString) + .instanceFunction("set", &NbtIntClass::set) + .instanceFunction("get", &NbtIntClass::get) + .build(); + +ClassDefine NbtLongClassBuilder = defineClass("NbtLong") + .constructor(&NbtLongClass::constructor) + .instanceFunction("getType", &NbtLongClass::getType) + .instanceFunction("toString", &NbtLongClass::toString) + .instanceFunction("set", &NbtLongClass::set) + .instanceFunction("get", &NbtLongClass::get) + .build(); + +ClassDefine NbtFloatClassBuilder = defineClass("NbtFloat") + .constructor(&NbtFloatClass::constructor) + .instanceFunction("getType", &NbtFloatClass::getType) + .instanceFunction("toString", &NbtFloatClass::toString) + .instanceFunction("set", &NbtFloatClass::set) + .instanceFunction("get", &NbtFloatClass::get) + .build(); + +ClassDefine NbtDoubleClassBuilder = defineClass("NbtDouble") + .constructor(&NbtDoubleClass::constructor) + .instanceFunction("getType", &NbtDoubleClass::getType) + .instanceFunction("toString", &NbtDoubleClass::toString) + .instanceFunction("set", &NbtDoubleClass::set) + .instanceFunction("get", &NbtDoubleClass::get) + .build(); + +ClassDefine NbtStringClassBuilder = defineClass("NbtString") + .constructor(&NbtStringClass::constructor) + .instanceFunction("getType", &NbtStringClass::getType) + .instanceFunction("toString", &NbtStringClass::toString) + .instanceFunction("set", &NbtStringClass::set) + .instanceFunction("get", &NbtStringClass::get) + .build(); ClassDefine NbtByteArrayClassBuilder = defineClass("NbtByteArray") @@ -126,29 +117,28 @@ ClassDefine NbtByteArrayClassBuilder = .instanceFunction("get", &NbtByteArrayClass::get) .build(); -ClassDefine NbtListClassBuilder = - defineClass("NbtList") - .constructor(&NbtListClass::constructor) - .instanceFunction("getType", &NbtListClass::getType) - .instanceFunction("toString", &NbtListClass::toString) - .instanceFunction("getSize", &NbtListClass::getSize) - .instanceFunction("getTypeOf", &NbtListClass::getTypeOf) - .instanceFunction("setEnd", &NbtListClass::setEnd) - .instanceFunction("setByte", &NbtListClass::setByte) - .instanceFunction("setInt", &NbtListClass::setInt) - .instanceFunction("setShort", &NbtListClass::setShort) - .instanceFunction("setLong", &NbtListClass::setLong) - .instanceFunction("setFloat", &NbtListClass::setFloat) - .instanceFunction("setDouble", &NbtListClass::setDouble) - .instanceFunction("setString", &NbtListClass::setString) - .instanceFunction("setByteArray", &NbtListClass::setByteArray) - .instanceFunction("setTag", &NbtListClass::setTag) - .instanceFunction("addTag", &NbtListClass::addTag) - .instanceFunction("removeTag", &NbtListClass::removeTag) - .instanceFunction("getData", &NbtListClass::getData) - .instanceFunction("getTag", &NbtListClass::getTag) - .instanceFunction("toArray", &NbtListClass::toArray) - .build(); +ClassDefine NbtListClassBuilder = defineClass("NbtList") + .constructor(&NbtListClass::constructor) + .instanceFunction("getType", &NbtListClass::getType) + .instanceFunction("toString", &NbtListClass::toString) + .instanceFunction("getSize", &NbtListClass::getSize) + .instanceFunction("getTypeOf", &NbtListClass::getTypeOf) + .instanceFunction("setEnd", &NbtListClass::setEnd) + .instanceFunction("setByte", &NbtListClass::setByte) + .instanceFunction("setInt", &NbtListClass::setInt) + .instanceFunction("setShort", &NbtListClass::setShort) + .instanceFunction("setLong", &NbtListClass::setLong) + .instanceFunction("setFloat", &NbtListClass::setFloat) + .instanceFunction("setDouble", &NbtListClass::setDouble) + .instanceFunction("setString", &NbtListClass::setString) + .instanceFunction("setByteArray", &NbtListClass::setByteArray) + .instanceFunction("setTag", &NbtListClass::setTag) + .instanceFunction("addTag", &NbtListClass::addTag) + .instanceFunction("removeTag", &NbtListClass::removeTag) + .instanceFunction("getData", &NbtListClass::getData) + .instanceFunction("getTag", &NbtListClass::getTag) + .instanceFunction("toArray", &NbtListClass::toArray) + .build(); ClassDefine NbtCompoundClassBuilder = defineClass("NbtCompound") @@ -176,2263 +166,2079 @@ ClassDefine NbtCompoundClassBuilder = .instanceFunction("destroy", &NbtCompoundClass::destroy) .build(); -void TagToJson_Compound_Helper(ordered_json &res, CompoundTag *nbt); - -void TagToJson_List_Helper(ordered_json &res, ListTag *nbt) { - auto &list = nbt->mList; - for (auto &tag : list) { - switch (tag->getId()) { - case Tag::Type::End: - res.push_back(nullptr); - break; - case Tag::Type::Byte: - tag->as() = 4; - res.push_back(tag->as().data); - break; - case Tag::Type::Short: - res.push_back(tag->as().data); - break; - case Tag::Type::Int: - res.push_back(tag->as().data); - break; - case Tag::Type::Int64: - res.push_back(tag->as().data); - break; - case Tag::Type::Float: - res.push_back(tag->as().data); - break; - case Tag::Type::Double: - res.push_back(tag->as().data); - break; - case Tag::Type::String: - res.push_back(tag->as().data); - break; - case Tag::Type::ByteArray: { - auto &bytes = tag->as().data; - res.push_back( - Base64::Encode(string((char *)bytes.mBuffer.get(), bytes.mSize))); - break; +void TagToJson_Compound_Helper(ordered_json& res, CompoundTag* nbt); + +void TagToJson_List_Helper(ordered_json& res, ListTag* nbt) { + auto& list = nbt->mList; + for (auto& tag : list) { + switch (tag->getId()) { + case Tag::Type::End: + res.push_back(nullptr); + break; + case Tag::Type::Byte: + tag->as() = 4; + res.push_back(tag->as().data); + break; + case Tag::Type::Short: + res.push_back(tag->as().data); + break; + case Tag::Type::Int: + res.push_back(tag->as().data); + break; + case Tag::Type::Int64: + res.push_back(tag->as().data); + break; + case Tag::Type::Float: + res.push_back(tag->as().data); + break; + case Tag::Type::Double: + res.push_back(tag->as().data); + break; + case Tag::Type::String: + res.push_back(tag->as().data); + break; + case Tag::Type::ByteArray: { + auto& bytes = tag->as().data; + res.push_back(Base64::Encode(string((char*)bytes.mBuffer.get(), bytes.mSize))); + break; + } + case Tag::Type::List: { + ordered_json arrJson = ordered_json::array(); + TagToJson_List_Helper(arrJson, tag->as_ptr()); + res.push_back(arrJson); + break; + } + case Tag::Type::Compound: { + ordered_json arrObj = ordered_json::object(); + TagToJson_Compound_Helper(arrObj, tag->as_ptr()); + res.push_back(arrObj); + break; + } + default: + res.push_back(nullptr); + break; + } } - case Tag::Type::List: { - ordered_json arrJson = ordered_json::array(); - TagToJson_List_Helper(arrJson, tag->as_ptr()); - res.push_back(arrJson); - break; - } - case Tag::Type::Compound: { - ordered_json arrObj = ordered_json::object(); - TagToJson_Compound_Helper(arrObj, tag->as_ptr()); - res.push_back(arrObj); - break; - } - default: - res.push_back(nullptr); - break; +} + +void TagToJson_Compound_Helper(ordered_json& res, CompoundTag* nbt) { + auto& list = nbt->mTags; + for (auto& [key, tmp] : list) { + auto& tag = tmp.get(); + switch (tag.getId()) { + case Tag::Type::End: + res.push_back({key, nullptr}); + break; + case Tag::Type::Byte: + res.push_back({key, tag.as().data}); + break; + case Tag::Type::Short: + res.push_back({key, tag.as().data}); + break; + case Tag::Type::Int: + res.push_back({key, tag.as().data}); + break; + case Tag::Type::Int64: + res.push_back({key, tag.as().data}); + break; + case Tag::Type::Float: + res.push_back({key, tag.as().data}); + break; + case Tag::Type::Double: + res.push_back({key, tag.as().data}); + break; + case Tag::Type::String: + res.push_back({key, tag.as().data}); + break; + case Tag::Type::ByteArray: { + auto& bytes = tag.as().data; + res.push_back(Base64::Encode(string((char*)bytes.mBuffer.get(), bytes.mSize))); + break; + } + case Tag::Type::List: { + ordered_json arrJson = ordered_json::array(); + TagToJson_List_Helper(arrJson, &tag.as()); + res.push_back({key, arrJson}); + break; + } + case Tag::Type::Compound: { + ordered_json arrObj = ordered_json::object(); + TagToJson_Compound_Helper(arrObj, &tag.as()); + res.push_back({key, arrObj}); + break; + } + default: + res.push_back({key, nullptr}); + break; + } } - } } -void TagToJson_Compound_Helper(ordered_json &res, CompoundTag *nbt) { - auto &list = nbt->mTags; - for (auto &[key, tmp] : list) { - auto &tag = tmp.get(); - switch (tag.getId()) { +std::string TagToJson(Tag* nbt, int formatIndent) { + std::string result; + switch (nbt->getId()) { case Tag::Type::End: - res.push_back({key, nullptr}); - break; + result = ""; + break; case Tag::Type::Byte: - res.push_back({key, tag.as().data}); - break; + result = std::to_string(nbt->as().data); + break; case Tag::Type::Short: - res.push_back({key, tag.as().data}); - break; + result = std::to_string(nbt->as().data); + break; case Tag::Type::Int: - res.push_back({key, tag.as().data}); - break; + result = std::to_string(nbt->as().data); + break; case Tag::Type::Int64: - res.push_back({key, tag.as().data}); - break; + result = std::to_string(nbt->as().data); + break; case Tag::Type::Float: - res.push_back({key, tag.as().data}); - break; + result = std::to_string(nbt->as().data); + break; case Tag::Type::Double: - res.push_back({key, tag.as().data}); - break; + result = std::to_string(nbt->as().data); + break; case Tag::Type::String: - res.push_back({key, tag.as().data}); - break; + result = nbt->as().data; + break; case Tag::Type::ByteArray: { - auto &bytes = tag.as().data; - res.push_back( - Base64::Encode(string((char *)bytes.mBuffer.get(), bytes.mSize))); - break; + auto& bytes = nbt->as().data; + result = Base64::Encode(string((char*)bytes.mBuffer.get(), bytes.mSize)); + break; } case Tag::Type::List: { - ordered_json arrJson = ordered_json::array(); - TagToJson_List_Helper(arrJson, &tag.as()); - res.push_back({key, arrJson}); - break; + ordered_json jsonRes = ordered_json::array(); + TagToJson_List_Helper(jsonRes, nbt->as_ptr()); + result = jsonRes.dump(formatIndent); + break; } case Tag::Type::Compound: { - ordered_json arrObj = ordered_json::object(); - TagToJson_Compound_Helper(arrObj, &tag.as()); - res.push_back({key, arrObj}); - break; + ordered_json jsonRes = ordered_json::object(); + TagToJson_Compound_Helper(jsonRes, nbt->as_ptr()); + result = jsonRes.dump(formatIndent); + break; } default: - res.push_back({key, nullptr}); - break; - } - } -} - -std::string TagToJson(Tag *nbt, int formatIndent) { - std::string result; - switch (nbt->getId()) { - case Tag::Type::End: - result = ""; - break; - case Tag::Type::Byte: - result = std::to_string(nbt->as().data); - break; - case Tag::Type::Short: - result = std::to_string(nbt->as().data); - break; - case Tag::Type::Int: - result = std::to_string(nbt->as().data); - break; - case Tag::Type::Int64: - result = std::to_string(nbt->as().data); - break; - case Tag::Type::Float: - result = std::to_string(nbt->as().data); - break; - case Tag::Type::Double: - result = std::to_string(nbt->as().data); - break; - case Tag::Type::String: - result = nbt->as().data; - break; - case Tag::Type::ByteArray: { - auto &bytes = nbt->as().data; - result = Base64::Encode(string((char *)bytes.mBuffer.get(), bytes.mSize)); - break; - } - case Tag::Type::List: { - ordered_json jsonRes = ordered_json::array(); - TagToJson_List_Helper(jsonRes, nbt->as_ptr()); - result = jsonRes.dump(formatIndent); - break; - } - case Tag::Type::Compound: { - ordered_json jsonRes = ordered_json::object(); - TagToJson_Compound_Helper(jsonRes, nbt->as_ptr()); - result = jsonRes.dump(formatIndent); - break; - } - default: - result = ""; - break; - } - return result; + result = ""; + break; + } + return result; } //////////////////// Classes NbtEnd //////////////////// -NbtEndClass::NbtEndClass(const Local &scriptObj, - std::unique_ptr p) - : ScriptClass(scriptObj) { - this->nbt = std::move(p); +NbtEndClass::NbtEndClass(const Local& scriptObj, std::unique_ptr p) : ScriptClass(scriptObj) { + this->nbt = std::move(p); } -NbtEndClass::NbtEndClass(std::unique_ptr p) - : ScriptClass(ScriptClass::ConstructFromCpp{}) { - this->nbt = std::move(p); +NbtEndClass::NbtEndClass(std::unique_ptr p) : ScriptClass(ScriptClass::ConstructFromCpp{}) { + this->nbt = std::move(p); } -NbtEndClass *NbtEndClass::constructor(const Arguments &args) { - try { - return new NbtEndClass(args.thiz(), std::make_unique()); - } - CATCH_C("Fail in Create EndTag!"); +NbtEndClass* NbtEndClass::constructor(const Arguments& args) { + try { + return new NbtEndClass(args.thiz(), std::make_unique()); + } + CATCH_C("Fail in Create EndTag!"); } -EndTag *NbtEndClass::extract(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine() - ->getNativeInstance(v) - ->nbt.get(); - else - return nullptr; +EndTag* NbtEndClass::extract(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v)->nbt.get(); + else return nullptr; } -Local NbtEndClass::pack(EndTag *tag, bool noDelete) { - try { - if (noDelete) // unique_ptr 共享指针 + noDelete - { - std::unique_ptr nbt(tag); - auto *nbtObj = new NbtEndClass(std::move(nbt)); - nbtObj->canDelete = false; - return nbtObj->getScriptObject(); - } else - return (new NbtEndClass(std::unique_ptr(tag)))->getScriptObject(); - } - CATCH("Fail in construct NbtEnd!"); +Local NbtEndClass::pack(EndTag* tag, bool noDelete) { + try { + if (noDelete) // unique_ptr 共享指针 + noDelete + { + std::unique_ptr nbt(tag); + auto* nbtObj = new NbtEndClass(std::move(nbt)); + nbtObj->canDelete = false; + return nbtObj->getScriptObject(); + } else return (new NbtEndClass(std::unique_ptr(tag)))->getScriptObject(); + } + CATCH("Fail in construct NbtEnd!"); } Local NbtEndClass::pack(std::unique_ptr tag) { - try { - return (new NbtEndClass(std::move(tag)))->getScriptObject(); - } - CATCH("Fail in construct NbtEnd!"); + try { + return (new NbtEndClass(std::move(tag)))->getScriptObject(); + } + CATCH("Fail in construct NbtEnd!"); } -Local NbtEndClass::getType(const Arguments &args) { - return Number::newNumber((int)Tag::Type::End); -} +Local NbtEndClass::getType(const Arguments& args) { return Number::newNumber((int)Tag::Type::End); } -Local NbtEndClass::get(const Arguments &args) { - try { - return Local(); - } - CATCH("Fail in NbtValueGet!") +Local NbtEndClass::get(const Arguments& args) { + try { + return Local(); + } + CATCH("Fail in NbtValueGet!") } -Local NbtEndClass::toString(const Arguments &args) { - if (args.size() >= 1) - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local NbtEndClass::toString(const Arguments& args) { + if (args.size() >= 1) CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - return String::newString( - TagToJson(nbt.get(), args.size() >= 1 ? args[0].toInt() : -1)); - } - CATCH("Fail in NBTtoJson!"); + try { + return String::newString(TagToJson(nbt.get(), args.size() >= 1 ? args[0].toInt() : -1)); + } + CATCH("Fail in NBTtoJson!"); } -Local NbtEndClass::set(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) +Local NbtEndClass::set(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) - try { - return Boolean::newBoolean(true); - } - CATCH("Fail in NbtValueSet!") + try { + return Boolean::newBoolean(true); + } + CATCH("Fail in NbtValueSet!") } //////////////////// Classes NbtByte //////////////////// -NbtByteClass::NbtByteClass(const Local &scriptObj, - std::unique_ptr p) - : ScriptClass(scriptObj) { - this->nbt = std::move(p); +NbtByteClass::NbtByteClass(const Local& scriptObj, std::unique_ptr p) : ScriptClass(scriptObj) { + this->nbt = std::move(p); } -NbtByteClass::NbtByteClass(std::unique_ptr p) - : ScriptClass(ScriptClass::ConstructFromCpp{}) { - this->nbt = std::move(p); +NbtByteClass::NbtByteClass(std::unique_ptr p) : ScriptClass(ScriptClass::ConstructFromCpp{}) { + this->nbt = std::move(p); } -NbtByteClass *NbtByteClass::constructor(const Arguments &args) { - try { - auto tag = ByteTag((char)args[0].toInt()); - return new NbtByteClass(args.thiz(), - std::move(std::make_unique(tag))); - } - CATCH_C("Fail in Create ByteTag!"); +NbtByteClass* NbtByteClass::constructor(const Arguments& args) { + try { + auto tag = ByteTag((char)args[0].toInt()); + return new NbtByteClass(args.thiz(), std::move(std::make_unique(tag))); + } + CATCH_C("Fail in Create ByteTag!"); } -ByteTag *NbtByteClass::extract(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine() - ->getNativeInstance(v) - ->nbt.get(); - else - return nullptr; +ByteTag* NbtByteClass::extract(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v)->nbt.get(); + else return nullptr; } -Local NbtByteClass::pack(ByteTag *tag, bool noDelete) { - try { - if (noDelete) // unique_ptr 共享指针 + noDelete - { - std::unique_ptr nbt(tag); - auto *nbtObj = new NbtByteClass(std::move(nbt)); - nbtObj->canDelete = false; - return nbtObj->getScriptObject(); - } else - return (new NbtByteClass(std::make_unique(tag->as()))) - ->getScriptObject(); - } - CATCH("Fail in construct NbtByte!"); +Local NbtByteClass::pack(ByteTag* tag, bool noDelete) { + try { + if (noDelete) // unique_ptr 共享指针 + noDelete + { + std::unique_ptr nbt(tag); + auto* nbtObj = new NbtByteClass(std::move(nbt)); + nbtObj->canDelete = false; + return nbtObj->getScriptObject(); + } else return (new NbtByteClass(std::make_unique(tag->as())))->getScriptObject(); + } + CATCH("Fail in construct NbtByte!"); } Local NbtByteClass::pack(std::unique_ptr tag) { - try { - return (new NbtByteClass(std::move(tag)))->getScriptObject(); - } - CATCH("Fail in construct NbtByte!"); + try { + return (new NbtByteClass(std::move(tag)))->getScriptObject(); + } + CATCH("Fail in construct NbtByte!"); } -Local NbtByteClass::getType(const Arguments &args) { - return Number::newNumber((int)Tag::Type::Byte); -} +Local NbtByteClass::getType(const Arguments& args) { return Number::newNumber((int)Tag::Type::Byte); } -Local NbtByteClass::get(const Arguments &args) { - try { - return Number::newNumber(nbt->data); - } - CATCH("Fail in NbtValueGet!") +Local NbtByteClass::get(const Arguments& args) { + try { + return Number::newNumber(nbt->data); + } + CATCH("Fail in NbtValueGet!") } -Local NbtByteClass::toString(const Arguments &args) { - if (args.size() >= 1) - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local NbtByteClass::toString(const Arguments& args) { + if (args.size() >= 1) CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - return String::newString( - TagToJson(nbt.get(), args.size() >= 1 ? args[0].toInt() : -1)); - } - CATCH("Fail in NBTtoJson!"); + try { + return String::newString(TagToJson(nbt.get(), args.size() >= 1 ? args[0].toInt() : -1)); + } + CATCH("Fail in NBTtoJson!"); } -Local NbtByteClass::set(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); +Local NbtByteClass::set(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); - try { - nbt->data = (char)args[0].toInt(); - return Boolean::newBoolean(true); - } - CATCH("Fail in NbtValueSet!") + try { + nbt->data = (char)args[0].toInt(); + return Boolean::newBoolean(true); + } + CATCH("Fail in NbtValueSet!") } //////////////////// Classes NbtInt //////////////////// -NbtIntClass::NbtIntClass(const Local &scriptObj, - std::unique_ptr p) - : ScriptClass(scriptObj) { - this->nbt = std::move(p); +NbtIntClass::NbtIntClass(const Local& scriptObj, std::unique_ptr p) : ScriptClass(scriptObj) { + this->nbt = std::move(p); } -NbtIntClass::NbtIntClass(std::unique_ptr p) - : ScriptClass(ScriptClass::ConstructFromCpp{}) { - this->nbt = std::move(p); +NbtIntClass::NbtIntClass(std::unique_ptr p) : ScriptClass(ScriptClass::ConstructFromCpp{}) { + this->nbt = std::move(p); } -NbtIntClass *NbtIntClass::constructor(const Arguments &args) { - try { - auto tag = IntTag(args[0].toInt()); - return new NbtIntClass(args.thiz(), std::make_unique(tag)); - } - CATCH_C("Fail in Create IntTag!"); +NbtIntClass* NbtIntClass::constructor(const Arguments& args) { + try { + auto tag = IntTag(args[0].toInt()); + return new NbtIntClass(args.thiz(), std::make_unique(tag)); + } + CATCH_C("Fail in Create IntTag!"); } -IntTag *NbtIntClass::extract(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine() - ->getNativeInstance(v) - ->nbt.get(); - else - return nullptr; +IntTag* NbtIntClass::extract(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v)->nbt.get(); + else return nullptr; } -Local NbtIntClass::pack(IntTag *tag, bool noDelete) { - try { - if (noDelete) // unique_ptr 共享指针 + noDelete - { - std::unique_ptr nbt(tag); - auto *nbtObj = new NbtIntClass(std::move(nbt)); - nbtObj->canDelete = false; - return nbtObj->getScriptObject(); - } else - return (new NbtIntClass(std::make_unique(tag->as()))) - ->getScriptObject(); - } - CATCH("Fail in construct NbtInt!"); +Local NbtIntClass::pack(IntTag* tag, bool noDelete) { + try { + if (noDelete) // unique_ptr 共享指针 + noDelete + { + std::unique_ptr nbt(tag); + auto* nbtObj = new NbtIntClass(std::move(nbt)); + nbtObj->canDelete = false; + return nbtObj->getScriptObject(); + } else return (new NbtIntClass(std::make_unique(tag->as())))->getScriptObject(); + } + CATCH("Fail in construct NbtInt!"); } Local NbtIntClass::pack(std::unique_ptr tag) { - try { - return (new NbtIntClass(std::move(tag)))->getScriptObject(); - } - CATCH("Fail in construct NbtInt!"); + try { + return (new NbtIntClass(std::move(tag)))->getScriptObject(); + } + CATCH("Fail in construct NbtInt!"); } -Local NbtIntClass::getType(const Arguments &args) { - return Number::newNumber((int)Tag::Type::Int); -} +Local NbtIntClass::getType(const Arguments& args) { return Number::newNumber((int)Tag::Type::Int); } -Local NbtIntClass::get(const Arguments &args) { - try { - return Number::newNumber(nbt->data); - } - CATCH("Fail in NbtValueGet!") +Local NbtIntClass::get(const Arguments& args) { + try { + return Number::newNumber(nbt->data); + } + CATCH("Fail in NbtValueGet!") } -Local NbtIntClass::toString(const Arguments &args) { - if (args.size() >= 1) - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local NbtIntClass::toString(const Arguments& args) { + if (args.size() >= 1) CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - return String::newString( - TagToJson(nbt.get(), args.size() >= 1 ? args[0].toInt() : -1)); - } - CATCH("Fail in NBTtoJson!"); + try { + return String::newString(TagToJson(nbt.get(), args.size() >= 1 ? args[0].toInt() : -1)); + } + CATCH("Fail in NBTtoJson!"); } -Local NbtIntClass::set(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) +Local NbtIntClass::set(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) - try { - nbt->data = args[0].toInt(); - return Boolean::newBoolean(true); - } - CATCH("Fail in NbtValueSet!") + try { + nbt->data = args[0].toInt(); + return Boolean::newBoolean(true); + } + CATCH("Fail in NbtValueSet!") } //////////////////// Classes NbtShort //////////////////// -NbtShortClass::NbtShortClass(const Local &scriptObj, - std::unique_ptr p) - : ScriptClass(scriptObj) { - this->nbt = std::move(p); +NbtShortClass::NbtShortClass(const Local& scriptObj, std::unique_ptr p) : ScriptClass(scriptObj) { + this->nbt = std::move(p); } NbtShortClass::NbtShortClass(std::unique_ptr p) - : ScriptClass(ScriptClass::ConstructFromCpp{}) { - this->nbt = std::move(p); -} - -NbtShortClass *NbtShortClass::constructor(const Arguments &args) { - try { - auto tag = ShortTag(args[0].toInt()); - return new NbtShortClass(args.thiz(), std::make_unique(tag)); - } - CATCH_C("Fail in Create ShortTag!"); -} - -ShortTag *NbtShortClass::extract(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine() - ->getNativeInstance(v) - ->nbt.get(); - else - return nullptr; -} - -Local NbtShortClass::pack(ShortTag *tag, bool noDelete) { - try { - if (noDelete) // unique_ptr 共享指针 + noDelete - { - std::unique_ptr nbt(tag); - auto *nbtObj = new NbtShortClass(std::move(nbt)); - nbtObj->canDelete = false; - return nbtObj->getScriptObject(); - } else - return (new NbtShortClass( - std::make_unique(tag->as()))) - ->getScriptObject(); - } - CATCH("Fail in construct NbtShort!"); +: ScriptClass(ScriptClass::ConstructFromCpp{}) { + this->nbt = std::move(p); } -Local NbtShortClass::pack(std::unique_ptr tag) { - try { - return (new NbtShortClass(std::move(tag)))->getScriptObject(); - } - CATCH("Fail in construct NbtShort!"); +NbtShortClass* NbtShortClass::constructor(const Arguments& args) { + try { + auto tag = ShortTag(args[0].toInt()); + return new NbtShortClass(args.thiz(), std::make_unique(tag)); + } + CATCH_C("Fail in Create ShortTag!"); } -Local NbtShortClass::getType(const Arguments &args) { - return Number::newNumber((int)Tag::Type::Short); +ShortTag* NbtShortClass::extract(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v)->nbt.get(); + else return nullptr; } -Local NbtShortClass::get(const Arguments &args) { - try { - return Number::newNumber(nbt->data); - } - CATCH("Fail in NbtValueGet!") +Local NbtShortClass::pack(ShortTag* tag, bool noDelete) { + try { + if (noDelete) // unique_ptr 共享指针 + noDelete + { + std::unique_ptr nbt(tag); + auto* nbtObj = new NbtShortClass(std::move(nbt)); + nbtObj->canDelete = false; + return nbtObj->getScriptObject(); + } else return (new NbtShortClass(std::make_unique(tag->as())))->getScriptObject(); + } + CATCH("Fail in construct NbtShort!"); } -Local NbtShortClass::toString(const Arguments &args) { - if (args.size() >= 1) - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local NbtShortClass::pack(std::unique_ptr tag) { + try { + return (new NbtShortClass(std::move(tag)))->getScriptObject(); + } + CATCH("Fail in construct NbtShort!"); +} - try { - return String::newString( - TagToJson(nbt.get(), args.size() >= 1 ? args[0].toInt() : -1)); - } - CATCH("Fail in NBTtoJson!"); +Local NbtShortClass::getType(const Arguments& args) { return Number::newNumber((int)Tag::Type::Short); } + +Local NbtShortClass::get(const Arguments& args) { + try { + return Number::newNumber(nbt->data); + } + CATCH("Fail in NbtValueGet!") } -Local NbtShortClass::set(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); +Local NbtShortClass::toString(const Arguments& args) { + if (args.size() >= 1) CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - nbt->data = args[0].toInt(); - return Boolean::newBoolean(true); - } - CATCH("Fail in NbtValueSet!") + try { + return String::newString(TagToJson(nbt.get(), args.size() >= 1 ? args[0].toInt() : -1)); + } + CATCH("Fail in NBTtoJson!"); +} + +Local NbtShortClass::set(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + + try { + nbt->data = args[0].toInt(); + return Boolean::newBoolean(true); + } + CATCH("Fail in NbtValueSet!") } //////////////////// Classes NbtLong //////////////////// -NbtLongClass::NbtLongClass(const Local &scriptObj, - std::unique_ptr p) - : ScriptClass(scriptObj) { - this->nbt = std::move(p); +NbtLongClass::NbtLongClass(const Local& scriptObj, std::unique_ptr p) : ScriptClass(scriptObj) { + this->nbt = std::move(p); } -NbtLongClass::NbtLongClass(std::unique_ptr p) - : ScriptClass(ScriptClass::ConstructFromCpp{}) { - this->nbt = std::move(p); +NbtLongClass::NbtLongClass(std::unique_ptr p) : ScriptClass(ScriptClass::ConstructFromCpp{}) { + this->nbt = std::move(p); } -NbtLongClass *NbtLongClass::constructor(const Arguments &args) { - try { - auto tag = Int64Tag(args[0].asNumber().toInt64()); - return new NbtLongClass(args.thiz(), std::make_unique(tag)); - } - CATCH_C("Fail in Create LongTag!"); +NbtLongClass* NbtLongClass::constructor(const Arguments& args) { + try { + auto tag = Int64Tag(args[0].asNumber().toInt64()); + return new NbtLongClass(args.thiz(), std::make_unique(tag)); + } + CATCH_C("Fail in Create LongTag!"); } -Int64Tag *NbtLongClass::extract(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine() - ->getNativeInstance(v) - ->nbt.get(); - else - return nullptr; +Int64Tag* NbtLongClass::extract(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v)->nbt.get(); + else return nullptr; } -Local NbtLongClass::pack(Int64Tag *tag, bool noDelete) { - try { - if (noDelete) // unique_ptr 共享指针 + noDelete - { - std::unique_ptr nbt(tag); - auto *nbtObj = new NbtLongClass(std::move(nbt)); - nbtObj->canDelete = false; - return nbtObj->getScriptObject(); - } else - return (new NbtLongClass(std::make_unique(tag->as()))) - ->getScriptObject(); - } - CATCH("Fail in construct NbtLong!"); +Local NbtLongClass::pack(Int64Tag* tag, bool noDelete) { + try { + if (noDelete) // unique_ptr 共享指针 + noDelete + { + std::unique_ptr nbt(tag); + auto* nbtObj = new NbtLongClass(std::move(nbt)); + nbtObj->canDelete = false; + return nbtObj->getScriptObject(); + } else return (new NbtLongClass(std::make_unique(tag->as())))->getScriptObject(); + } + CATCH("Fail in construct NbtLong!"); } Local NbtLongClass::pack(std::unique_ptr tag) { - try { - return (new NbtLongClass(std::move(tag)))->getScriptObject(); - } - CATCH("Fail in construct NbtLong!"); + try { + return (new NbtLongClass(std::move(tag)))->getScriptObject(); + } + CATCH("Fail in construct NbtLong!"); } -Local NbtLongClass::getType(const Arguments &args) { - return Number::newNumber((int)Tag::Type::Int64); -} +Local NbtLongClass::getType(const Arguments& args) { return Number::newNumber((int)Tag::Type::Int64); } -Local NbtLongClass::get(const Arguments &args) { - try { - return Number::newNumber(nbt->data); - } - CATCH("Fail in NbtValueGet!") +Local NbtLongClass::get(const Arguments& args) { + try { + return Number::newNumber(nbt->data); + } + CATCH("Fail in NbtValueGet!") } -Local NbtLongClass::toString(const Arguments &args) { - if (args.size() >= 1) - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local NbtLongClass::toString(const Arguments& args) { + if (args.size() >= 1) CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - return String::newString( - TagToJson(nbt.get(), args.size() >= 1 ? args[0].toInt() : -1)); - } - CATCH("Fail in NBTtoJson!"); + try { + return String::newString(TagToJson(nbt.get(), args.size() >= 1 ? args[0].toInt() : -1)); + } + CATCH("Fail in NBTtoJson!"); } -Local NbtLongClass::set(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); +Local NbtLongClass::set(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); - try { - nbt->data = args[0].asNumber().toInt64(); - return Boolean::newBoolean(true); - } - CATCH("Fail in NbtValueSet!") + try { + nbt->data = args[0].asNumber().toInt64(); + return Boolean::newBoolean(true); + } + CATCH("Fail in NbtValueSet!") } //////////////////// Classes NbtFloat //////////////////// -NbtFloatClass::NbtFloatClass(const Local &scriptObj, - std::unique_ptr p) - : ScriptClass(scriptObj) { - this->nbt = std::move(p); +NbtFloatClass::NbtFloatClass(const Local& scriptObj, std::unique_ptr p) : ScriptClass(scriptObj) { + this->nbt = std::move(p); } NbtFloatClass::NbtFloatClass(std::unique_ptr p) - : ScriptClass(ScriptClass::ConstructFromCpp{}) { - this->nbt = std::move(p); -} - -NbtFloatClass *NbtFloatClass::constructor(const Arguments &args) { - try { - auto tag = FloatTag(args[0].asNumber().toFloat()); - return new NbtFloatClass(args.thiz(), std::make_unique(tag)); - } - CATCH_C("Fail in Create FloatTag!"); -} - -FloatTag *NbtFloatClass::extract(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine() - ->getNativeInstance(v) - ->nbt.get(); - else - return nullptr; -} - -Local NbtFloatClass::pack(FloatTag *tag, bool noDelete) { - try { - if (noDelete) // unique_ptr 共享指针 + noDelete - { - std::unique_ptr nbt(tag); - auto *nbtObj = new NbtFloatClass(std::move(nbt)); - nbtObj->canDelete = false; - return nbtObj->getScriptObject(); - } else - return (new NbtFloatClass( - std::make_unique(tag->as()))) - ->getScriptObject(); - } - CATCH("Fail in construct NbtFloat!"); +: ScriptClass(ScriptClass::ConstructFromCpp{}) { + this->nbt = std::move(p); } -Local NbtFloatClass::pack(std::unique_ptr tag) { - try { - return (new NbtFloatClass(std::move(tag)))->getScriptObject(); - } - CATCH("Fail in construct NbtFloat!"); +NbtFloatClass* NbtFloatClass::constructor(const Arguments& args) { + try { + auto tag = FloatTag(args[0].asNumber().toFloat()); + return new NbtFloatClass(args.thiz(), std::make_unique(tag)); + } + CATCH_C("Fail in Create FloatTag!"); } -Local NbtFloatClass::getType(const Arguments &args) { - return Number::newNumber((int)Tag::Type::Float); +FloatTag* NbtFloatClass::extract(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v)->nbt.get(); + else return nullptr; } -Local NbtFloatClass::get(const Arguments &args) { - try { - return Number::newNumber(nbt->data); - } - CATCH("Fail in NbtValueGet!") +Local NbtFloatClass::pack(FloatTag* tag, bool noDelete) { + try { + if (noDelete) // unique_ptr 共享指针 + noDelete + { + std::unique_ptr nbt(tag); + auto* nbtObj = new NbtFloatClass(std::move(nbt)); + nbtObj->canDelete = false; + return nbtObj->getScriptObject(); + } else return (new NbtFloatClass(std::make_unique(tag->as())))->getScriptObject(); + } + CATCH("Fail in construct NbtFloat!"); } -Local NbtFloatClass::toString(const Arguments &args) { - if (args.size() >= 1) - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local NbtFloatClass::pack(std::unique_ptr tag) { + try { + return (new NbtFloatClass(std::move(tag)))->getScriptObject(); + } + CATCH("Fail in construct NbtFloat!"); +} - try { - return String::newString( - TagToJson(nbt.get(), args.size() >= 1 ? args[0].toInt() : -1)); - } - CATCH("Fail in NBTtoJson!"); +Local NbtFloatClass::getType(const Arguments& args) { return Number::newNumber((int)Tag::Type::Float); } + +Local NbtFloatClass::get(const Arguments& args) { + try { + return Number::newNumber(nbt->data); + } + CATCH("Fail in NbtValueGet!") +} + +Local NbtFloatClass::toString(const Arguments& args) { + if (args.size() >= 1) CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + + try { + return String::newString(TagToJson(nbt.get(), args.size() >= 1 ? args[0].toInt() : -1)); + } + CATCH("Fail in NBTtoJson!"); } -Local NbtFloatClass::set(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); +Local NbtFloatClass::set(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); - try { - nbt->data = args[0].asNumber().toFloat(); - return Boolean::newBoolean(true); - } - CATCH("Fail in NbtValueSet!") + try { + nbt->data = args[0].asNumber().toFloat(); + return Boolean::newBoolean(true); + } + CATCH("Fail in NbtValueSet!") } //////////////////// Classes NbtDouble //////////////////// -NbtDoubleClass::NbtDoubleClass(const Local &scriptObj, - std::unique_ptr p) - : ScriptClass(scriptObj) { - this->nbt = std::move(p); +NbtDoubleClass::NbtDoubleClass(const Local& scriptObj, std::unique_ptr p) : ScriptClass(scriptObj) { + this->nbt = std::move(p); } NbtDoubleClass::NbtDoubleClass(std::unique_ptr p) - : ScriptClass(ScriptClass::ConstructFromCpp{}) { - this->nbt = std::move(p); -} - -NbtDoubleClass *NbtDoubleClass::constructor(const Arguments &args) { - try { - auto tag = DoubleTag(args[0].asNumber().toDouble()); - return new NbtDoubleClass(args.thiz(), std::make_unique(tag)); - } - CATCH_C("Fail in Create DoubleTag!"); -} - -DoubleTag *NbtDoubleClass::extract(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine() - ->getNativeInstance(v) - ->nbt.get(); - else - return nullptr; -} - -Local NbtDoubleClass::pack(DoubleTag *tag, bool noDelete) { - try { - if (noDelete) // unique_ptr 共享指针 + noDelete - { - std::unique_ptr nbt(tag); - auto *nbtObj = new NbtDoubleClass(std::move(nbt)); - nbtObj->canDelete = false; - return nbtObj->getScriptObject(); - } else - return (new NbtDoubleClass( - std::make_unique(tag->as()))) - ->getScriptObject(); - } - CATCH("Fail in construct NbtDouble!"); +: ScriptClass(ScriptClass::ConstructFromCpp{}) { + this->nbt = std::move(p); } -Local NbtDoubleClass::pack(std::unique_ptr tag) { - try { - return (new NbtDoubleClass(std::move(tag)))->getScriptObject(); - } - CATCH("Fail in construct NbtDouble!"); +NbtDoubleClass* NbtDoubleClass::constructor(const Arguments& args) { + try { + auto tag = DoubleTag(args[0].asNumber().toDouble()); + return new NbtDoubleClass(args.thiz(), std::make_unique(tag)); + } + CATCH_C("Fail in Create DoubleTag!"); } -Local NbtDoubleClass::getType(const Arguments &args) { - return Number::newNumber((int)Tag::Type::Double); +DoubleTag* NbtDoubleClass::extract(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v)->nbt.get(); + else return nullptr; } -Local NbtDoubleClass::get(const Arguments &args) { - try { - return Number::newNumber(nbt->data); - } - CATCH("Fail in NbtValueGet!") +Local NbtDoubleClass::pack(DoubleTag* tag, bool noDelete) { + try { + if (noDelete) // unique_ptr 共享指针 + noDelete + { + std::unique_ptr nbt(tag); + auto* nbtObj = new NbtDoubleClass(std::move(nbt)); + nbtObj->canDelete = false; + return nbtObj->getScriptObject(); + } else return (new NbtDoubleClass(std::make_unique(tag->as())))->getScriptObject(); + } + CATCH("Fail in construct NbtDouble!"); } -Local NbtDoubleClass::toString(const Arguments &args) { - if (args.size() >= 1) - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local NbtDoubleClass::pack(std::unique_ptr tag) { + try { + return (new NbtDoubleClass(std::move(tag)))->getScriptObject(); + } + CATCH("Fail in construct NbtDouble!"); +} - try { - return String::newString( - TagToJson(nbt.get(), args.size() >= 1 ? args[0].toInt() : -1)); - } - CATCH("Fail in NBTtoJson!"); +Local NbtDoubleClass::getType(const Arguments& args) { return Number::newNumber((int)Tag::Type::Double); } + +Local NbtDoubleClass::get(const Arguments& args) { + try { + return Number::newNumber(nbt->data); + } + CATCH("Fail in NbtValueGet!") } -Local NbtDoubleClass::set(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); +Local NbtDoubleClass::toString(const Arguments& args) { + if (args.size() >= 1) CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - nbt->data = args[0].asNumber().toDouble(); - return Boolean::newBoolean(true); - } - CATCH("Fail in NbtValueSet!") + try { + return String::newString(TagToJson(nbt.get(), args.size() >= 1 ? args[0].toInt() : -1)); + } + CATCH("Fail in NBTtoJson!"); +} + +Local NbtDoubleClass::set(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + + try { + nbt->data = args[0].asNumber().toDouble(); + return Boolean::newBoolean(true); + } + CATCH("Fail in NbtValueSet!") } //////////////////// Classes NbtString //////////////////// -NbtStringClass::NbtStringClass(const Local &scriptObj, - std::unique_ptr p) - : ScriptClass(scriptObj) { - this->nbt = std::move(p); +NbtStringClass::NbtStringClass(const Local& scriptObj, std::unique_ptr p) : ScriptClass(scriptObj) { + this->nbt = std::move(p); } NbtStringClass::NbtStringClass(std::unique_ptr p) - : ScriptClass(ScriptClass::ConstructFromCpp{}) { - this->nbt = std::move(p); -} - -NbtStringClass *NbtStringClass::constructor(const Arguments &args) { - try { - auto tag = StringTag(args[0].toStr()); - return new NbtStringClass(args.thiz(), std::make_unique(tag)); - } - CATCH_C("Fail in Create StringTag!"); -} - -StringTag *NbtStringClass::extract(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine() - ->getNativeInstance(v) - ->nbt.get(); - else - return nullptr; -} - -Local NbtStringClass::pack(StringTag *tag, bool noDelete) { - try { - if (noDelete) // unique_ptr 共享指针 + noDelete - { - std::unique_ptr nbt(tag); - auto *nbtObj = new NbtStringClass(std::move(nbt)); - nbtObj->canDelete = false; - return nbtObj->getScriptObject(); - } else - return (new NbtStringClass( - std::make_unique(tag->as()))) - ->getScriptObject(); - } - CATCH("Fail in construct NbtString!"); +: ScriptClass(ScriptClass::ConstructFromCpp{}) { + this->nbt = std::move(p); } -Local NbtStringClass::pack(std::unique_ptr tag) { - try { - return (new NbtStringClass(std::move(tag)))->getScriptObject(); - } - CATCH("Fail in construct NbtString!"); +NbtStringClass* NbtStringClass::constructor(const Arguments& args) { + try { + auto tag = StringTag(args[0].toStr()); + return new NbtStringClass(args.thiz(), std::make_unique(tag)); + } + CATCH_C("Fail in Create StringTag!"); } -Local NbtStringClass::getType(const Arguments &args) { - return Number::newNumber((int)Tag::Type::String); +StringTag* NbtStringClass::extract(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v)->nbt.get(); + else return nullptr; } -Local NbtStringClass::get(const Arguments &args) { - try { - return String::newString(nbt->data); - } - CATCH("Fail in NbtValueGet!") +Local NbtStringClass::pack(StringTag* tag, bool noDelete) { + try { + if (noDelete) // unique_ptr 共享指针 + noDelete + { + std::unique_ptr nbt(tag); + auto* nbtObj = new NbtStringClass(std::move(nbt)); + nbtObj->canDelete = false; + return nbtObj->getScriptObject(); + } else return (new NbtStringClass(std::make_unique(tag->as())))->getScriptObject(); + } + CATCH("Fail in construct NbtString!"); } -Local NbtStringClass::toString(const Arguments &args) { - if (args.size() >= 1) - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local NbtStringClass::pack(std::unique_ptr tag) { + try { + return (new NbtStringClass(std::move(tag)))->getScriptObject(); + } + CATCH("Fail in construct NbtString!"); +} + +Local NbtStringClass::getType(const Arguments& args) { return Number::newNumber((int)Tag::Type::String); } + +Local NbtStringClass::get(const Arguments& args) { + try { + return String::newString(nbt->data); + } + CATCH("Fail in NbtValueGet!") +} + +Local NbtStringClass::toString(const Arguments& args) { + if (args.size() >= 1) CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - return String::newString( - TagToJson(nbt.get(), args.size() >= 1 ? args[0].toInt() : -1)); - } - CATCH("Fail in NBTtoJson!"); + try { + return String::newString(TagToJson(nbt.get(), args.size() >= 1 ? args[0].toInt() : -1)); + } + CATCH("Fail in NBTtoJson!"); } -Local NbtStringClass::set(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); +Local NbtStringClass::set(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); - try { - nbt->data = args[0].toStr(); - return Boolean::newBoolean(true); - } - CATCH("Fail in NbtValueSet!") + try { + nbt->data = args[0].toStr(); + return Boolean::newBoolean(true); + } + CATCH("Fail in NbtValueSet!") } //////////////////// Classes NbtByteArray //////////////////// -NbtByteArrayClass::NbtByteArrayClass(const Local &scriptObj, - std::unique_ptr p) - : ScriptClass(scriptObj) { - this->nbt = std::move(p); +NbtByteArrayClass::NbtByteArrayClass(const Local& scriptObj, std::unique_ptr p) +: ScriptClass(scriptObj) { + this->nbt = std::move(p); } NbtByteArrayClass::NbtByteArrayClass(std::unique_ptr p) - : ScriptClass(ScriptClass::ConstructFromCpp{}) { - this->nbt = std::move(p); -} - -NbtByteArrayClass *NbtByteArrayClass::constructor(const Arguments &args) { - try { - auto buf = args[0].asByteBuffer(); - std::vector array; - - TagMemoryChunk tag = TagMemoryChunk(); - tag.mBuffer = std::unique_ptr(new uchar[buf.byteLength()]); - memcpy(tag.mBuffer.get(), buf.getRawBytes(), buf.byteLength()); - std::unique_ptr arrayTag = - std::make_unique(ByteArrayTag()); - arrayTag->data = std::move(tag); - arrayTag->data.mSize = arrayTag->data.mCapacity; - return new NbtByteArrayClass(args.thiz(), std::move(arrayTag)); - } - CATCH_C("Fail in Create ByteArrayTag!"); -} - -ByteArrayTag *NbtByteArrayClass::extract(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine() - ->getNativeInstance(v) - ->nbt.get(); - else - return nullptr; -} - -Local NbtByteArrayClass::pack(ByteArrayTag *tag, bool noDelete) { - try { - if (noDelete) // unique_ptr 共享指针 + noDelete - { - std::unique_ptr nbt(tag); - auto *nbtObj = new NbtByteArrayClass(std::move(nbt)); - nbtObj->canDelete = false; - return nbtObj->getScriptObject(); - } else - return (new NbtByteArrayClass( - std::make_unique(tag->as()))) - ->getScriptObject(); - } - CATCH("Fail in construct NbtByteArray!"); +: ScriptClass(ScriptClass::ConstructFromCpp{}) { + this->nbt = std::move(p); +} + +NbtByteArrayClass* NbtByteArrayClass::constructor(const Arguments& args) { + try { + auto buf = args[0].asByteBuffer(); + std::vector array; + + TagMemoryChunk tag = TagMemoryChunk(); + tag.mBuffer = std::unique_ptr(new uchar[buf.byteLength()]); + memcpy(tag.mBuffer.get(), buf.getRawBytes(), buf.byteLength()); + std::unique_ptr arrayTag = std::make_unique(ByteArrayTag()); + arrayTag->data = std::move(tag); + arrayTag->data.mSize = arrayTag->data.mCapacity; + return new NbtByteArrayClass(args.thiz(), std::move(arrayTag)); + } + CATCH_C("Fail in Create ByteArrayTag!"); } -Local NbtByteArrayClass::pack(std::unique_ptr tag) { - try { - return (new NbtByteArrayClass(std::move(tag)))->getScriptObject(); - } - CATCH("Fail in construct NbtByteArray!"); +ByteArrayTag* NbtByteArrayClass::extract(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v)->nbt.get(); + else return nullptr; } -Local NbtByteArrayClass::getType(const Arguments &args) { - return Number::newNumber((int)Tag::Type::ByteArray); +Local NbtByteArrayClass::pack(ByteArrayTag* tag, bool noDelete) { + try { + if (noDelete) // unique_ptr 共享指针 + noDelete + { + std::unique_ptr nbt(tag); + auto* nbtObj = new NbtByteArrayClass(std::move(nbt)); + nbtObj->canDelete = false; + return nbtObj->getScriptObject(); + } else + return (new NbtByteArrayClass(std::make_unique(tag->as())))->getScriptObject(); + } + CATCH("Fail in construct NbtByteArray!"); } -Local NbtByteArrayClass::get(const Arguments &args) { - try { - auto &data = nbt->data; - return ByteBuffer::newByteBuffer((char *)data.mBuffer.get(), data.mSize); - } - CATCH("Fail in NbtValueGet!") +Local NbtByteArrayClass::pack(std::unique_ptr tag) { + try { + return (new NbtByteArrayClass(std::move(tag)))->getScriptObject(); + } + CATCH("Fail in construct NbtByteArray!"); } -Local NbtByteArrayClass::toString(const Arguments &args) { - if (args.size() >= 1) - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local NbtByteArrayClass::getType(const Arguments& args) { return Number::newNumber((int)Tag::Type::ByteArray); } - try { - return String::newString( - TagToJson(nbt.get(), args.size() >= 1 ? args[0].toInt() : -1)); - } - CATCH("Fail in NBTtoJson!"); +Local NbtByteArrayClass::get(const Arguments& args) { + try { + auto& data = nbt->data; + return ByteBuffer::newByteBuffer((char*)data.mBuffer.get(), data.mSize); + } + CATCH("Fail in NbtValueGet!") } -Local NbtByteArrayClass::set(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); +Local NbtByteArrayClass::toString(const Arguments& args) { + if (args.size() >= 1) CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Local buf = args[0].asByteBuffer(); - TagMemoryChunk tag = TagMemoryChunk(); - tag.mBuffer = std::unique_ptr(new uchar[buf.byteLength()]); - memcpy(tag.mBuffer.get(), buf.getRawBytes(), buf.byteLength()); - nbt->data = tag; - return Boolean::newBoolean(true); - } - CATCH("Fail in NbtValueSet!") + try { + return String::newString(TagToJson(nbt.get(), args.size() >= 1 ? args[0].toInt() : -1)); + } + CATCH("Fail in NBTtoJson!"); +} + +Local NbtByteArrayClass::set(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + + try { + Local buf = args[0].asByteBuffer(); + TagMemoryChunk tag = TagMemoryChunk(); + tag.mBuffer = std::unique_ptr(new uchar[buf.byteLength()]); + memcpy(tag.mBuffer.get(), buf.getRawBytes(), buf.byteLength()); + nbt->data = tag; + return Boolean::newBoolean(true); + } + CATCH("Fail in NbtValueSet!") } //////////////////// Classes NbtList //////////////////// -NbtListClass::NbtListClass(const Local &scriptObj, - std::unique_ptr p) - : ScriptClass(scriptObj) { - this->nbt = std::move(p); +NbtListClass::NbtListClass(const Local& scriptObj, std::unique_ptr p) : ScriptClass(scriptObj) { + this->nbt = std::move(p); } -NbtListClass::NbtListClass(std::unique_ptr p) - : ScriptClass(ScriptClass::ConstructFromCpp{}) { - this->nbt = std::move(p); +NbtListClass::NbtListClass(std::unique_ptr p) : ScriptClass(ScriptClass::ConstructFromCpp{}) { + this->nbt = std::move(p); } ////////////////// Helper ////////////////// -void NbtListClassAddHelper(ListTag *tag, Local &arr) { - if (arr.size() > 0) { - Local t = arr.get(0); - if (IsInstanceOf(t)) - for (int i = 0; i < arr.size(); ++i) - tag->add(NbtEndClass::extract(arr.get(i))->copy()); - else if (IsInstanceOf(t)) - for (int i = 0; i < arr.size(); ++i) - tag->add(NbtByteClass::extract(arr.get(i))->copy()); - else if (IsInstanceOf(t)) - for (int i = 0; i < arr.size(); ++i) - tag->add(NbtShortClass::extract(arr.get(i))->copy()); - else if (IsInstanceOf(t)) - for (int i = 0; i < arr.size(); ++i) - tag->add(NbtIntClass::extract(arr.get(i))->copy()); - else if (IsInstanceOf(t)) - for (int i = 0; i < arr.size(); ++i) - tag->add(NbtLongClass::extract(arr.get(i))->copy()); - else if (IsInstanceOf(t)) - for (int i = 0; i < arr.size(); ++i) - tag->add(NbtFloatClass::extract(arr.get(i))->copy()); - else if (IsInstanceOf(t)) - for (int i = 0; i < arr.size(); ++i) - tag->add(NbtDoubleClass::extract(arr.get(i))->copy()); - else if (IsInstanceOf(t)) - for (int i = 0; i < arr.size(); ++i) - tag->add(NbtStringClass::extract(arr.get(i))->copy()); - else if (IsInstanceOf(t)) - for (int i = 0; i < arr.size(); ++i) - tag->add(NbtByteArrayClass::extract(arr.get(i))->copy()); - else if (IsInstanceOf(t)) - for (int i = 0; i < arr.size(); ++i) - tag->add(NbtListClass::extract(arr.get(i))->copyList()); - else if (IsInstanceOf(t)) - for (int i = 0; i < arr.size(); ++i) - tag->add(NbtCompoundClass::extract(arr.get(i))->clone()); - else if (t.isArray()) { - for (int i = 0; i < arr.size(); ++i) { - auto arrTag = ListTag(); - auto data = arr.get(i).asArray(); - NbtListClassAddHelper(&arrTag, data); - tag->add(std::move(arrTag)); - } - } else if (t.isObject()) { - for (int i = 0; i < arr.size(); ++i) { - auto objTag = CompoundTag(); - auto data = arr.get(i).asObject(); - NbtCompoundClassAddHelper(&objTag, data); - tag->add(std::move(objTag)); - } - } else { - throw script::Exception("Wrong Type of data to set into NBT List!"); - } - } -} - -NbtListClass *NbtListClass::constructor(const Arguments &args) { - try { - auto tag = ListTag(); - - if (args.size() >= 1 && args[0].isArray()) { - auto arr = args[0].asArray(); - NbtListClassAddHelper(&tag, arr); - } - - return new NbtListClass(args.thiz(), std::make_unique(tag)); - } - CATCH_C("Fail in Create ListTag!"); -} - -ListTag *NbtListClass::extract(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine() - ->getNativeInstance(v) - ->nbt.get(); - else - return nullptr; -} - -Local NbtListClass::pack(ListTag *tag, bool noDelete) { - try { - if (noDelete) // unique_ptr 共享指针 + noDelete - { - std::unique_ptr nbt(tag); - auto *nbtObj = new NbtListClass(std::move(nbt)); - nbtObj->canDelete = false; - return nbtObj->getScriptObject(); - } else - return (new NbtListClass(tag->copyList()))->getScriptObject(); - } - CATCH("Fail in construct NbtList!"); +void NbtListClassAddHelper(ListTag* tag, Local& arr) { + if (arr.size() > 0) { + Local t = arr.get(0); + if (IsInstanceOf(t)) + for (int i = 0; i < arr.size(); ++i) tag->add(NbtEndClass::extract(arr.get(i))->copy()); + else if (IsInstanceOf(t)) + for (int i = 0; i < arr.size(); ++i) tag->add(NbtByteClass::extract(arr.get(i))->copy()); + else if (IsInstanceOf(t)) + for (int i = 0; i < arr.size(); ++i) tag->add(NbtShortClass::extract(arr.get(i))->copy()); + else if (IsInstanceOf(t)) + for (int i = 0; i < arr.size(); ++i) tag->add(NbtIntClass::extract(arr.get(i))->copy()); + else if (IsInstanceOf(t)) + for (int i = 0; i < arr.size(); ++i) tag->add(NbtLongClass::extract(arr.get(i))->copy()); + else if (IsInstanceOf(t)) + for (int i = 0; i < arr.size(); ++i) tag->add(NbtFloatClass::extract(arr.get(i))->copy()); + else if (IsInstanceOf(t)) + for (int i = 0; i < arr.size(); ++i) tag->add(NbtDoubleClass::extract(arr.get(i))->copy()); + else if (IsInstanceOf(t)) + for (int i = 0; i < arr.size(); ++i) tag->add(NbtStringClass::extract(arr.get(i))->copy()); + else if (IsInstanceOf(t)) + for (int i = 0; i < arr.size(); ++i) tag->add(NbtByteArrayClass::extract(arr.get(i))->copy()); + else if (IsInstanceOf(t)) + for (int i = 0; i < arr.size(); ++i) tag->add(NbtListClass::extract(arr.get(i))->copyList()); + else if (IsInstanceOf(t)) + for (int i = 0; i < arr.size(); ++i) tag->add(NbtCompoundClass::extract(arr.get(i))->clone()); + else if (t.isArray()) { + for (int i = 0; i < arr.size(); ++i) { + auto arrTag = ListTag(); + auto data = arr.get(i).asArray(); + NbtListClassAddHelper(&arrTag, data); + tag->add(std::move(arrTag)); + } + } else if (t.isObject()) { + for (int i = 0; i < arr.size(); ++i) { + auto objTag = CompoundTag(); + auto data = arr.get(i).asObject(); + NbtCompoundClassAddHelper(&objTag, data); + tag->add(std::move(objTag)); + } + } else { + throw script::Exception("Wrong Type of data to set into NBT List!"); + } + } +} + +NbtListClass* NbtListClass::constructor(const Arguments& args) { + try { + auto tag = ListTag(); + + if (args.size() >= 1 && args[0].isArray()) { + auto arr = args[0].asArray(); + NbtListClassAddHelper(&tag, arr); + } + + return new NbtListClass(args.thiz(), std::make_unique(tag)); + } + CATCH_C("Fail in Create ListTag!"); +} + +ListTag* NbtListClass::extract(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v)->nbt.get(); + else return nullptr; +} + +Local NbtListClass::pack(ListTag* tag, bool noDelete) { + try { + if (noDelete) // unique_ptr 共享指针 + noDelete + { + std::unique_ptr nbt(tag); + auto* nbtObj = new NbtListClass(std::move(nbt)); + nbtObj->canDelete = false; + return nbtObj->getScriptObject(); + } else return (new NbtListClass(tag->copyList()))->getScriptObject(); + } + CATCH("Fail in construct NbtList!"); } Local NbtListClass::pack(std::unique_ptr tag) { - try { - return (new NbtListClass(std::move(tag)))->getScriptObject(); - } - CATCH("Fail in construct NbtList!"); + try { + return (new NbtListClass(std::move(tag)))->getScriptObject(); + } + CATCH("Fail in construct NbtList!"); } -Local NbtListClass::getType(const Arguments &args) { - return Number::newNumber((int)Tag::Type::List); +Local NbtListClass::getType(const Arguments& args) { return Number::newNumber((int)Tag::Type::List); } + +Local NbtListClass::getSize(const Arguments& args) { + try { + return Number::newNumber((int)nbt->size()); + } + CATCH("Fail in NBT GetSize!"); } -Local NbtListClass::getSize(const Arguments &args) { - try { - return Number::newNumber((int)nbt->size()); - } - CATCH("Fail in NBT GetSize!"); +Local NbtListClass::getTypeOf(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + + try { + auto list = nbt.get(); + auto index = args[0].toInt(); + + if (index >= list->size() || index < 0) { + return Local(); + } + + return Number::newNumber(int(list[index].getId())); + } + CATCH("Fail in NBT GetTypeOf!"); } -Local NbtListClass::getTypeOf(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local NbtListClass::setEnd(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - auto list = nbt.get(); - auto index = args[0].toInt(); + try { + auto list = nbt.get(); + auto index = args[0].toInt(); + + if (index >= list->size() || index < 0) { + LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!"); + } else if (list[0].getId() != Tag::Type::End) { + LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!"); + } else { + list[index].as_ptr(); + } + return this->getScriptObject(); + } + CATCH("Fail in NBT SetEnd!"); +} - if (index >= list->size() || index < 0) { - return Local(); +Local NbtListClass::setByte(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + + try { + auto list = nbt.get(); + auto index = args[0].toInt(); + + if (index >= list->size() || index < 0) { + LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!"); + } else if (list[0].getId() != Tag::Type::Byte) { + LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!"); + } else { + list[index].as_ptr()->data = args[1].toInt(); + } + return this->getScriptObject(); } + CATCH("Fail in NBT SetByte!"); +} - return Number::newNumber(int(list[index].getId())); - } - CATCH("Fail in NBT GetTypeOf!"); +Local NbtListClass::setInt(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + + try { + auto list = nbt.get(); + auto index = args[0].toInt(); + + if (index >= list->size() || index < 0) { + LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!"); + } else if (list[0].getId() != Tag::Type::Int) { + LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!"); + } else { + list[index].as_ptr()->data = args[1].toInt(); + } + return this->getScriptObject(); + } + CATCH("Fail in NBT SetInt!"); } -Local NbtListClass::setEnd(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local NbtListClass::setShort(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + + try { + auto list = nbt.get(); + auto index = args[0].toInt(); + + if (index >= list->size() || index < 0) { + LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!"); + } else if (list[0].getId() != Tag::Type::Short) { + LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!"); + } else { + list[index].as_ptr()->data = args[1].toInt(); + } + return this->getScriptObject(); + } + CATCH("Fail in NBT SetShort!"); +} - try { - auto list = nbt.get(); - auto index = args[0].toInt(); +Local NbtListClass::setLong(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + + try { + auto list = nbt.get(); + auto index = args[0].toInt(); + + if (index >= list->size() || index < 0) { + LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!"); + } else if (list[0].getId() != Tag::Type::Int64) { + LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!"); + } else { + list[index].as_ptr()->data = args[1].asNumber().toInt64(); + } + return this->getScriptObject(); + } + CATCH("Fail in NBT SetLong!"); +} + +Local NbtListClass::setFloat(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + + try { + auto list = nbt.get(); + auto index = args[0].toInt(); + + if (index >= list->size() || index < 0) { + LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!"); + } else if (list[0].getId() != Tag::Type::Float) { + LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!"); + } else { + list[index].as_ptr()->data = args[1].asNumber().toFloat(); + } + return this->getScriptObject(); + } + CATCH("Fail in NBT SetFloat!"); +} - if (index >= list->size() || index < 0) { - LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!"); - } else if (list[0].getId() != Tag::Type::End) { - LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!"); - } else { - list[index].as_ptr(); +Local NbtListClass::setDouble(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + + try { + auto list = nbt.get(); + auto index = args[0].toInt(); + + if (index >= list->size() || index < 0) { + LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!"); + } else if (list[0].getId() != Tag::Type::Double) { + LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!"); + } else { + list[index].as_ptr()->data = args[1].asNumber().toDouble(); + } + return this->getScriptObject(); } - return this->getScriptObject(); - } - CATCH("Fail in NBT SetEnd!"); + CATCH("Fail in NBT SetDouble!"); } -Local NbtListClass::setByte(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); +Local NbtListClass::setString(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + + try { + auto list = nbt.get(); + auto index = args[0].toInt(); - try { - auto list = nbt.get(); - auto index = args[0].toInt(); + if (index >= list->size() || index < 0) { + LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!"); + } else if (list[0].getId() != Tag::Type::String) { + LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!"); + } else { + list[index].as_ptr()->data = args[1].toStr(); + } - if (index >= list->size() || index < 0) { - LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!"); - } else if (list[0].getId() != Tag::Type::Byte) { - LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!"); - } else { - list[index].as_ptr()->data = args[1].toInt(); + return this->getScriptObject(); } - return this->getScriptObject(); - } - CATCH("Fail in NBT SetByte!"); + CATCH("Fail in NBT SetString!"); } -Local NbtListClass::setInt(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); +Local NbtListClass::setByteArray(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kByteBuffer); + + try { + auto list = nbt.get(); + auto index = args[0].toInt(); + + if (index >= list->size() || index < 0) { + LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!"); + } else if (list[0].getId() != Tag::Type::ByteArray) { + LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!"); + } else { + auto data = args[1].asByteBuffer(); + TagMemoryChunk tag = TagMemoryChunk(); + tag.mBuffer = std::unique_ptr(new uchar[data.byteLength()]); + memcpy(tag.mBuffer.get(), data.getRawBytes(), data.byteLength()); + list[index].as_ptr()->data = tag; + } + return this->getScriptObject(); + } + CATCH("Fail in NBT SetByteArray!"); +} - try { - auto list = nbt.get(); - auto index = args[0].toInt(); +Local NbtListClass::setTag(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - if (index >= list->size() || index < 0) { - LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!"); - } else if (list[0].getId() != Tag::Type::Int) { - LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!"); - } else { - list[index].as_ptr()->data = args[1].toInt(); + try { + auto& list = nbt->mList; + auto index = args[0].toInt(); + + if (index >= list.size() || index < 0) { + LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!"); + return Local(); + } + + if (IsInstanceOf(args[1])) { + list[index] = std::unique_ptr(NbtEndClass::extract(args[1])); + } else if (IsInstanceOf(args[1])) { + list[index] = std::unique_ptr(NbtByteClass::extract(args[1])); + } else if (IsInstanceOf(args[1])) { + list[index] = std::unique_ptr(NbtShortClass::extract(args[1])); + } else if (IsInstanceOf(args[1])) { + list[index] = std::unique_ptr(NbtIntClass::extract(args[1])); + } else if (IsInstanceOf(args[1])) { + list[index] = std::unique_ptr(NbtLongClass::extract(args[1])); + } else if (IsInstanceOf(args[1])) { + list[index] = std::unique_ptr(NbtFloatClass::extract(args[1])); + } else if (IsInstanceOf(args[1])) { + list[index] = std::unique_ptr(NbtDoubleClass::extract(args[1])); + } else if (IsInstanceOf(args[1])) { + list[index] = std::unique_ptr(NbtStringClass::extract(args[1])); + } else if (IsInstanceOf(args[1])) { + list[index] = std::unique_ptr(NbtByteArrayClass::extract(args[1])); + } else if (IsInstanceOf(args[1])) { + list[index] = std::unique_ptr(NbtListClass::extract(args[1])); + } else if (IsInstanceOf(args[1])) { + list[index] = std::unique_ptr(NbtCompoundClass::extract(args[1])); + } else { + LOG_ERROR_WITH_SCRIPT_INFO("Unknown type! Cannot set Tag into List"); + return Local(); + } + return this->getScriptObject(); + } + CATCH("Fail in NBT SetTag!"); +} + +Local NbtListClass::addTag(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + + try { + if (IsInstanceOf(args[0])) { + nbt->add(NbtEndClass::extract(args[0])->copy()); + } else if (IsInstanceOf(args[0])) { + nbt->add(NbtByteClass::extract(args[0])->copy()); + } else if (IsInstanceOf(args[0])) { + nbt->add(NbtShortClass::extract(args[0])->copy()); + } else if (IsInstanceOf(args[0])) { + nbt->add(NbtIntClass::extract(args[0])->copy()); + } else if (IsInstanceOf(args[0])) { + nbt->add(NbtLongClass::extract(args[0])->copy()); + } else if (IsInstanceOf(args[0])) { + nbt->add(NbtFloatClass::extract(args[0])->copy()); + } else if (IsInstanceOf(args[0])) { + nbt->add(NbtDoubleClass::extract(args[0])->copy()); + } else if (IsInstanceOf(args[0])) { + nbt->add(NbtStringClass::extract(args[0])->copy()); + } else if (IsInstanceOf(args[0])) { + nbt->add(NbtByteArrayClass::extract(args[0])->copy()); + } else if (IsInstanceOf(args[0])) { + nbt->add(NbtListClass::extract(args[0])->copyList()); + } else if (IsInstanceOf(args[0])) { + nbt->add(NbtCompoundClass::extract(args[0])->clone()); + } else { + LOG_ERROR_WITH_SCRIPT_INFO("Unknown type! Cannot add Tag into List"); + return Local(); + } + return this->getScriptObject(); } - return this->getScriptObject(); - } - CATCH("Fail in NBT SetInt!"); + CATCH("Fail in NBT AddTag!"); } -Local NbtListClass::setShort(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); +Local NbtListClass::removeTag(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + + try { + auto& list = nbt->mList; + auto index = args[0].toInt(); - try { - auto list = nbt.get(); - auto index = args[0].toInt(); + if (index >= list.size() || index < 0) { + LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!"); + return Local(); + } - if (index >= list->size() || index < 0) { - LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!"); - } else if (list[0].getId() != Tag::Type::Short) { - LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!"); - } else { - list[index].as_ptr()->data = args[1].toInt(); + list.erase(list.begin() + index); //===== delete? + return this->getScriptObject(); } - return this->getScriptObject(); - } - CATCH("Fail in NBT SetShort!"); + CATCH("Fail in NBT SetTag!"); } -Local NbtListClass::setLong(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - - try { - auto list = nbt.get(); - auto index = args[0].toInt(); - - if (index >= list->size() || index < 0) { - LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!"); - } else if (list[0].getId() != Tag::Type::Int64) { - LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!"); - } else { - list[index].as_ptr()->data = args[1].asNumber().toInt64(); - } - return this->getScriptObject(); - } - CATCH("Fail in NBT SetLong!"); -} - -Local NbtListClass::setFloat(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - - try { - auto list = nbt.get(); - auto index = args[0].toInt(); - - if (index >= list->size() || index < 0) { - LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!"); - } else if (list[0].getId() != Tag::Type::Float) { - LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!"); - } else { - list[index].as_ptr()->data = args[1].asNumber().toFloat(); - } - return this->getScriptObject(); - } - CATCH("Fail in NBT SetFloat!"); -} - -Local NbtListClass::setDouble(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - - try { - auto list = nbt.get(); - auto index = args[0].toInt(); - - if (index >= list->size() || index < 0) { - LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!"); - } else if (list[0].getId() != Tag::Type::Double) { - LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!"); - } else { - list[index].as_ptr()->data = args[1].asNumber().toDouble(); - } - return this->getScriptObject(); - } - CATCH("Fail in NBT SetDouble!"); -} - -Local NbtListClass::setString(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - - try { - auto list = nbt.get(); - auto index = args[0].toInt(); - - if (index >= list->size() || index < 0) { - LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!"); - } else if (list[0].getId() != Tag::Type::String) { - LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!"); - } else { - list[index].as_ptr()->data = args[1].toStr(); - } - - return this->getScriptObject(); - } - CATCH("Fail in NBT SetString!"); -} - -Local NbtListClass::setByteArray(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kByteBuffer); - - try { - auto list = nbt.get(); - auto index = args[0].toInt(); - - if (index >= list->size() || index < 0) { - LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!"); - } else if (list[0].getId() != Tag::Type::ByteArray) { - LOG_ERROR_WITH_SCRIPT_INFO("Set wrong type of element into NBT List!"); - } else { - auto data = args[1].asByteBuffer(); - TagMemoryChunk tag = TagMemoryChunk(); - tag.mBuffer = std::unique_ptr(new uchar[data.byteLength()]); - memcpy(tag.mBuffer.get(), data.getRawBytes(), data.byteLength()); - list[index].as_ptr()->data = tag; - } - return this->getScriptObject(); - } - CATCH("Fail in NBT SetByteArray!"); -} - -Local NbtListClass::setTag(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - - try { - auto &list = nbt->mList; - auto index = args[0].toInt(); - - if (index >= list.size() || index < 0) { - LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!"); - return Local(); - } - - if (IsInstanceOf(args[1])) { - list[index] = std::unique_ptr(NbtEndClass::extract(args[1])); - } else if (IsInstanceOf(args[1])) { - list[index] = std::unique_ptr(NbtByteClass::extract(args[1])); - } else if (IsInstanceOf(args[1])) { - list[index] = std::unique_ptr(NbtShortClass::extract(args[1])); - } else if (IsInstanceOf(args[1])) { - list[index] = std::unique_ptr(NbtIntClass::extract(args[1])); - } else if (IsInstanceOf(args[1])) { - list[index] = std::unique_ptr(NbtLongClass::extract(args[1])); - } else if (IsInstanceOf(args[1])) { - list[index] = std::unique_ptr(NbtFloatClass::extract(args[1])); - } else if (IsInstanceOf(args[1])) { - list[index] = - std::unique_ptr(NbtDoubleClass::extract(args[1])); - } else if (IsInstanceOf(args[1])) { - list[index] = - std::unique_ptr(NbtStringClass::extract(args[1])); - } else if (IsInstanceOf(args[1])) { - list[index] = - std::unique_ptr(NbtByteArrayClass::extract(args[1])); - } else if (IsInstanceOf(args[1])) { - list[index] = std::unique_ptr(NbtListClass::extract(args[1])); - } else if (IsInstanceOf(args[1])) { - list[index] = - std::unique_ptr(NbtCompoundClass::extract(args[1])); - } else { - LOG_ERROR_WITH_SCRIPT_INFO("Unknown type! Cannot set Tag into List"); - return Local(); - } - return this->getScriptObject(); - } - CATCH("Fail in NBT SetTag!"); -} - -Local NbtListClass::addTag(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - - try { - if (IsInstanceOf(args[0])) { - nbt->add(NbtEndClass::extract(args[0])->copy()); - } else if (IsInstanceOf(args[0])) { - nbt->add(NbtByteClass::extract(args[0])->copy()); - } else if (IsInstanceOf(args[0])) { - nbt->add(NbtShortClass::extract(args[0])->copy()); - } else if (IsInstanceOf(args[0])) { - nbt->add(NbtIntClass::extract(args[0])->copy()); - } else if (IsInstanceOf(args[0])) { - nbt->add(NbtLongClass::extract(args[0])->copy()); - } else if (IsInstanceOf(args[0])) { - nbt->add(NbtFloatClass::extract(args[0])->copy()); - } else if (IsInstanceOf(args[0])) { - nbt->add(NbtDoubleClass::extract(args[0])->copy()); - } else if (IsInstanceOf(args[0])) { - nbt->add(NbtStringClass::extract(args[0])->copy()); - } else if (IsInstanceOf(args[0])) { - nbt->add(NbtByteArrayClass::extract(args[0])->copy()); - } else if (IsInstanceOf(args[0])) { - nbt->add(NbtListClass::extract(args[0])->copyList()); - } else if (IsInstanceOf(args[0])) { - nbt->add(NbtCompoundClass::extract(args[0])->clone()); - } else { - LOG_ERROR_WITH_SCRIPT_INFO("Unknown type! Cannot add Tag into List"); - return Local(); - } - return this->getScriptObject(); - } - CATCH("Fail in NBT AddTag!"); -} - -Local NbtListClass::removeTag(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - - try { - auto &list = nbt->mList; - auto index = args[0].toInt(); - - if (index >= list.size() || index < 0) { - LOG_ERROR_WITH_SCRIPT_INFO("Bad Index of NBT List!"); - return Local(); - } - - list.erase(list.begin() + index); //===== delete? - return this->getScriptObject(); - } - CATCH("Fail in NBT SetTag!"); -} - -Local NbtListClass::getData(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - - try { - auto &list = nbt->mList; - auto index = args[0].toInt(); - - if (index >= list.size() || index < 0) { - return Local(); - } - - return Tag2Value(list[index].get()); - } - CATCH("Fail in NBTgetData!") -} - -Local NbtListClass::getTag(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - - try { - auto &list = nbt->mList; - auto index = args[0].toInt(); - - if (index >= list.size() || index < 0) { - return Local(); - } - - Local res; - switch (list[index]->getId()) { - case Tag::Type::End: - res = NbtEndClass::pack(list[index]->as_ptr(), true); // share ptr - break; - case Tag::Type::Byte: - res = NbtByteClass::pack(list[index]->as_ptr(), - true); // share ptr - break; - case Tag::Type::Short: - res = NbtShortClass::pack(list[index]->as_ptr(), - true); // share ptr - break; - case Tag::Type::Int: - res = NbtIntClass::pack(list[index]->as_ptr(), - true); // share ptr - break; - case Tag::Type::Int64: - res = NbtLongClass::pack(list[index]->as_ptr(), - true); // share ptr - break; - case Tag::Type::Float: - res = NbtFloatClass::pack(list[index]->as_ptr(), - true); // share ptr - break; - case Tag::Type::Double: - res = NbtDoubleClass::pack(list[index]->as_ptr(), true); - // share ptr - break; - case Tag::Type::String: - res = NbtStringClass::pack(list[index]->as_ptr(), - true); // share ptr - break; - case Tag::Type::ByteArray: - res = NbtByteArrayClass::pack(list[index]->as_ptr(), +Local NbtListClass::getData(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + + try { + auto& list = nbt->mList; + auto index = args[0].toInt(); + + if (index >= list.size() || index < 0) { + return Local(); + } + + return Tag2Value(list[index].get()); + } + CATCH("Fail in NBTgetData!") +} + +Local NbtListClass::getTag(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + + try { + auto& list = nbt->mList; + auto index = args[0].toInt(); + + if (index >= list.size() || index < 0) { + return Local(); + } + + Local res; + switch (list[index]->getId()) { + case Tag::Type::End: + res = NbtEndClass::pack(list[index]->as_ptr(), true); // share ptr + break; + case Tag::Type::Byte: + res = NbtByteClass::pack(list[index]->as_ptr(), + true); // share ptr + break; + case Tag::Type::Short: + res = NbtShortClass::pack(list[index]->as_ptr(), + true); // share ptr + break; + case Tag::Type::Int: + res = NbtIntClass::pack(list[index]->as_ptr(), true); // share ptr - break; - case Tag::Type::List: - res = - NbtListClass::pack(list[index]->as_ptr(), true); // share ptr - break; - case Tag::Type::Compound: - res = NbtCompoundClass::pack(list[index]->as_ptr(), - true); // share ptr - break; - default: - res = Local(); - break; + break; + case Tag::Type::Int64: + res = NbtLongClass::pack(list[index]->as_ptr(), + true); // share ptr + break; + case Tag::Type::Float: + res = NbtFloatClass::pack(list[index]->as_ptr(), + true); // share ptr + break; + case Tag::Type::Double: + res = NbtDoubleClass::pack(list[index]->as_ptr(), true); + // share ptr + break; + case Tag::Type::String: + res = NbtStringClass::pack(list[index]->as_ptr(), + true); // share ptr + break; + case Tag::Type::ByteArray: + res = NbtByteArrayClass::pack(list[index]->as_ptr(), + true); // share ptr + break; + case Tag::Type::List: + res = NbtListClass::pack(list[index]->as_ptr(), true); // share ptr + break; + case Tag::Type::Compound: + res = NbtCompoundClass::pack(list[index]->as_ptr(), + true); // share ptr + break; + default: + res = Local(); + break; + } + return res; } - return res; - } - CATCH("Fail in NBT GetTag!"); + CATCH("Fail in NBT GetTag!"); } -Local NbtListClass::toArray(const Arguments &args) { - try { - auto &list = nbt->mList; - Local arr = Array::newArray(); +Local NbtListClass::toArray(const Arguments& args) { + try { + auto& list = nbt->mList; + Local arr = Array::newArray(); - for (auto &tag : list) { - arr.add(Tag2Value(tag.get(), true)); + for (auto& tag : list) { + arr.add(Tag2Value(tag.get(), true)); + } + return arr; } - return arr; - } - CATCH("Fail in NBTtoArray!"); + CATCH("Fail in NBTtoArray!"); } -Local NbtListClass::toString(const Arguments &args) { - if (args.size() >= 1) - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local NbtListClass::toString(const Arguments& args) { + if (args.size() >= 1) CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - return String::newString( - TagToJson(nbt.get(), args.size() >= 1 ? args[0].toInt() : -1)); - } - CATCH("Fail in NBTtoJson!"); + try { + return String::newString(TagToJson(nbt.get(), args.size() >= 1 ? args[0].toInt() : -1)); + } + CATCH("Fail in NBTtoJson!"); } //////////////////// Classes NbtCompound //////////////////// -NbtCompoundClass::NbtCompoundClass(const Local &scriptObj, - std::unique_ptr p) - : ScriptClass(scriptObj) { - nbt = std::move(p); +NbtCompoundClass::NbtCompoundClass(const Local& scriptObj, std::unique_ptr p) +: ScriptClass(scriptObj) { + nbt = std::move(p); } NbtCompoundClass::NbtCompoundClass(std::unique_ptr p) - : ScriptClass(ScriptClass::ConstructFromCpp{}) { - nbt = std::move(p); +: ScriptClass(ScriptClass::ConstructFromCpp{}) { + nbt = std::move(p); } ////////////////// Helper ////////////////// -void NbtCompoundClassAddHelper(CompoundTag *tag, Local &obj) { - auto keys = obj.getKeyNames(); - if (keys.size() > 0) { - for (int i = 0; i < keys.size(); ++i) { - Local t = obj.get(keys[i]); - if (IsInstanceOf(t)) - tag->put(keys[i], NbtEndClass::extract(obj.get(keys[i]))->copy()); - else if (IsInstanceOf(t)) - tag->put(keys[i], NbtByteClass::extract(obj.get(keys[i]))->copy()); - else if (IsInstanceOf(t)) - tag->put(keys[i], NbtShortClass::extract(obj.get(keys[i]))->copy()); - else if (IsInstanceOf(t)) - tag->put(keys[i], NbtIntClass::extract(obj.get(keys[i]))->copy()); - else if (IsInstanceOf(t)) - tag->put(keys[i], NbtLongClass::extract(obj.get(keys[i]))->copy()); - else if (IsInstanceOf(t)) - tag->put(keys[i], NbtFloatClass::extract(obj.get(keys[i]))->copy()); - else if (IsInstanceOf(t)) - tag->put(keys[i], NbtDoubleClass::extract(obj.get(keys[i]))->copy()); - else if (IsInstanceOf(t)) - tag->put(keys[i], NbtStringClass::extract(obj.get(keys[i]))->copy()); - else if (IsInstanceOf(t)) - tag->put(keys[i], NbtByteArrayClass::extract(obj.get(keys[i]))->copy()); - else if (IsInstanceOf(t)) - tag->put(keys[i], NbtListClass::extract(obj.get(keys[i]))->copyList()); - else if (IsInstanceOf(t)) - tag->put(keys[i], NbtCompoundClass::extract(obj.get(keys[i]))->clone()); - else if (t.isArray()) { - auto arrTag = ListTag(); - auto data = obj.get(keys[i]).asArray(); - NbtListClassAddHelper(&arrTag, data); - tag->put(keys[i], std::move(arrTag)); - } else if (t.isObject()) { - auto objTag = CompoundTag(); - auto data = obj.get(keys[i]).asObject(); - NbtCompoundClassAddHelper(&objTag, data); - tag->put(keys[i], std::move(objTag)); - } else { - LOG_ERROR_WITH_SCRIPT_INFO( - "Wrong Type of data to set into NBT Compound!"); - } - } - } -} - -NbtCompoundClass *NbtCompoundClass::constructor(const Arguments &args) { - try { - auto tag = CompoundTag(); - - if (args.size() >= 1 && args[0].isObject()) { - auto obj = args[0].asObject(); - NbtCompoundClassAddHelper(&tag, obj); - } - - return new NbtCompoundClass(args.thiz(), - std::make_unique(tag)); - } - CATCH_C("Fail in Create ListTag!"); -} - -CompoundTag *NbtCompoundClass::extract(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine() - ->getNativeInstance(v) - ->nbt.get(); - else - return nullptr; -} - -Local NbtCompoundClass::pack(CompoundTag *tag, bool noDelete) { - try { - if (noDelete) // unique_ptr 共享指针 + noDelete - { - std::unique_ptr nbt(tag); - auto *nbtObj = new NbtCompoundClass(std::move(nbt)); - nbtObj->canDelete = false; - return nbtObj->getScriptObject(); - } else - return (new NbtCompoundClass(tag->clone()))->getScriptObject(); - } - CATCH("Fail in construct NbtCompound!"); +void NbtCompoundClassAddHelper(CompoundTag* tag, Local& obj) { + auto keys = obj.getKeyNames(); + if (keys.size() > 0) { + for (int i = 0; i < keys.size(); ++i) { + Local t = obj.get(keys[i]); + if (IsInstanceOf(t)) tag->put(keys[i], NbtEndClass::extract(obj.get(keys[i]))->copy()); + else if (IsInstanceOf(t)) tag->put(keys[i], NbtByteClass::extract(obj.get(keys[i]))->copy()); + else if (IsInstanceOf(t)) + tag->put(keys[i], NbtShortClass::extract(obj.get(keys[i]))->copy()); + else if (IsInstanceOf(t)) tag->put(keys[i], NbtIntClass::extract(obj.get(keys[i]))->copy()); + else if (IsInstanceOf(t)) tag->put(keys[i], NbtLongClass::extract(obj.get(keys[i]))->copy()); + else if (IsInstanceOf(t)) + tag->put(keys[i], NbtFloatClass::extract(obj.get(keys[i]))->copy()); + else if (IsInstanceOf(t)) + tag->put(keys[i], NbtDoubleClass::extract(obj.get(keys[i]))->copy()); + else if (IsInstanceOf(t)) + tag->put(keys[i], NbtStringClass::extract(obj.get(keys[i]))->copy()); + else if (IsInstanceOf(t)) + tag->put(keys[i], NbtByteArrayClass::extract(obj.get(keys[i]))->copy()); + else if (IsInstanceOf(t)) + tag->put(keys[i], NbtListClass::extract(obj.get(keys[i]))->copyList()); + else if (IsInstanceOf(t)) + tag->put(keys[i], NbtCompoundClass::extract(obj.get(keys[i]))->clone()); + else if (t.isArray()) { + auto arrTag = ListTag(); + auto data = obj.get(keys[i]).asArray(); + NbtListClassAddHelper(&arrTag, data); + tag->put(keys[i], std::move(arrTag)); + } else if (t.isObject()) { + auto objTag = CompoundTag(); + auto data = obj.get(keys[i]).asObject(); + NbtCompoundClassAddHelper(&objTag, data); + tag->put(keys[i], std::move(objTag)); + } else { + LOG_ERROR_WITH_SCRIPT_INFO("Wrong Type of data to set into NBT Compound!"); + } + } + } } -Local NbtCompoundClass::pack(std::unique_ptr tag) { - try { - return (new NbtCompoundClass(std::move(tag)))->getScriptObject(); - } - CATCH("Fail in construct NbtCompound!"); +NbtCompoundClass* NbtCompoundClass::constructor(const Arguments& args) { + try { + auto tag = CompoundTag(); + + if (args.size() >= 1 && args[0].isObject()) { + auto obj = args[0].asObject(); + NbtCompoundClassAddHelper(&tag, obj); + } + + return new NbtCompoundClass(args.thiz(), std::make_unique(tag)); + } + CATCH_C("Fail in Create ListTag!"); } -Local NbtCompoundClass::getType(const Arguments &args) { - return Number::newNumber((int)Tag::Type::Compound); +CompoundTag* NbtCompoundClass::extract(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v)->nbt.get(); + else return nullptr; } -Local NbtCompoundClass::getKeys(const Arguments &args) { - try { - Local arr = Array::newArray(); - auto &list = nbt->mTags; - for (auto &[k, v] : list) { - arr.add(String::newString(k)); +Local NbtCompoundClass::pack(CompoundTag* tag, bool noDelete) { + try { + if (noDelete) // unique_ptr 共享指针 + noDelete + { + std::unique_ptr nbt(tag); + auto* nbtObj = new NbtCompoundClass(std::move(nbt)); + nbtObj->canDelete = false; + return nbtObj->getScriptObject(); + } else return (new NbtCompoundClass(tag->clone()))->getScriptObject(); } + CATCH("Fail in construct NbtCompound!"); +} - return arr; - } - CATCH("Fail in NBT GetKeys!"); +Local NbtCompoundClass::pack(std::unique_ptr tag) { + try { + return (new NbtCompoundClass(std::move(tag)))->getScriptObject(); + } + CATCH("Fail in construct NbtCompound!"); } -Local NbtCompoundClass::getTypeOf(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local NbtCompoundClass::getType(const Arguments& args) { return Number::newNumber((int)Tag::Type::Compound); } - try { - auto &list = nbt->mTags; - auto key = args[0].toStr(); +Local NbtCompoundClass::getKeys(const Arguments& args) { + try { + Local arr = Array::newArray(); + auto& list = nbt->mTags; + for (auto& [k, v] : list) { + arr.add(String::newString(k)); + } - return Number::newNumber(int(list.at(key).getId())); - } catch (const std::out_of_range &e) { - return Local(); - } - CATCH("Fail in NBT GetTypeOf!"); + return arr; + } + CATCH("Fail in NBT GetKeys!"); } -Local NbtCompoundClass::setEnd(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local NbtCompoundClass::getTypeOf(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - auto key = args[0].toStr(); - nbt->putByte(key, (char)0); + try { + auto& list = nbt->mTags; + auto key = args[0].toStr(); - return this->getScriptObject(); - } - CATCH("Fail in NBT SetEnd!"); + return Number::newNumber(int(list.at(key).getId())); + } catch (const std::out_of_range& e) { + return Local(); + } + CATCH("Fail in NBT GetTypeOf!"); } -Local NbtCompoundClass::setByte(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); +Local NbtCompoundClass::setEnd(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - auto key = args[0].toStr(); - auto data = char(args[1].toInt()); - nbt->putByte(key, data); + try { + auto key = args[0].toStr(); + nbt->putByte(key, (char)0); - return this->getScriptObject(); - } - CATCH("Fail in NBT SetByte!"); + return this->getScriptObject(); + } + CATCH("Fail in NBT SetEnd!"); } -Local NbtCompoundClass::setInt(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); +Local NbtCompoundClass::setByte(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - try { - auto key = args[0].toStr(); - auto data = int(args[1].toInt()); - nbt->putInt(key, data); + try { + auto key = args[0].toStr(); + auto data = char(args[1].toInt()); + nbt->putByte(key, data); - return this->getScriptObject(); - } - CATCH("Fail in NBT SetInt!"); + return this->getScriptObject(); + } + CATCH("Fail in NBT SetByte!"); } -Local NbtCompoundClass::setShort(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); +Local NbtCompoundClass::setInt(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - try { - auto key = args[0].toStr(); - auto data = short(args[1].toInt()); - nbt->putShort(key, data); + try { + auto key = args[0].toStr(); + auto data = int(args[1].toInt()); + nbt->putInt(key, data); - return this->getScriptObject(); - } - CATCH("Fail in NBT SetShort!"); + return this->getScriptObject(); + } + CATCH("Fail in NBT SetInt!"); } -Local NbtCompoundClass::setLong(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - - try { - auto key = args[0].toStr(); - auto data = args[1].asNumber().toInt64(); - nbt->putInt64(key, data); - - return this->getScriptObject(); - } - CATCH("Fail in NBT SetLong!"); -} - -Local NbtCompoundClass::setFloat(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - - try { - auto key = args[0].toStr(); - auto data = args[1].asNumber().toFloat(); - nbt->putFloat(key, data); - - return this->getScriptObject(); - } - CATCH("Fail in NBT SetFloat!"); -} - -Local NbtCompoundClass::setDouble(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - - try { - auto &list = nbt; - auto key = args[0].toStr(); - auto data = args[1].asNumber().toDouble(); - - list->at(key) = data; - return this->getScriptObject(); - } - CATCH("Fail in NBT SetDouble!"); -} - -Local NbtCompoundClass::setString(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - - try { - auto key = args[0].toStr(); - auto data = args[1].toStr(); - nbt->putString(key, data); - - return this->getScriptObject(); - } - CATCH("Fail in NBT SetString!"); -} - -Local NbtCompoundClass::setByteArray(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kByteBuffer); - - try { - auto key = args[0].toStr(); - auto data = args[1].asByteBuffer(); - TagMemoryChunk tag = TagMemoryChunk(); - tag.mBuffer = std::unique_ptr(new uchar[data.byteLength()]); - memcpy(tag.mBuffer.get(), data.getRawBytes(), data.byteLength()); - nbt->putByteArray(key, tag); - return this->getScriptObject(); - } - CATCH("Fail in NBT SetString!"); -} - -Local NbtCompoundClass::setTag(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - auto key = args[0].toStr(); - - if (IsInstanceOf(args[1])) { - nbt->put(key, std::move(NbtEndClass::extract(args[1])->copy())); - } else if (IsInstanceOf(args[1])) { - nbt->put(key, std::move(NbtByteClass::extract(args[1])->copy())); - } else if (IsInstanceOf(args[1])) { - nbt->put(key, std::move(NbtShortClass::extract(args[1])->copy())); - } else if (IsInstanceOf(args[1])) { - nbt->put(key, std::move(NbtIntClass::extract(args[1])->copy())); - } else if (IsInstanceOf(args[1])) { - nbt->put(key, std::move(NbtLongClass::extract(args[1])->copy())); - } else if (IsInstanceOf(args[1])) { - nbt->put(key, std::move(NbtFloatClass::extract(args[1])->copy())); - } else if (IsInstanceOf(args[1])) { - nbt->put(key, std::move(NbtDoubleClass::extract(args[1])->copy())); - } else if (IsInstanceOf(args[1])) { - nbt->put(key, std::move(NbtStringClass::extract(args[1])->copy())); - } else if (IsInstanceOf(args[1])) { - nbt->put(key, std::move(NbtByteArrayClass::extract(args[1])->copy())); - } else if (IsInstanceOf(args[1])) { - nbt->put(key, std::move(NbtListClass::extract(args[1])->copy())); - } else if (IsInstanceOf(args[1])) { - nbt->put(key, std::move(NbtCompoundClass::extract(args[1])->copy())); - } else { - LOG_ERROR_WITH_SCRIPT_INFO("Unknown type! Cannot set Tag into Compound"); - return Local(); - } - return this->getScriptObject(); - } - CATCH("Fail in NBT SetTag!"); -} - -Local NbtCompoundClass::removeTag(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - auto &list = nbt->mTags; - auto key = args[0].toStr(); - - list.erase(key); - return this->getScriptObject(); - } catch (const std::out_of_range &e) { - LOG_ERROR_WITH_SCRIPT_INFO("Key no found in NBT Compound!"); - return Local(); - } - CATCH("Fail in NBT RemoveTag!"); -} - -Local NbtCompoundClass::getData(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - auto &list = nbt; - auto key = args[0].toStr(); - - return Tag2Value(list->at(key).toUnique().get()); - } catch (const std::out_of_range &e) { - return Local(); - } - CATCH("Fail in NBT GetData!") -} - -Local NbtCompoundClass::getTag(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - auto key = args[0].toStr(); - - Local res; - switch (nbt->at(key).getId()) { - case Tag::Type::End: - res = NbtEndClass::pack(nbt->at(key).toUnique()->as_ptr(), true); - // share ptr break; case Tag::Type::Byte: res = - NbtByteClass::pack((ByteTag *)nbt->getByteTag(key), - true); // share ptr break; - case Tag::Type::Short: - res = NbtShortClass::pack( - const_cast(nbt->getShortTag(key)->as_ptr()), - true); // share ptr break; case Tag::Type::Int: res = - NbtIntClass::pack((IntTag *)nbt->getIntTag(key), - true); // share ptr - break; - case Tag::Type::Int64: - res = NbtLongClass::pack(nbt->getInt64Tag(key)->as_ptr(), - true); // share ptr - break; - case Tag::Type::Float: - res = NbtFloatClass::pack(nbt->get(key)->as_ptr(), - true); // share ptr - break; - case Tag::Type::Double: - res = NbtDoubleClass::pack(nbt->get(key)->as_ptr(), - true); // share ptr - break; - case Tag::Type::String: - res = NbtStringClass::pack( - const_cast(nbt->getStringTag(key)->as_ptr()), - true); // share ptr - break; - case Tag::Type::ByteArray: - res = NbtByteArrayClass::pack(nbt->get(key)->as_ptr(), - true); // share ptr - break; +Local NbtCompoundClass::setShort(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - case Tag::Type::List: - res = NbtListClass::pack(nbt->getList(key), - true); // share ptr break; - case Tag::Type::Compound: - res = NbtCompoundClass::pack(nbt->getCompound(key), - true); // share ptr - break; - default: - res = Local(); - break; + try { + auto key = args[0].toStr(); + auto data = short(args[1].toInt()); + nbt->putShort(key, data); + + return this->getScriptObject(); } - return res; - } catch (const std::out_of_range &e) { - return Local(); - } - CATCH("Fail in NBT GetTag!"); + CATCH("Fail in NBT SetShort!"); } -Local NbtCompoundClass::toObject(const Arguments &args) { - try { - auto &comp = nbt->mTags; - Local obj = Object::newObject(); +Local NbtCompoundClass::setLong(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + + try { + auto key = args[0].toStr(); + auto data = args[1].asNumber().toInt64(); + nbt->putInt64(key, data); - for (auto &[k, v] : comp) { - obj.set(k, Tag2Value(v.toUnique().get(), true)); + return this->getScriptObject(); } - return obj; - } - CATCH("Fail in NBT ToObject!"); + CATCH("Fail in NBT SetLong!"); } -Local NbtCompoundClass::toSNBT(const Arguments &args) { - try { - int indent = args.size() >= 1 ? args[0].toInt() : -1; - if (indent == -1) - return String::newString(nbt->toSnbt(SnbtFormat::Minimize, 0)); - else - return String::newString( - nbt->toSnbt(SnbtFormat::PartialLineFeed, indent)); - } - CATCH("Fail in toSNBT!"); +Local NbtCompoundClass::setFloat(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + + try { + auto key = args[0].toStr(); + auto data = args[1].asNumber().toFloat(); + nbt->putFloat(key, data); + + return this->getScriptObject(); + } + CATCH("Fail in NBT SetFloat!"); } -Local NbtCompoundClass::toBinaryNBT(const Arguments &args) { - try { - auto res = nbt->toBinaryNbt(); - return ByteBuffer::newByteBuffer(res.data(), res.size()); - } - CATCH("Fail in toBinaryNBT!"); +Local NbtCompoundClass::setDouble(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + + try { + auto& list = nbt; + auto key = args[0].toStr(); + auto data = args[1].asNumber().toDouble(); + + list->at(key) = data; + return this->getScriptObject(); + } + CATCH("Fail in NBT SetDouble!"); } -Local NbtCompoundClass::toString(const Arguments &args) { - if (args.size() >= 1) - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local NbtCompoundClass::setString(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + + try { + auto key = args[0].toStr(); + auto data = args[1].toStr(); + nbt->putString(key, data); - try { - return String::newString( - TagToJson(nbt.get(), args.size() >= 1 ? args[0].toInt() : -1)); - } - CATCH("Fail in NBTtoJson!"); + return this->getScriptObject(); + } + CATCH("Fail in NBT SetString!"); +} + +Local NbtCompoundClass::setByteArray(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kByteBuffer); + + try { + auto key = args[0].toStr(); + auto data = args[1].asByteBuffer(); + TagMemoryChunk tag = TagMemoryChunk(); + tag.mBuffer = std::unique_ptr(new uchar[data.byteLength()]); + memcpy(tag.mBuffer.get(), data.getRawBytes(), data.byteLength()); + nbt->putByteArray(key, tag); + return this->getScriptObject(); + } + CATCH("Fail in NBT SetString!"); +} + +Local NbtCompoundClass::setTag(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + auto key = args[0].toStr(); + + if (IsInstanceOf(args[1])) { + nbt->put(key, std::move(NbtEndClass::extract(args[1])->copy())); + } else if (IsInstanceOf(args[1])) { + nbt->put(key, std::move(NbtByteClass::extract(args[1])->copy())); + } else if (IsInstanceOf(args[1])) { + nbt->put(key, std::move(NbtShortClass::extract(args[1])->copy())); + } else if (IsInstanceOf(args[1])) { + nbt->put(key, std::move(NbtIntClass::extract(args[1])->copy())); + } else if (IsInstanceOf(args[1])) { + nbt->put(key, std::move(NbtLongClass::extract(args[1])->copy())); + } else if (IsInstanceOf(args[1])) { + nbt->put(key, std::move(NbtFloatClass::extract(args[1])->copy())); + } else if (IsInstanceOf(args[1])) { + nbt->put(key, std::move(NbtDoubleClass::extract(args[1])->copy())); + } else if (IsInstanceOf(args[1])) { + nbt->put(key, std::move(NbtStringClass::extract(args[1])->copy())); + } else if (IsInstanceOf(args[1])) { + nbt->put(key, std::move(NbtByteArrayClass::extract(args[1])->copy())); + } else if (IsInstanceOf(args[1])) { + nbt->put(key, std::move(NbtListClass::extract(args[1])->copy())); + } else if (IsInstanceOf(args[1])) { + nbt->put(key, std::move(NbtCompoundClass::extract(args[1])->copy())); + } else { + LOG_ERROR_WITH_SCRIPT_INFO("Unknown type! Cannot set Tag into Compound"); + return Local(); + } + return this->getScriptObject(); + } + CATCH("Fail in NBT SetTag!"); } -Local NbtCompoundClass::destroy(const Arguments &args) { - return Boolean::newBoolean(true); +Local NbtCompoundClass::removeTag(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + auto& list = nbt->mTags; + auto key = args[0].toStr(); + + list.erase(key); + return this->getScriptObject(); + } catch (const std::out_of_range& e) { + LOG_ERROR_WITH_SCRIPT_INFO("Key no found in NBT Compound!"); + return Local(); + } + CATCH("Fail in NBT RemoveTag!"); } -//////////////////// APIs //////////////////// +Local NbtCompoundClass::getData(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); -Local NbtStatic::newTag(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - - try { - auto type = enum_cast(args[0].toInt()).value(); - - Local res; - switch (type) { - case Tag::Type::End: { - auto tag = EndTag(); - // if (args.size() >= 2 && args[1].isNumber()) { - // tag->set(); - // } - res = NbtEndClass::pack(std::move(&tag)); - break; - } - case Tag::Type::Byte: { - ByteTag tag(0); - if (args.size() >= 2 && args[1].isNumber()) { - tag = ByteTag(args[1].toInt()); - } - res = NbtByteClass::pack(std::move(&tag)); - break; - } - case Tag::Type::Short: { - ShortTag tag(0); - if (args.size() >= 2 && args[1].isNumber()) { - tag.data = args[1].toInt(); - } - res = NbtShortClass::pack(std::move(&tag)); - break; - } - case Tag::Type::Int: { - IntTag tag(0); - if (args.size() >= 2 && args[1].isNumber()) { - tag.data = args[1].toInt(); - } - res = NbtIntClass::pack(std::move(&tag)); - break; - } - case Tag::Type::Int64: { - Int64Tag tag(0); - if (args.size() >= 2 && args[1].isNumber()) { - tag.data = args[1].asNumber().toInt64(); - } - res = NbtLongClass::pack(std::move(&tag)); - break; - } - case Tag::Type::Float: { - FloatTag tag; - if (args.size() >= 2 && args[1].isNumber()) { - tag.data = args[1].asNumber().toFloat(); - } - res = NbtFloatClass::pack(std::move(&tag)); - break; - } - case Tag::Type::Double: { - DoubleTag tag; - if (args.size() >= 2 && args[1].isNumber()) { - tag.data = args[1].asNumber().toDouble(); - } - res = NbtDoubleClass::pack(std::move(&tag)); - break; - } - case Tag::Type::String: { - StringTag tag; - if (args.size() >= 2 && args[1].isString()) { - tag.data = args[1].toStr(); - } - res = NbtStringClass::pack(std::move(&tag)); - break; + try { + auto& list = nbt; + auto key = args[0].toStr(); + + return Tag2Value(list->at(key).toUnique().get()); + } catch (const std::out_of_range& e) { + return Local(); } - case Tag::Type::ByteArray: { - ByteArrayTag tag; - if (args.size() >= 2 && args[1].isByteBuffer()) { - Local buf = args[1].asByteBuffer(); - TagMemoryChunk chunk = TagMemoryChunk(); - chunk.mBuffer = std::unique_ptr(new uchar[buf.byteLength()]); - memcpy(chunk.mBuffer.get(), buf.getRawBytes(), buf.byteLength()); - tag.data = tag; - tag.data.mSize = tag.data.mCapacity; - } - res = NbtByteArrayClass::pack(std::move(&tag)); - break; + CATCH("Fail in NBT GetData!") +} + +Local NbtCompoundClass::getTag(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + auto key = args[0].toStr(); + + Local res; + switch (nbt->at(key).getId()) { + case Tag::Type::End: + res = NbtEndClass::pack(nbt->at(key).toUnique()->as_ptr(), true); + // share ptr break; case Tag::Type::Byte: res = + NbtByteClass::pack((ByteTag*)nbt->getByteTag(key), + true); // share ptr break; + case Tag::Type::Short: + res = NbtShortClass::pack( + const_cast(nbt->getShortTag(key)->as_ptr()), + true + ); // share ptr break; case Tag::Type::Int: res = + NbtIntClass::pack((IntTag*)nbt->getIntTag(key), + true); // share ptr + break; + case Tag::Type::Int64: + res = NbtLongClass::pack(nbt->getInt64Tag(key)->as_ptr(), + true); // share ptr + break; + case Tag::Type::Float: + res = NbtFloatClass::pack(nbt->get(key)->as_ptr(), + true); // share ptr + break; + case Tag::Type::Double: + res = NbtDoubleClass::pack(nbt->get(key)->as_ptr(), + true); // share ptr + break; + case Tag::Type::String: + res = NbtStringClass::pack( + const_cast(nbt->getStringTag(key)->as_ptr()), + true + ); // share ptr + break; + case Tag::Type::ByteArray: + res = NbtByteArrayClass::pack(nbt->get(key)->as_ptr(), + true); // share ptr + break; + + case Tag::Type::List: + res = NbtListClass::pack(nbt->getList(key), + true); // share ptr break; + case Tag::Type::Compound: + res = NbtCompoundClass::pack(nbt->getCompound(key), + true); // share ptr + break; + default: + res = Local(); + break; + } + return res; + } catch (const std::out_of_range& e) { + return Local(); } - case Tag::Type::List: { - ListTag tag; - if (args.size() >= 2 && args[1].isArray()) { - Local arr = args[1].asArray(); - NbtListClassAddHelper(&tag, arr); - } - res = NbtListClass::pack(std::move(&tag)); - break; + CATCH("Fail in NBT GetTag!"); +} + +Local NbtCompoundClass::toObject(const Arguments& args) { + try { + auto& comp = nbt->mTags; + Local obj = Object::newObject(); + + for (auto& [k, v] : comp) { + obj.set(k, Tag2Value(v.toUnique().get(), true)); + } + return obj; } - case Tag::Type::Compound: { - CompoundTag tag; - if (args.size() >= 2 && args[1].isObject()) { - Local obj = args[1].asObject(); - NbtCompoundClassAddHelper(&tag, obj); - } - res = NbtCompoundClass::pack(std::move(&tag)); - break; + CATCH("Fail in NBT ToObject!"); +} + +Local NbtCompoundClass::toSNBT(const Arguments& args) { + try { + int indent = args.size() >= 1 ? args[0].toInt() : -1; + if (indent == -1) return String::newString(nbt->toSnbt(SnbtFormat::Minimize, 0)); + else return String::newString(nbt->toSnbt(SnbtFormat::PartialLineFeed, indent)); } - default: - res = Local(); - break; + CATCH("Fail in toSNBT!"); +} + +Local NbtCompoundClass::toBinaryNBT(const Arguments& args) { + try { + auto res = nbt->toBinaryNbt(); + return ByteBuffer::newByteBuffer(res.data(), res.size()); } - return res; - } - CATCH("Fail in NBT CreateTag!"); + CATCH("Fail in toBinaryNBT!"); } -Local NbtStatic::parseSNBT(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local NbtCompoundClass::toString(const Arguments& args) { + if (args.size() >= 1) CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - auto tag = CompoundTag::fromSnbt(args[0].toStr()); - if (tag) - return NbtCompoundClass::pack(std::move(tag)); - else - return Local(); - } - CATCH("Fail in parseSNBT!"); + try { + return String::newString(TagToJson(nbt.get(), args.size() >= 1 ? args[0].toInt() : -1)); + } + CATCH("Fail in NBTtoJson!"); } -Local NbtStatic::parseBinaryNBT(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kByteBuffer); +Local NbtCompoundClass::destroy(const Arguments& args) { return Boolean::newBoolean(true); } + +//////////////////// APIs //////////////////// + +Local NbtStatic::newTag(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - auto data = args[0].asByteBuffer(); - auto tag = CompoundTag::fromBinaryNbt(data.describeUtf8()); - if (tag) - return NbtCompoundClass::pack(std::move(tag)); - else - return Local(); - } - CATCH("Fail in parseBinaryNBT!"); + try { + auto type = enum_cast(args[0].toInt()).value(); + + Local res; + switch (type) { + case Tag::Type::End: { + auto tag = EndTag(); + // if (args.size() >= 2 && args[1].isNumber()) { + // tag->set(); + // } + res = NbtEndClass::pack(std::move(&tag)); + break; + } + case Tag::Type::Byte: { + ByteTag tag(0); + if (args.size() >= 2 && args[1].isNumber()) { + tag = ByteTag(args[1].toInt()); + } + res = NbtByteClass::pack(std::move(&tag)); + break; + } + case Tag::Type::Short: { + ShortTag tag(0); + if (args.size() >= 2 && args[1].isNumber()) { + tag.data = args[1].toInt(); + } + res = NbtShortClass::pack(std::move(&tag)); + break; + } + case Tag::Type::Int: { + IntTag tag(0); + if (args.size() >= 2 && args[1].isNumber()) { + tag.data = args[1].toInt(); + } + res = NbtIntClass::pack(std::move(&tag)); + break; + } + case Tag::Type::Int64: { + Int64Tag tag(0); + if (args.size() >= 2 && args[1].isNumber()) { + tag.data = args[1].asNumber().toInt64(); + } + res = NbtLongClass::pack(std::move(&tag)); + break; + } + case Tag::Type::Float: { + FloatTag tag; + if (args.size() >= 2 && args[1].isNumber()) { + tag.data = args[1].asNumber().toFloat(); + } + res = NbtFloatClass::pack(std::move(&tag)); + break; + } + case Tag::Type::Double: { + DoubleTag tag; + if (args.size() >= 2 && args[1].isNumber()) { + tag.data = args[1].asNumber().toDouble(); + } + res = NbtDoubleClass::pack(std::move(&tag)); + break; + } + case Tag::Type::String: { + StringTag tag; + if (args.size() >= 2 && args[1].isString()) { + tag.data = args[1].toStr(); + } + res = NbtStringClass::pack(std::move(&tag)); + break; + } + case Tag::Type::ByteArray: { + ByteArrayTag tag; + if (args.size() >= 2 && args[1].isByteBuffer()) { + Local buf = args[1].asByteBuffer(); + TagMemoryChunk chunk = TagMemoryChunk(); + chunk.mBuffer = std::unique_ptr(new uchar[buf.byteLength()]); + memcpy(chunk.mBuffer.get(), buf.getRawBytes(), buf.byteLength()); + tag.data = tag; + tag.data.mSize = tag.data.mCapacity; + } + res = NbtByteArrayClass::pack(std::move(&tag)); + break; + } + case Tag::Type::List: { + ListTag tag; + if (args.size() >= 2 && args[1].isArray()) { + Local arr = args[1].asArray(); + NbtListClassAddHelper(&tag, arr); + } + res = NbtListClass::pack(std::move(&tag)); + break; + } + case Tag::Type::Compound: { + CompoundTag tag; + if (args.size() >= 2 && args[1].isObject()) { + Local obj = args[1].asObject(); + NbtCompoundClassAddHelper(&tag, obj); + } + res = NbtCompoundClass::pack(std::move(&tag)); + break; + } + default: + res = Local(); + break; + } + return res; + } + CATCH("Fail in NBT CreateTag!"); +} + +Local NbtStatic::parseSNBT(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + auto tag = CompoundTag::fromSnbt(args[0].toStr()); + if (tag) return NbtCompoundClass::pack(std::move(tag)); + else return Local(); + } + CATCH("Fail in parseSNBT!"); +} + +Local NbtStatic::parseBinaryNBT(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kByteBuffer); + + try { + auto data = args[0].asByteBuffer(); + auto tag = CompoundTag::fromBinaryNbt(data.describeUtf8()); + if (tag) return NbtCompoundClass::pack(std::move(tag)); + else return Local(); + } + CATCH("Fail in parseBinaryNBT!"); } //////////////////// Helper //////////////////// bool IsNbtClass(Local value) { - return IsInstanceOf(value) || - IsInstanceOf(value) || - IsInstanceOf(value) || - IsInstanceOf(value) || - IsInstanceOf(value) || - IsInstanceOf(value) || - IsInstanceOf(value) || - IsInstanceOf(value) || - IsInstanceOf(value) || - IsInstanceOf(value) || - IsInstanceOf(value); + return IsInstanceOf(value) || IsInstanceOf(value) || IsInstanceOf(value) + || IsInstanceOf(value) || IsInstanceOf(value) || IsInstanceOf(value) + || IsInstanceOf(value) || IsInstanceOf(value) + || IsInstanceOf(value) || IsInstanceOf(value) + || IsInstanceOf(value); } //////////////////// Tag To Value //////////////////// -Local Tag2Value_CompoundHelper(CompoundTag *nbt, - bool autoExpansion = false); - -Local Tag2Value_ListHelper(ListTag *nbt, bool autoExpansion = false) { - Local res = Array::newArray(); - - auto &list = nbt->as_ptr()->mList; - for (auto &tag : list) { - switch (tag->getId()) { - case Tag::Type::End: - res.add(Local()); - break; - case Tag::Type::Byte: - res.add(Number::newNumber(tag->as_ptr()->data)); - break; - case Tag::Type::Short: - res.add(Number::newNumber(tag->as_ptr()->data)); - break; - case Tag::Type::Int: - res.add(Number::newNumber(tag->as_ptr()->data)); - break; - case Tag::Type::Int64: - res.add(Number::newNumber(tag->as_ptr()->data)); - break; - case Tag::Type::Float: - res.add(Number::newNumber(tag->as_ptr()->data)); - break; - case Tag::Type::Double: - res.add(Number::newNumber(tag->as_ptr()->data)); - break; - case Tag::Type::String: - res.add(String::newString(tag->as_ptr()->data)); - break; - case Tag::Type::ByteArray: { - auto &data = tag->as_ptr()->data; - res.add(ByteBuffer::newByteBuffer(data.mBuffer.get(), data.mSize)); - break; +Local Tag2Value_CompoundHelper(CompoundTag* nbt, bool autoExpansion = false); + +Local Tag2Value_ListHelper(ListTag* nbt, bool autoExpansion = false) { + Local res = Array::newArray(); + + auto& list = nbt->as_ptr()->mList; + for (auto& tag : list) { + switch (tag->getId()) { + case Tag::Type::End: + res.add(Local()); + break; + case Tag::Type::Byte: + res.add(Number::newNumber(tag->as_ptr()->data)); + break; + case Tag::Type::Short: + res.add(Number::newNumber(tag->as_ptr()->data)); + break; + case Tag::Type::Int: + res.add(Number::newNumber(tag->as_ptr()->data)); + break; + case Tag::Type::Int64: + res.add(Number::newNumber(tag->as_ptr()->data)); + break; + case Tag::Type::Float: + res.add(Number::newNumber(tag->as_ptr()->data)); + break; + case Tag::Type::Double: + res.add(Number::newNumber(tag->as_ptr()->data)); + break; + case Tag::Type::String: + res.add(String::newString(tag->as_ptr()->data)); + break; + case Tag::Type::ByteArray: { + auto& data = tag->as_ptr()->data; + res.add(ByteBuffer::newByteBuffer(data.mBuffer.get(), data.mSize)); + break; + } + case Tag::Type::List: + if (!autoExpansion) res.add(NbtListClass::pack(tag->as_ptr())); + else res.add(Tag2Value_ListHelper(tag->as_ptr(), autoExpansion)); + break; + case Tag::Type::Compound: + if (!autoExpansion) res.add(NbtCompoundClass::pack(tag->as_ptr())); + else res.add(Tag2Value_CompoundHelper(tag->as_ptr(), autoExpansion)); + default: + res.add(Local()); + break; + } } - case Tag::Type::List: - if (!autoExpansion) - res.add(NbtListClass::pack(tag->as_ptr())); - else - res.add(Tag2Value_ListHelper(tag->as_ptr(), autoExpansion)); - break; - case Tag::Type::Compound: - if (!autoExpansion) - res.add(NbtCompoundClass::pack(tag->as_ptr())); - else - res.add(Tag2Value_CompoundHelper(tag->as_ptr(), - autoExpansion)); - default: - res.add(Local()); - break; + return res; +} + +Local Tag2Value_CompoundHelper(CompoundTag* nbt, bool autoExpansion) { + Local res = Object::newObject(); + + auto& list = nbt->as_ptr()->mTags; + for (auto& [key, tag] : list) { + switch (tag.getId()) { + case Tag::Type::End: + res.set(key, Local()); + break; + case Tag::Type::Byte: + res.set(key, Number::newNumber(tag.toUnique()->as_ptr()->data)); + break; + case Tag::Type::Short: + res.set(key, Number::newNumber(tag.toUnique()->as_ptr()->data)); + break; + case Tag::Type::Int: + res.set(key, Number::newNumber(tag.toUnique()->as_ptr()->data)); + break; + case Tag::Type::Int64: + res.set(key, Number::newNumber(tag.toUnique()->as_ptr()->data)); + break; + case Tag::Type::Float: + res.set(key, Number::newNumber(tag.toUnique()->as_ptr()->data)); + break; + case Tag::Type::Double: + res.set(key, Number::newNumber(tag.toUnique()->as_ptr()->data)); + break; + case Tag::Type::String: + res.set(key, String::newString(tag.toUnique()->as_ptr()->data)); + break; + case Tag::Type::ByteArray: { + auto& data = tag.toUnique()->as_ptr()->data; + res.set(key, ByteBuffer::newByteBuffer(data.mBuffer.get(), data.mSize)); + break; + } + case Tag::Type::List: + if (!autoExpansion) res.set(key, NbtListClass::pack(tag.toUnique()->as_ptr())); + else res.set(key, Tag2Value_ListHelper(tag.toUnique()->as_ptr(), autoExpansion)); + break; + case Tag::Type::Compound: + if (!autoExpansion) res.set(key, NbtCompoundClass::pack(tag.toUnique()->as_ptr())); + else res.set(key, Tag2Value_CompoundHelper(tag.toUnique()->as_ptr(), autoExpansion)); + default: + res.set(key, Local()); + break; + } } - } - return res; + return res; } -Local Tag2Value_CompoundHelper(CompoundTag *nbt, bool autoExpansion) { - Local res = Object::newObject(); +Local Tag2Value(Tag* nbt, bool autoExpansion) { + Local value; - auto &list = nbt->as_ptr()->mTags; - for (auto &[key, tag] : list) { - switch (tag.getId()) { + switch (nbt->getId()) { case Tag::Type::End: - res.set(key, Local()); - break; + value = Number::newNumber(0); + break; case Tag::Type::Byte: - res.set(key, Number::newNumber(tag.toUnique()->as_ptr()->data)); - break; + value = Number::newNumber(nbt->as_ptr()->data); + break; case Tag::Type::Short: - res.set(key, Number::newNumber(tag.toUnique()->as_ptr()->data)); - break; + value = Number::newNumber(nbt->as_ptr()->data); + break; case Tag::Type::Int: - res.set(key, Number::newNumber(tag.toUnique()->as_ptr()->data)); - break; + value = Number::newNumber(nbt->as_ptr()->data); + break; case Tag::Type::Int64: - res.set(key, Number::newNumber(tag.toUnique()->as_ptr()->data)); - break; + value = Number::newNumber(nbt->as_ptr()->data); + break; case Tag::Type::Float: - res.set(key, Number::newNumber(tag.toUnique()->as_ptr()->data)); - break; + value = Number::newNumber(nbt->as_ptr()->data); + break; case Tag::Type::Double: - res.set(key, - Number::newNumber(tag.toUnique()->as_ptr()->data)); - break; + value = Number::newNumber(nbt->as_ptr()->data); + break; case Tag::Type::String: - res.set(key, - String::newString(tag.toUnique()->as_ptr()->data)); - break; + value = String::newString(nbt->as_ptr()->data); + break; case Tag::Type::ByteArray: { - auto &data = tag.toUnique()->as_ptr()->data; - res.set(key, ByteBuffer::newByteBuffer(data.mBuffer.get(), data.mSize)); - break; + auto& data = nbt->as_ptr()->data; + value = ByteBuffer::newByteBuffer(data.mBuffer.get(), data.mSize); + break; } case Tag::Type::List: - if (!autoExpansion) - res.set(key, NbtListClass::pack(tag.toUnique()->as_ptr())); - else - res.set(key, Tag2Value_ListHelper(tag.toUnique()->as_ptr(), - autoExpansion)); - break; + if (!autoExpansion) value = NbtListClass::pack(nbt->as_ptr()); + else value = Tag2Value_ListHelper(nbt->as_ptr(), autoExpansion); + break; case Tag::Type::Compound: - if (!autoExpansion) - res.set(key, - NbtCompoundClass::pack(tag.toUnique()->as_ptr())); - else - res.set(key, Tag2Value_CompoundHelper( - tag.toUnique()->as_ptr(), autoExpansion)); + if (!autoExpansion) value = NbtCompoundClass::pack(nbt->as_ptr()); + else value = Tag2Value_CompoundHelper(nbt->as_ptr(), autoExpansion); + break; default: - res.set(key, Local()); - break; - } - } - return res; -} - -Local Tag2Value(Tag *nbt, bool autoExpansion) { - Local value; - - switch (nbt->getId()) { - case Tag::Type::End: - value = Number::newNumber(0); - break; - case Tag::Type::Byte: - value = Number::newNumber(nbt->as_ptr()->data); - break; - case Tag::Type::Short: - value = Number::newNumber(nbt->as_ptr()->data); - break; - case Tag::Type::Int: - value = Number::newNumber(nbt->as_ptr()->data); - break; - case Tag::Type::Int64: - value = Number::newNumber(nbt->as_ptr()->data); - break; - case Tag::Type::Float: - value = Number::newNumber(nbt->as_ptr()->data); - break; - case Tag::Type::Double: - value = Number::newNumber(nbt->as_ptr()->data); - break; - case Tag::Type::String: - value = String::newString(nbt->as_ptr()->data); - break; - case Tag::Type::ByteArray: { - auto &data = nbt->as_ptr()->data; - value = ByteBuffer::newByteBuffer(data.mBuffer.get(), data.mSize); - break; - } - case Tag::Type::List: - if (!autoExpansion) - value = NbtListClass::pack(nbt->as_ptr()); - else - value = Tag2Value_ListHelper(nbt->as_ptr(), autoExpansion); - break; - case Tag::Type::Compound: - if (!autoExpansion) - value = NbtCompoundClass::pack(nbt->as_ptr()); - else - value = - Tag2Value_CompoundHelper(nbt->as_ptr(), autoExpansion); - break; - default: - value = Local(); - break; - } - return value; -} \ No newline at end of file + value = Local(); + break; + } + return value; +} diff --git a/src/api/NbtAPI.h b/src/api/NbtAPI.h index d003e3be..83f24bb7 100644 --- a/src/api/NbtAPI.h +++ b/src/api/NbtAPI.h @@ -15,13 +15,14 @@ // NBT Static class NbtStatic : public ScriptClass { public: - static Local newTag(const Arguments &args); - static Local parseSNBT(const Arguments &args); - static Local parseBinaryNBT(const Arguments &args); - - template static Local getType() { - return Number::newNumber((int)T); - } + static Local newTag(const Arguments& args); + static Local parseSNBT(const Arguments& args); + static Local parseBinaryNBT(const Arguments& args); + + template + static Local getType() { + return Number::newNumber((int)T); + } }; extern ClassDefine NbtStaticBuilder; @@ -29,330 +30,308 @@ extern ClassDefine NbtStaticBuilder; class EndTag; class NbtEndClass : public ScriptClass { public: - std::unique_ptr nbt; - bool canDelete = true; - - explicit NbtEndClass(const Local &scriptObj, - std::unique_ptr p); - explicit NbtEndClass(std::unique_ptr p); - ~NbtEndClass() { - if (!canDelete) - nbt.release(); - } - - static NbtEndClass *constructor(const Arguments &args); - static EndTag *extract(Local v); - static Local pack(EndTag *tag, bool noDelete = false); - static Local pack(std::unique_ptr tag); - - Local getType(const Arguments &args); - Local set(const Arguments &args); - Local get(const Arguments &args); - Local toString(const Arguments &args); + std::unique_ptr nbt; + bool canDelete = true; + + explicit NbtEndClass(const Local& scriptObj, std::unique_ptr p); + explicit NbtEndClass(std::unique_ptr p); + ~NbtEndClass() { + if (!canDelete) nbt.release(); + } + + static NbtEndClass* constructor(const Arguments& args); + static EndTag* extract(Local v); + static Local pack(EndTag* tag, bool noDelete = false); + static Local pack(std::unique_ptr tag); + + Local getType(const Arguments& args); + Local set(const Arguments& args); + Local get(const Arguments& args); + Local toString(const Arguments& args); }; extern ClassDefine NbtEndClassBuilder; // NBT Byte class NbtByteClass : public ScriptClass { public: - std::unique_ptr nbt; - bool canDelete = true; - - explicit NbtByteClass(const Local &scriptObj, - std::unique_ptr p); - explicit NbtByteClass(std::unique_ptr p); - ~NbtByteClass() { - if (!canDelete) - nbt.release(); - } - - static NbtByteClass *constructor(const Arguments &args); - static ByteTag *extract(Local v); - static Local pack(ByteTag *tag, bool noDelete = false); - static Local pack(std::unique_ptr tag); - - Local getType(const Arguments &args); - Local set(const Arguments &args); - Local get(const Arguments &args); - Local toString(const Arguments &args); + std::unique_ptr nbt; + bool canDelete = true; + + explicit NbtByteClass(const Local& scriptObj, std::unique_ptr p); + explicit NbtByteClass(std::unique_ptr p); + ~NbtByteClass() { + if (!canDelete) nbt.release(); + } + + static NbtByteClass* constructor(const Arguments& args); + static ByteTag* extract(Local v); + static Local pack(ByteTag* tag, bool noDelete = false); + static Local pack(std::unique_ptr tag); + + Local getType(const Arguments& args); + Local set(const Arguments& args); + Local get(const Arguments& args); + Local toString(const Arguments& args); }; extern ClassDefine NbtByteClassBuilder; // NBT Short class NbtShortClass : public ScriptClass { public: - std::unique_ptr nbt; - bool canDelete = true; - - explicit NbtShortClass(const Local &scriptObj, - std::unique_ptr p); - explicit NbtShortClass(std::unique_ptr p); - ~NbtShortClass() { - if (!canDelete) - nbt.release(); - } - - static NbtShortClass *constructor(const Arguments &args); - static ShortTag *extract(Local v); - static Local pack(ShortTag *tag, bool noDelete = false); - static Local pack(std::unique_ptr tag); - - Local getType(const Arguments &args); - Local set(const Arguments &args); - Local get(const Arguments &args); - Local toString(const Arguments &args); + std::unique_ptr nbt; + bool canDelete = true; + + explicit NbtShortClass(const Local& scriptObj, std::unique_ptr p); + explicit NbtShortClass(std::unique_ptr p); + ~NbtShortClass() { + if (!canDelete) nbt.release(); + } + + static NbtShortClass* constructor(const Arguments& args); + static ShortTag* extract(Local v); + static Local pack(ShortTag* tag, bool noDelete = false); + static Local pack(std::unique_ptr tag); + + Local getType(const Arguments& args); + Local set(const Arguments& args); + Local get(const Arguments& args); + Local toString(const Arguments& args); }; extern ClassDefine NbtShortClassBuilder; // NBT Int class NbtIntClass : public ScriptClass { public: - std::unique_ptr nbt; - bool canDelete = true; - - explicit NbtIntClass(const Local &scriptObj, - std::unique_ptr p); - explicit NbtIntClass(std::unique_ptr p); - ~NbtIntClass() { - if (!canDelete) - nbt.release(); - } - - static NbtIntClass *constructor(const Arguments &args); - static IntTag *extract(Local v); - static Local pack(IntTag *tag, bool noDelete = false); - static Local pack(std::unique_ptr tag); - - Local getType(const Arguments &args); - Local set(const Arguments &args); - Local get(const Arguments &args); - Local toString(const Arguments &args); + std::unique_ptr nbt; + bool canDelete = true; + + explicit NbtIntClass(const Local& scriptObj, std::unique_ptr p); + explicit NbtIntClass(std::unique_ptr p); + ~NbtIntClass() { + if (!canDelete) nbt.release(); + } + + static NbtIntClass* constructor(const Arguments& args); + static IntTag* extract(Local v); + static Local pack(IntTag* tag, bool noDelete = false); + static Local pack(std::unique_ptr tag); + + Local getType(const Arguments& args); + Local set(const Arguments& args); + Local get(const Arguments& args); + Local toString(const Arguments& args); }; extern ClassDefine NbtIntClassBuilder; // NBT Long class NbtLongClass : public ScriptClass { public: - std::unique_ptr nbt; - bool canDelete = true; - - explicit NbtLongClass(const Local &scriptObj, - std::unique_ptr p); - explicit NbtLongClass(std::unique_ptr p); - ~NbtLongClass() { - if (!canDelete) - nbt.release(); - } - - static NbtLongClass *constructor(const Arguments &args); - static Int64Tag *extract(Local v); - static Local pack(Int64Tag *tag, bool noDelete = false); - static Local pack(std::unique_ptr tag); - - Local getType(const Arguments &args); - Local set(const Arguments &args); - Local get(const Arguments &args); - Local toString(const Arguments &args); + std::unique_ptr nbt; + bool canDelete = true; + + explicit NbtLongClass(const Local& scriptObj, std::unique_ptr p); + explicit NbtLongClass(std::unique_ptr p); + ~NbtLongClass() { + if (!canDelete) nbt.release(); + } + + static NbtLongClass* constructor(const Arguments& args); + static Int64Tag* extract(Local v); + static Local pack(Int64Tag* tag, bool noDelete = false); + static Local pack(std::unique_ptr tag); + + Local getType(const Arguments& args); + Local set(const Arguments& args); + Local get(const Arguments& args); + Local toString(const Arguments& args); }; extern ClassDefine NbtLongClassBuilder; // NBT Float class NbtFloatClass : public ScriptClass { public: - std::unique_ptr nbt; - bool canDelete = true; - - explicit NbtFloatClass(const Local &scriptObj, - std::unique_ptr p); - explicit NbtFloatClass(std::unique_ptr p); - ~NbtFloatClass() { - if (!canDelete) - nbt.release(); - } - - static NbtFloatClass *constructor(const Arguments &args); - static FloatTag *extract(Local v); - static Local pack(FloatTag *tag, bool noDelete = false); - static Local pack(std::unique_ptr tag); - - Local getType(const Arguments &args); - Local set(const Arguments &args); - Local get(const Arguments &args); - Local toString(const Arguments &args); + std::unique_ptr nbt; + bool canDelete = true; + + explicit NbtFloatClass(const Local& scriptObj, std::unique_ptr p); + explicit NbtFloatClass(std::unique_ptr p); + ~NbtFloatClass() { + if (!canDelete) nbt.release(); + } + + static NbtFloatClass* constructor(const Arguments& args); + static FloatTag* extract(Local v); + static Local pack(FloatTag* tag, bool noDelete = false); + static Local pack(std::unique_ptr tag); + + Local getType(const Arguments& args); + Local set(const Arguments& args); + Local get(const Arguments& args); + Local toString(const Arguments& args); }; extern ClassDefine NbtFloatClassBuilder; // NBT Double class NbtDoubleClass : public ScriptClass { public: - std::unique_ptr nbt; - bool canDelete = true; - - explicit NbtDoubleClass(const Local &scriptObj, - std::unique_ptr p); - explicit NbtDoubleClass(std::unique_ptr p); - ~NbtDoubleClass() { - if (!canDelete) - nbt.release(); - } - - static NbtDoubleClass *constructor(const Arguments &args); - static DoubleTag *extract(Local v); - static Local pack(DoubleTag *tag, bool noDelete = false); - static Local pack(std::unique_ptr tag); - - Local getType(const Arguments &args); - Local set(const Arguments &args); - Local get(const Arguments &args); - Local toString(const Arguments &args); + std::unique_ptr nbt; + bool canDelete = true; + + explicit NbtDoubleClass(const Local& scriptObj, std::unique_ptr p); + explicit NbtDoubleClass(std::unique_ptr p); + ~NbtDoubleClass() { + if (!canDelete) nbt.release(); + } + + static NbtDoubleClass* constructor(const Arguments& args); + static DoubleTag* extract(Local v); + static Local pack(DoubleTag* tag, bool noDelete = false); + static Local pack(std::unique_ptr tag); + + Local getType(const Arguments& args); + Local set(const Arguments& args); + Local get(const Arguments& args); + Local toString(const Arguments& args); }; extern ClassDefine NbtDoubleClassBuilder; // NBT String class NbtStringClass : public ScriptClass { public: - std::unique_ptr nbt; - bool canDelete = true; - - explicit NbtStringClass(const Local &scriptObj, - std::unique_ptr p); - explicit NbtStringClass(std::unique_ptr p); - ~NbtStringClass() { - if (!canDelete) - nbt.release(); - } - - static NbtStringClass *constructor(const Arguments &args); - static StringTag *extract(Local v); - static Local pack(StringTag *tag, bool noDelete = false); - static Local pack(std::unique_ptr tag); - - Local getType(const Arguments &args); - Local set(const Arguments &args); - Local get(const Arguments &args); - Local toString(const Arguments &args); + std::unique_ptr nbt; + bool canDelete = true; + + explicit NbtStringClass(const Local& scriptObj, std::unique_ptr p); + explicit NbtStringClass(std::unique_ptr p); + ~NbtStringClass() { + if (!canDelete) nbt.release(); + } + + static NbtStringClass* constructor(const Arguments& args); + static StringTag* extract(Local v); + static Local pack(StringTag* tag, bool noDelete = false); + static Local pack(std::unique_ptr tag); + + Local getType(const Arguments& args); + Local set(const Arguments& args); + Local get(const Arguments& args); + Local toString(const Arguments& args); }; extern ClassDefine NbtStringClassBuilder; // NBT ByteArray class NbtByteArrayClass : public ScriptClass { public: - std::unique_ptr nbt; - bool canDelete = true; - - explicit NbtByteArrayClass(const Local &scriptObj, - std::unique_ptr p); - explicit NbtByteArrayClass(std::unique_ptr p); - ~NbtByteArrayClass() { - if (!canDelete) - nbt.release(); - } - - static NbtByteArrayClass *constructor(const Arguments &args); - static ByteArrayTag *extract(Local v); - static Local pack(ByteArrayTag *tag, bool noDelete = false); - static Local pack(std::unique_ptr tag); - - Local getType(const Arguments &args); - Local set(const Arguments &args); - Local get(const Arguments &args); - Local toString(const Arguments &args); + std::unique_ptr nbt; + bool canDelete = true; + + explicit NbtByteArrayClass(const Local& scriptObj, std::unique_ptr p); + explicit NbtByteArrayClass(std::unique_ptr p); + ~NbtByteArrayClass() { + if (!canDelete) nbt.release(); + } + + static NbtByteArrayClass* constructor(const Arguments& args); + static ByteArrayTag* extract(Local v); + static Local pack(ByteArrayTag* tag, bool noDelete = false); + static Local pack(std::unique_ptr tag); + + Local getType(const Arguments& args); + Local set(const Arguments& args); + Local get(const Arguments& args); + Local toString(const Arguments& args); }; extern ClassDefine NbtByteArrayClassBuilder; // NBT List class NbtListClass : public ScriptClass { public: - std::unique_ptr nbt; - bool canDelete = true; - - explicit NbtListClass(const Local &scriptObj, - std::unique_ptr p); - explicit NbtListClass(std::unique_ptr p); - ~NbtListClass() { - if (!canDelete) - nbt.release(); - } - - static NbtListClass *constructor(const Arguments &args); - static ListTag *extract(Local v); - static Local pack(ListTag *tag, bool noDelete = false); - static Local pack(std::unique_ptr tag); - - Local getType(const Arguments &args); - Local getSize(const Arguments &args); - Local getTypeOf(const Arguments &args); - - Local setEnd(const Arguments &args); - Local setByte(const Arguments &args); - Local setInt(const Arguments &args); - Local setShort(const Arguments &args); - Local setLong(const Arguments &args); - Local setFloat(const Arguments &args); - Local setDouble(const Arguments &args); - Local setString(const Arguments &args); - Local setByteArray(const Arguments &args); - Local setTag(const Arguments &args); - Local addTag(const Arguments &args); - Local removeTag(const Arguments &args); - - Local getData(const Arguments &args); - Local getTag(const Arguments &args); - - Local toArray(const Arguments &args); - Local toString(const Arguments &args); + std::unique_ptr nbt; + bool canDelete = true; + + explicit NbtListClass(const Local& scriptObj, std::unique_ptr p); + explicit NbtListClass(std::unique_ptr p); + ~NbtListClass() { + if (!canDelete) nbt.release(); + } + + static NbtListClass* constructor(const Arguments& args); + static ListTag* extract(Local v); + static Local pack(ListTag* tag, bool noDelete = false); + static Local pack(std::unique_ptr tag); + + Local getType(const Arguments& args); + Local getSize(const Arguments& args); + Local getTypeOf(const Arguments& args); + + Local setEnd(const Arguments& args); + Local setByte(const Arguments& args); + Local setInt(const Arguments& args); + Local setShort(const Arguments& args); + Local setLong(const Arguments& args); + Local setFloat(const Arguments& args); + Local setDouble(const Arguments& args); + Local setString(const Arguments& args); + Local setByteArray(const Arguments& args); + Local setTag(const Arguments& args); + Local addTag(const Arguments& args); + Local removeTag(const Arguments& args); + + Local getData(const Arguments& args); + Local getTag(const Arguments& args); + + Local toArray(const Arguments& args); + Local toString(const Arguments& args); }; extern ClassDefine NbtListClassBuilder; // NBT Compound class NbtCompoundClass : public ScriptClass { public: - std::unique_ptr nbt; - bool canDelete = true; - - explicit NbtCompoundClass(const Local &scriptObj, - std::unique_ptr p); - explicit NbtCompoundClass(std::unique_ptr p); - ~NbtCompoundClass() { - if (!canDelete) - nbt.release(); - } - - static NbtCompoundClass *constructor(const Arguments &args); - static CompoundTag *extract(Local v); - static Local pack(CompoundTag *tag, bool noDelete = false); - static Local pack(std::unique_ptr tag); - - Local getType(const Arguments &args); - Local getKeys(const Arguments &args); - Local getTypeOf(const Arguments &args); - - Local setEnd(const Arguments &args); - Local setByte(const Arguments &args); - Local setInt(const Arguments &args); - Local setShort(const Arguments &args); - Local setLong(const Arguments &args); - Local setFloat(const Arguments &args); - Local setDouble(const Arguments &args); - Local setString(const Arguments &args); - Local setByteArray(const Arguments &args); - Local setTag(const Arguments &args); - Local removeTag(const Arguments &args); - - Local getData(const Arguments &args); - Local getTag(const Arguments &args); - - Local toObject(const Arguments &args); - Local toSNBT(const Arguments &args); - Local toBinaryNBT(const Arguments &args); - Local toString(const Arguments &args); - - Local destroy(const Arguments &args); + std::unique_ptr nbt; + bool canDelete = true; + + explicit NbtCompoundClass(const Local& scriptObj, std::unique_ptr p); + explicit NbtCompoundClass(std::unique_ptr p); + ~NbtCompoundClass() { + if (!canDelete) nbt.release(); + } + + static NbtCompoundClass* constructor(const Arguments& args); + static CompoundTag* extract(Local v); + static Local pack(CompoundTag* tag, bool noDelete = false); + static Local pack(std::unique_ptr tag); + + Local getType(const Arguments& args); + Local getKeys(const Arguments& args); + Local getTypeOf(const Arguments& args); + + Local setEnd(const Arguments& args); + Local setByte(const Arguments& args); + Local setInt(const Arguments& args); + Local setShort(const Arguments& args); + Local setLong(const Arguments& args); + Local setFloat(const Arguments& args); + Local setDouble(const Arguments& args); + Local setString(const Arguments& args); + Local setByteArray(const Arguments& args); + Local setTag(const Arguments& args); + Local removeTag(const Arguments& args); + + Local getData(const Arguments& args); + Local getTag(const Arguments& args); + + Local toObject(const Arguments& args); + Local toSNBT(const Arguments& args); + Local toBinaryNBT(const Arguments& args); + Local toString(const Arguments& args); + + Local destroy(const Arguments& args); }; extern ClassDefine NbtCompoundClassBuilder; // Helper -bool IsNbtClass(Local value); -Local Tag2Value(Tag *nbt, bool autoExpansion = false); -void NbtCompoundClassAddHelper(CompoundTag *tag, Local &obj); -void NbtListClassAddHelper(ListTag *tag, Local &arr); \ No newline at end of file +bool IsNbtClass(Local value); +Local Tag2Value(Tag* nbt, bool autoExpansion = false); +void NbtCompoundClassAddHelper(CompoundTag* tag, Local& obj); +void NbtListClassAddHelper(ListTag* tag, Local& arr); \ No newline at end of file diff --git a/src/api/NetworkAPI.cpp b/src/api/NetworkAPI.cpp index ef24ce34..81157f79 100644 --- a/src/api/NetworkAPI.cpp +++ b/src/api/NetworkAPI.cpp @@ -11,15 +11,14 @@ using namespace cyanray; //////////////////// Classes //////////////////// -ClassDefine NetworkClassBuilder = - defineClass("network") - .function("httpGet", &NetworkClass::httpGet) - .function("httpPost", &NetworkClass::httpPost) - .function("httpGetSync", &NetworkClass::httpGetSync) - - // For compatibility - .function("newWebSocket", &NetworkClass::newWebSocket) - .build(); +ClassDefine NetworkClassBuilder = defineClass("network") + .function("httpGet", &NetworkClass::httpGet) + .function("httpPost", &NetworkClass::httpPost) + .function("httpGetSync", &NetworkClass::httpGetSync) + + // For compatibility + .function("newWebSocket", &NetworkClass::newWebSocket) + .build(); ClassDefine WSClientClassBuilder = defineClass("WSClient") @@ -33,21 +32,9 @@ ClassDefine WSClientClassBuilder = .instanceFunction("shutdown", &WSClientClass::shutdown) .instanceFunction("errorCode", &WSClientClass::errorCode) - .property("Open", - [] { - return Number::newNumber( - (int)WebSocketClient::Status::Open); - }) - .property("Closing", - [] { - return Number::newNumber( - (int)WebSocketClient::Status::Closing); - }) - .property("Closed", - [] { - return Number::newNumber( - (int)WebSocketClient::Status::Closed); - }) + .property("Open", [] { return Number::newNumber((int)WebSocketClient::Status::Open); }) + .property("Closing", [] { return Number::newNumber((int)WebSocketClient::Status::Closing); }) + .property("Closed", [] { return Number::newNumber((int)WebSocketClient::Status::Closed); }) .build(); ClassDefine HttpServerClassBuilder = @@ -96,1147 +83,1093 @@ ClassDefine HttpResponseClassBuilder = .instanceFunction("setHeader", &HttpResponseClass::setHeader) .instanceFunction("write", &HttpResponseClass::write) - .instanceProperty("headers", &HttpResponseClass::getHeaders, - &HttpResponseClass::setHeaders) - .instanceProperty("status", &HttpResponseClass::getStatus, - &HttpResponseClass::setStatus) - .instanceProperty("body", &HttpResponseClass::getBody, - &HttpResponseClass::setBody) - .instanceProperty("version", &HttpResponseClass::getVersion, - &HttpResponseClass::setVersion) - .instanceProperty("reason", &HttpResponseClass::getReason, - &HttpResponseClass::setReason) + .instanceProperty("headers", &HttpResponseClass::getHeaders, &HttpResponseClass::setHeaders) + .instanceProperty("status", &HttpResponseClass::getStatus, &HttpResponseClass::setStatus) + .instanceProperty("body", &HttpResponseClass::getBody, &HttpResponseClass::setBody) + .instanceProperty("version", &HttpResponseClass::getVersion, &HttpResponseClass::setVersion) + .instanceProperty("reason", &HttpResponseClass::getReason, &HttpResponseClass::setReason) .build(); // 生成函数 -WSClientClass::WSClientClass(const Local &scriptObj) - : ScriptClass(scriptObj), ws(std::make_shared()) { - initListeners(); +WSClientClass::WSClientClass(const Local& scriptObj) +: ScriptClass(scriptObj), + ws(std::make_shared()) { + initListeners(); } WSClientClass::WSClientClass() - : ScriptClass(ScriptClass::ConstructFromCpp{}), - ws(std::make_shared()) { - initListeners(); +: ScriptClass(ScriptClass::ConstructFromCpp{}), + ws(std::make_shared()) { + initListeners(); } void WSClientClass::initListeners() { - ws->OnTextReceived([nowList{&listeners[int(WSClientEvents::onTextReceived)]}]( - WebSocketClient &client, string msg) { - if (!nowList->empty()) - for (auto &listener : *nowList) { - if (!EngineManager::isValid(listener.engine)) - return; - EngineScope enter(listener.engine); - // dangerous - NewTimeout(listener.func.get(), {String::newString(msg)}, 1); - } - }); - - ws->OnBinaryReceived([nowList{ - &listeners[int(WSClientEvents::onBinaryReceived)]}]( - WebSocketClient &client, vector data) { - if (!nowList->empty()) - for (auto &listener : *nowList) { - if (!EngineManager::isValid(listener.engine)) - return; - EngineScope enter(listener.engine); - NewTimeout(listener.func.get(), - {ByteBuffer::newByteBuffer(data.data(), data.size())}, 1); - } - }); - - ws->OnError([nowList{&listeners[int(WSClientEvents::onError)]}]( - WebSocketClient &client, string msg) { - if (!nowList->empty()) - for (auto &listener : *nowList) { - if (!EngineManager::isValid(listener.engine)) - return; - EngineScope enter(listener.engine); - NewTimeout(listener.func.get(), {String::newString(msg)}, 1); - } - }); - - ws->OnLostConnection( - [nowList{&listeners[int(WSClientEvents::onLostConnection)]}]( - WebSocketClient &client, int code) { + ws->OnTextReceived([nowList{&listeners[int(WSClientEvents::onTextReceived)]}](WebSocketClient& client, string msg) { + if (!nowList->empty()) + for (auto& listener : *nowList) { + if (!EngineManager::isValid(listener.engine)) return; + EngineScope enter(listener.engine); + // dangerous + NewTimeout(listener.func.get(), {String::newString(msg)}, 1); + } + }); + + ws->OnBinaryReceived( + [nowList{&listeners[int(WSClientEvents::onBinaryReceived)]}](WebSocketClient& client, vector data) { + if (!nowList->empty()) + for (auto& listener : *nowList) { + if (!EngineManager::isValid(listener.engine)) return; + EngineScope enter(listener.engine); + NewTimeout(listener.func.get(), {ByteBuffer::newByteBuffer(data.data(), data.size())}, 1); + } + } + ); + + ws->OnError([nowList{&listeners[int(WSClientEvents::onError)]}](WebSocketClient& client, string msg) { if (!nowList->empty()) - for (auto &listener : *nowList) { - if (!EngineManager::isValid(listener.engine)) - return; - EngineScope enter(listener.engine); - NewTimeout(listener.func.get(), {Number::newNumber(code)}, 1); - } - }); + for (auto& listener : *nowList) { + if (!EngineManager::isValid(listener.engine)) return; + EngineScope enter(listener.engine); + NewTimeout(listener.func.get(), {String::newString(msg)}, 1); + } + }); + + ws->OnLostConnection([nowList{ + &listeners[int(WSClientEvents::onLostConnection)]}](WebSocketClient& client, int code) { + if (!nowList->empty()) + for (auto& listener : *nowList) { + if (!EngineManager::isValid(listener.engine)) return; + EngineScope enter(listener.engine); + NewTimeout(listener.func.get(), {Number::newNumber(code)}, 1); + } + }); } void WSClientClass::initListeners_s() { - ws->OnTextReceived([nowList{&listeners[int(WSClientEvents::onTextReceived)]}, - engine = EngineScope::currentEngine()]( - WebSocketClient &client, string msg) { - if ((ll::getServerStatus() != ll::ServerStatus::Running) || - !EngineManager::isValid(engine) || engine->isDestroying()) - return; - std::thread([nowList, engine, msg = std::move(msg)]() { - if ((ll::getServerStatus() != ll::ServerStatus::Running) || - !EngineManager::isValid(engine) || engine->isDestroying()) - return; - EngineScope enter(engine); - if (!nowList->empty()) - for (auto &listener : *nowList) { - listener.func.get().call({}, {String::newString(msg)}); - } - }).detach(); - }); - - ws->OnBinaryReceived( - [nowList{&listeners[int(WSClientEvents::onBinaryReceived)]}, - engine = EngineScope::currentEngine()](WebSocketClient &client, - vector data) { - if ((ll::getServerStatus() != ll::ServerStatus::Running) || - !EngineManager::isValid(engine) || engine->isDestroying()) - return; + ws->OnTextReceived([nowList{&listeners[int(WSClientEvents::onTextReceived)]}, + engine = EngineScope::currentEngine()](WebSocketClient& client, string msg) { + if ((ll::getServerStatus() != ll::ServerStatus::Running) || !EngineManager::isValid(engine) + || engine->isDestroying()) + return; + std::thread([nowList, engine, msg = std::move(msg)]() { + if ((ll::getServerStatus() != ll::ServerStatus::Running) || !EngineManager::isValid(engine) + || engine->isDestroying()) + return; + EngineScope enter(engine); + if (!nowList->empty()) + for (auto& listener : *nowList) { + listener.func.get().call({}, {String::newString(msg)}); + } + }).detach(); + }); + + ws->OnBinaryReceived([nowList{&listeners[int(WSClientEvents::onBinaryReceived)]}, + engine = EngineScope::currentEngine()](WebSocketClient& client, vector data) { + if ((ll::getServerStatus() != ll::ServerStatus::Running) || !EngineManager::isValid(engine) + || engine->isDestroying()) + return; std::thread([nowList, engine, data = std::move(data)]() mutable { - if ((ll::getServerStatus() != ll::ServerStatus::Running) || - !EngineManager::isValid(engine) || engine->isDestroying()) + if ((ll::getServerStatus() != ll::ServerStatus::Running) || !EngineManager::isValid(engine) + || engine->isDestroying()) + return; + EngineScope enter(engine); + if (!nowList->empty()) + for (auto& listener : *nowList) { + listener.func.get().call({}, {ByteBuffer::newByteBuffer(data.data(), data.size())}); + } + }).detach(); + }); + + ws->OnError([nowList{&listeners[int(WSClientEvents::onError)]}, + engine = EngineScope::currentEngine()](WebSocketClient& client, string msg) { + if ((ll::getServerStatus() != ll::ServerStatus::Running) || !EngineManager::isValid(engine) + || engine->isDestroying()) return; - EngineScope enter(engine); - if (!nowList->empty()) - for (auto &listener : *nowList) { - listener.func.get().call( - {}, {ByteBuffer::newByteBuffer(data.data(), data.size())}); - } + std::thread([nowList, engine, msg = std::move(msg)]() { + if ((ll::getServerStatus() != ll::ServerStatus::Running) || !EngineManager::isValid(engine) + || engine->isDestroying()) + return; + EngineScope enter(engine); + if (!nowList->empty()) + for (auto& listener : *nowList) { + listener.func.get().call({}, {String::newString(msg)}); + } }).detach(); - }); - - ws->OnError([nowList{&listeners[int(WSClientEvents::onError)]}, - engine = EngineScope::currentEngine()](WebSocketClient &client, - string msg) { - if ((ll::getServerStatus() != ll::ServerStatus::Running) || - !EngineManager::isValid(engine) || engine->isDestroying()) - return; - std::thread([nowList, engine, msg = std::move(msg)]() { - if ((ll::getServerStatus() != ll::ServerStatus::Running) || - !EngineManager::isValid(engine) || engine->isDestroying()) - return; - EngineScope enter(engine); - if (!nowList->empty()) - for (auto &listener : *nowList) { - listener.func.get().call({}, {String::newString(msg)}); - } - }).detach(); - }); - - ws->OnLostConnection( - [nowList{&listeners[int(WSClientEvents::onLostConnection)]}, - engine = EngineScope::currentEngine()](WebSocketClient &client, - int code) { - if ((ll::getServerStatus() != ll::ServerStatus::Running) || - !EngineManager::isValid(engine) || engine->isDestroying()) - return; - std::thread([nowList, engine, code]() { - if ((ll::getServerStatus() != ll::ServerStatus::Running) || - !EngineManager::isValid(engine) || engine->isDestroying()) + }); + + ws->OnLostConnection([nowList{&listeners[int(WSClientEvents::onLostConnection)]}, + engine = EngineScope::currentEngine()](WebSocketClient& client, int code) { + if ((ll::getServerStatus() != ll::ServerStatus::Running) || !EngineManager::isValid(engine) + || engine->isDestroying()) return; - EngineScope enter(engine); - if (!nowList->empty()) - for (auto &listener : *nowList) { - listener.func.get().call({}, {Number::newNumber(code)}); - } + std::thread([nowList, engine, code]() { + if ((ll::getServerStatus() != ll::ServerStatus::Running) || !EngineManager::isValid(engine) + || engine->isDestroying()) + return; + EngineScope enter(engine); + if (!nowList->empty()) + for (auto& listener : *nowList) { + listener.func.get().call({}, {Number::newNumber(code)}); + } }).detach(); - }); + }); } void WSClientClass::clearListeners() { - ws->OnTextReceived([](WebSocketClient &, std::string) {}); - ws->OnBinaryReceived([](WebSocketClient &, std::vector) {}); - ws->OnError([](WebSocketClient &, std::string) {}); - ws->OnLostConnection([](WebSocketClient &, int) {}); + ws->OnTextReceived([](WebSocketClient&, std::string) {}); + ws->OnBinaryReceived([](WebSocketClient&, std::vector) {}); + ws->OnError([](WebSocketClient&, std::string) {}); + ws->OnLostConnection([](WebSocketClient&, int) {}); } -WSClientClass *WSClientClass::constructor(const Arguments &args) { - return new WSClientClass(args.thiz()); -} +WSClientClass* WSClientClass::constructor(const Arguments& args) { return new WSClientClass(args.thiz()); } // 成员函数 -void WSClientClass::addListener(const string &event, Local func) { - if (event == "onTextReceived") - listeners[(int)WSClientEvents::onTextReceived].push_back( - {EngineScope::currentEngine(), script::Global(func)}); - else if (event == "onBinaryReceived") - listeners[(int)WSClientEvents::onBinaryReceived].push_back( - {EngineScope::currentEngine(), script::Global(func)}); - else if (event == "onError") - listeners[(int)WSClientEvents::onError].push_back( - {EngineScope::currentEngine(), script::Global(func)}); - else if (event == "onLostConnection") - listeners[(int)WSClientEvents::onLostConnection].push_back( - {EngineScope::currentEngine(), script::Global(func)}); - else { - LOG_ERROR_WITH_SCRIPT_INFO("WSClient Event \"" + event + "\" No Found!\n"); - } +void WSClientClass::addListener(const string& event, Local func) { + if (event == "onTextReceived") + listeners[(int)WSClientEvents::onTextReceived].push_back( + {EngineScope::currentEngine(), script::Global(func)} + ); + else if (event == "onBinaryReceived") + listeners[(int)WSClientEvents::onBinaryReceived].push_back( + {EngineScope::currentEngine(), script::Global(func)} + ); + else if (event == "onError") + listeners[(int)WSClientEvents::onError].push_back({EngineScope::currentEngine(), script::Global(func)} + ); + else if (event == "onLostConnection") + listeners[(int)WSClientEvents::onLostConnection].push_back( + {EngineScope::currentEngine(), script::Global(func)} + ); + else { + LOG_ERROR_WITH_SCRIPT_INFO("WSClient Event \"" + event + "\" No Found!\n"); + } } Local WSClientClass::getStatus() { - try { - return Number::newNumber((int)ws->GetStatus()); - } catch (const std::runtime_error &e) { - return Local(); - } - CATCH("Fail in getStatus!"); + try { + return Number::newNumber((int)ws->GetStatus()); + } catch (const std::runtime_error& e) { + return Local(); + } + CATCH("Fail in getStatus!"); } -Local WSClientClass::connect(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - // if (args.size() > 1 && args[1].isFunction()) - // return connectAsync(args); - try { - - string target = args[0].toStr(); - RecordOperation(ENGINE_OWN_DATA()->pluginName, "ConnectToWebsocketServer", - target); - ws->Connect(target); - return Boolean::newBoolean(true); - } catch (const std::runtime_error &e) { - return Boolean::newBoolean(false); - } - CATCH("Fail in connect!"); +Local WSClientClass::connect(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + // if (args.size() > 1 && args[1].isFunction()) + // return connectAsync(args); + try { + + string target = args[0].toStr(); + RecordOperation(ENGINE_OWN_DATA()->pluginName, "ConnectToWebsocketServer", target); + ws->Connect(target); + return Boolean::newBoolean(true); + } catch (const std::runtime_error& e) { + return Boolean::newBoolean(false); + } + CATCH("Fail in connect!"); } // 异步连接ws客户端 -Local WSClientClass::connectAsync(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kFunction); - - try { - string target = args[0].toStr(); - RecordOperation(ENGINE_OWN_DATA()->pluginName, "ConnectToWebsocketServer", - target); - - script::Global callbackFunc{args[1].asFunction()}; - std::thread([ws{this->ws}, target, callback{std::move(callbackFunc)}, - engine{EngineScope::currentEngine()}, - pluginName{ENGINE_OWN_DATA()->pluginName}]() mutable { - try { - bool result = false; - try { - ws->Connect(target); - result = true; - } catch (const std::runtime_error &e) { - result = false; - } - if ((ll::getServerStatus() != ll::ServerStatus::Running) || - !EngineManager::isValid(engine) || engine->isDestroying()) - return; - EngineScope enter(engine); - // fix get on empty Global - if (callback.isEmpty()) - return; - NewTimeout(callback.get(), {Boolean::newBoolean(result)}, 0); - } catch (...) { - logger.error("WSClientClass::connectAsync Failed!"); - logger.error("Uncaught Exception Detected!"); - logger.error("In Plugin: " + pluginName); - } - }).detach(); - return Boolean::newBoolean(true); - } catch (const std::runtime_error &e) { - return Boolean::newBoolean(false); - } - CATCH("Fail in connectAsync!"); +Local WSClientClass::connectAsync(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kFunction); + + try { + string target = args[0].toStr(); + RecordOperation(ENGINE_OWN_DATA()->pluginName, "ConnectToWebsocketServer", target); + + script::Global callbackFunc{args[1].asFunction()}; + std::thread([ws{this->ws}, + target, + callback{std::move(callbackFunc)}, + engine{EngineScope::currentEngine()}, + pluginName{ENGINE_OWN_DATA()->pluginName}]() mutable { + try { + bool result = false; + try { + ws->Connect(target); + result = true; + } catch (const std::runtime_error& e) { + result = false; + } + if ((ll::getServerStatus() != ll::ServerStatus::Running) || !EngineManager::isValid(engine) + || engine->isDestroying()) + return; + EngineScope enter(engine); + // fix get on empty Global + if (callback.isEmpty()) return; + NewTimeout(callback.get(), {Boolean::newBoolean(result)}, 0); + } catch (...) { + logger.error("WSClientClass::connectAsync Failed!"); + logger.error("Uncaught Exception Detected!"); + logger.error("In Plugin: " + pluginName); + } + }).detach(); + return Boolean::newBoolean(true); + } catch (const std::runtime_error& e) { + return Boolean::newBoolean(false); + } + CATCH("Fail in connectAsync!"); } -Local WSClientClass::send(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); +Local WSClientClass::send(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); - try { - if (args[0].isString()) - ws->SendText(args[0].toStr()); - else if (args[0].isByteBuffer()) - ws->SendBinary((char *)args[0].asByteBuffer().getRawBytes(), - args[0].asByteBuffer().byteLength()); - else { - LOG_WRONG_ARG_TYPE(); - return Local(); + try { + if (args[0].isString()) ws->SendText(args[0].toStr()); + else if (args[0].isByteBuffer()) + ws->SendBinary((char*)args[0].asByteBuffer().getRawBytes(), args[0].asByteBuffer().byteLength()); + else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + return Boolean::newBoolean(true); + } catch (const std::runtime_error& e) { + return Boolean::newBoolean(false); } - return Boolean::newBoolean(true); - } catch (const std::runtime_error &e) { - return Boolean::newBoolean(false); - } - CATCH("Fail in send!"); + CATCH("Fail in send!"); } -Local WSClientClass::listen(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kFunction); - - try { - addListener(args[0].toStr(), args[1].asFunction()); - return Boolean::newBoolean(true); - } catch (const std::runtime_error &e) { - return Boolean::newBoolean(false); - } - CATCH("Fail in listen!"); +Local WSClientClass::listen(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kFunction); + + try { + addListener(args[0].toStr(), args[1].asFunction()); + return Boolean::newBoolean(true); + } catch (const std::runtime_error& e) { + return Boolean::newBoolean(false); + } + CATCH("Fail in listen!"); } -Local WSClientClass::close(const Arguments &args) { - try { - ws->Close(); - return Boolean::newBoolean(true); - } catch (const std::runtime_error &e) { - return Boolean::newBoolean(false); - } - CATCH("Fail in close!"); +Local WSClientClass::close(const Arguments& args) { + try { + ws->Close(); + return Boolean::newBoolean(true); + } catch (const std::runtime_error& e) { + return Boolean::newBoolean(false); + } + CATCH("Fail in close!"); } -Local WSClientClass::shutdown(const Arguments &args) { - try { - ws->Shutdown(); - return Boolean::newBoolean(true); - } catch (const std::runtime_error &e) { - return Boolean::newBoolean(false); - } - CATCH("Fail in shutdown!"); +Local WSClientClass::shutdown(const Arguments& args) { + try { + ws->Shutdown(); + return Boolean::newBoolean(true); + } catch (const std::runtime_error& e) { + return Boolean::newBoolean(false); + } + CATCH("Fail in shutdown!"); } -Local WSClientClass::errorCode(const Arguments &args) { - try { - return Number::newNumber(WSAGetLastError()); - } catch (const std::runtime_error &e) { - return Local(); - } - CATCH("Fail in errorCode!"); +Local WSClientClass::errorCode(const Arguments& args) { + try { + return Number::newNumber(WSAGetLastError()); + } catch (const std::runtime_error& e) { + return Local(); + } + CATCH("Fail in errorCode!"); } //////////////////// Class HttpServer //////////////////// using namespace httplib; -#define ADD_CALLBACK(method, path, func) \ - callbacks.emplace( \ - make_pair(path, HttpServerCallback{EngineScope::currentEngine(), \ - script::Global{func}, \ - HttpRequestType::method, path})); \ - svr->##method##(path.c_str(), [this, engine = EngineScope::currentEngine()]( \ - const Request &req, Response &resp) { \ - if ((ll::getServerStatus() != ll::ServerStatus::Running) || \ - !EngineManager::isValid(engine) || engine->isDestroying()) \ - return; \ - std::thread([this, engine, req, &resp] { \ - if ((ll::getServerStatus() != ll::ServerStatus::Running) || \ - !EngineManager::isValid(engine) || engine->isDestroying()) \ - return; \ - EngineScope enter(engine); \ - for (auto &[k, v] : this->callbacks) { \ - if (v.type != HttpRequestType::method) \ - return; \ - std::regex rgx(k); \ - std::smatch matches; \ - if (std::regex_match(req.path, matches, rgx)) { \ - if (matches == req.matches) { \ - auto reqObj = new HttpRequestClass(req); \ - auto respObj = new HttpResponseClass(resp); \ - v.func.get().call({}, reqObj, respObj); \ - resp = *respObj->get(); \ - break; \ - } \ - } \ - } \ - }).join(); \ - }); - -HttpServerClass::HttpServerClass(const Local &scriptObj) - : ScriptClass(scriptObj), svr(new Server) {} -HttpServerClass::HttpServerClass() - : ScriptClass(ScriptClass::ConstructFromCpp{}), - svr(new Server) {} +#define ADD_CALLBACK(method, path, func) \ + callbacks.emplace(make_pair( \ + path, \ + HttpServerCallback{ \ + EngineScope::currentEngine(), \ + script::Global{func}, \ + HttpRequestType::method, \ + path} \ + )); \ + svr->##method##(path.c_str(), [this, engine = EngineScope::currentEngine()](const Request& req, Response& resp) { \ + if ((ll::getServerStatus() != ll::ServerStatus::Running) || !EngineManager::isValid(engine) \ + || engine->isDestroying()) \ + return; \ + std::thread([this, engine, req, &resp] { \ + if ((ll::getServerStatus() != ll::ServerStatus::Running) || !EngineManager::isValid(engine) \ + || engine->isDestroying()) \ + return; \ + EngineScope enter(engine); \ + for (auto& [k, v] : this->callbacks) { \ + if (v.type != HttpRequestType::method) return; \ + std::regex rgx(k); \ + std::smatch matches; \ + if (std::regex_match(req.path, matches, rgx)) { \ + if (matches == req.matches) { \ + auto reqObj = new HttpRequestClass(req); \ + auto respObj = new HttpResponseClass(resp); \ + v.func.get().call({}, reqObj, respObj); \ + resp = *respObj->get(); \ + break; \ + } \ + } \ + } \ + }).join(); \ + }); + +HttpServerClass::HttpServerClass(const Local& scriptObj) : ScriptClass(scriptObj), svr(new Server) {} +HttpServerClass::HttpServerClass() : ScriptClass(ScriptClass::ConstructFromCpp{}), svr(new Server) {} HttpServerClass::~HttpServerClass() { svr->stop(); } -HttpServerClass *HttpServerClass::constructor(const Arguments &args) { - return new HttpServerClass(args.thiz()); -} +HttpServerClass* HttpServerClass::constructor(const Arguments& args) { return new HttpServerClass(args.thiz()); } + +Local HttpServerClass::onGet(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kFunction); -Local HttpServerClass::onGet(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kFunction); - - try { - auto path = args[0].toStr(); - auto func = args[1].asFunction(); - ADD_CALLBACK(Get, path, func); - return this->getScriptObject(); - } - CATCH("Fail in onGet") + try { + auto path = args[0].toStr(); + auto func = args[1].asFunction(); + ADD_CALLBACK(Get, path, func); + return this->getScriptObject(); + } + CATCH("Fail in onGet") } -Local HttpServerClass::onPut(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kFunction); - - try { - auto path = args[0].toStr(); - auto func = args[1].asFunction(); - ADD_CALLBACK(Put, path, func); - return this->getScriptObject(); - } - CATCH("Fail in onPut!"); +Local HttpServerClass::onPut(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kFunction); + + try { + auto path = args[0].toStr(); + auto func = args[1].asFunction(); + ADD_CALLBACK(Put, path, func); + return this->getScriptObject(); + } + CATCH("Fail in onPut!"); } -Local HttpServerClass::onPost(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kFunction); - - try { - auto path = args[0].toStr(); - auto func = args[1].asFunction(); - ADD_CALLBACK(Post, path, func); - return this->getScriptObject(); - } - CATCH("Fail in onPost!"); +Local HttpServerClass::onPost(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kFunction); + + try { + auto path = args[0].toStr(); + auto func = args[1].asFunction(); + ADD_CALLBACK(Post, path, func); + return this->getScriptObject(); + } + CATCH("Fail in onPost!"); } -Local HttpServerClass::onPatch(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kFunction); - - try { - auto path = args[0].toStr(); - auto func = args[1].asFunction(); - ADD_CALLBACK(Patch, path, func); - return this->getScriptObject(); - } - CATCH("Fail in onPatch!"); +Local HttpServerClass::onPatch(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kFunction); + + try { + auto path = args[0].toStr(); + auto func = args[1].asFunction(); + ADD_CALLBACK(Patch, path, func); + return this->getScriptObject(); + } + CATCH("Fail in onPatch!"); } -Local HttpServerClass::onDelete(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kFunction); - - try { - auto path = args[0].toStr(); - auto func = args[1].asFunction(); - ADD_CALLBACK(Delete, path, func); - return this->getScriptObject(); - } - CATCH("Fail in onDelete!"); +Local HttpServerClass::onDelete(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kFunction); + + try { + auto path = args[0].toStr(); + auto func = args[1].asFunction(); + ADD_CALLBACK(Delete, path, func); + return this->getScriptObject(); + } + CATCH("Fail in onDelete!"); } -Local HttpServerClass::onOptions(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kFunction); - - try { - auto path = args[0].toStr(); - auto func = args[1].asFunction(); - ADD_CALLBACK(Options, path, func); - return this->getScriptObject(); - } - CATCH("Fail in onOptions!"); +Local HttpServerClass::onOptions(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kFunction); + + try { + auto path = args[0].toStr(); + auto func = args[1].asFunction(); + ADD_CALLBACK(Options, path, func); + return this->getScriptObject(); + } + CATCH("Fail in onOptions!"); } -Local HttpServerClass::onPreRouting(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kFunction); - - try { - preRoutingCallback = {EngineScope::currentEngine(), - script::Global{args[0].asFunction()}}; - svr->set_pre_routing_handler([this, engine = EngineScope::currentEngine()]( - const Request &req, Response &resp) { - if ((ll::getServerStatus() != ll::ServerStatus::Running) || - !EngineManager::isValid(engine) || engine->isDestroying()) - return Server::HandlerResponse::Unhandled; - bool handled = false; - std::thread([this, engine, req, &resp, &handled] { - if ((ll::getServerStatus() != ll::ServerStatus::Running) || - !EngineManager::isValid(engine) || engine->isDestroying()) - return; - EngineScope enter(engine); - auto reqObj = new HttpRequestClass(req); - auto respObj = new HttpResponseClass(resp); - auto res = - this->preRoutingCallback.func.get().call({}, reqObj, respObj); - if (res.isBoolean() && res.asBoolean().value() == false) { - handled = true; - } - resp = *respObj->get(); - }).join(); - return handled ? Server::HandlerResponse::Handled - : Server::HandlerResponse::Unhandled; - }); - return this->getScriptObject(); - } - CATCH("Fail in onPreRouting!"); +Local HttpServerClass::onPreRouting(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kFunction); + + try { + preRoutingCallback = {EngineScope::currentEngine(), script::Global{args[0].asFunction()}}; + svr->set_pre_routing_handler([this, engine = EngineScope::currentEngine()](const Request& req, Response& resp) { + if ((ll::getServerStatus() != ll::ServerStatus::Running) || !EngineManager::isValid(engine) + || engine->isDestroying()) + return Server::HandlerResponse::Unhandled; + bool handled = false; + std::thread([this, engine, req, &resp, &handled] { + if ((ll::getServerStatus() != ll::ServerStatus::Running) || !EngineManager::isValid(engine) + || engine->isDestroying()) + return; + EngineScope enter(engine); + auto reqObj = new HttpRequestClass(req); + auto respObj = new HttpResponseClass(resp); + auto res = this->preRoutingCallback.func.get().call({}, reqObj, respObj); + if (res.isBoolean() && res.asBoolean().value() == false) { + handled = true; + } + resp = *respObj->get(); + }).join(); + return handled ? Server::HandlerResponse::Handled : Server::HandlerResponse::Unhandled; + }); + return this->getScriptObject(); + } + CATCH("Fail in onPreRouting!"); } -Local HttpServerClass::onPostRouting(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kFunction); - - try { - postRoutingCallback = {EngineScope::currentEngine(), - script::Global{args[0].asFunction()}}; - svr->set_post_routing_handler([this, engine = EngineScope::currentEngine()]( - const Request &req, Response &resp) { - if ((ll::getServerStatus() != ll::ServerStatus::Running) || - !EngineManager::isValid(engine) || engine->isDestroying()) - return; - std::thread([this, engine, req, &resp] { - if ((ll::getServerStatus() != ll::ServerStatus::Running) || - !EngineManager::isValid(engine) || engine->isDestroying()) - return; - EngineScope enter(engine); - auto reqObj = new HttpRequestClass(req); - auto respObj = new HttpResponseClass(resp); - this->postRoutingCallback.func.get().call({}, reqObj, respObj); - resp = *respObj->get(); - }).join(); - }); - return this->getScriptObject(); - } - CATCH("Fail in onPostRouting!"); +Local HttpServerClass::onPostRouting(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kFunction); + + try { + postRoutingCallback = {EngineScope::currentEngine(), script::Global{args[0].asFunction()}}; + svr->set_post_routing_handler([this, + engine = EngineScope::currentEngine()](const Request& req, Response& resp) { + if ((ll::getServerStatus() != ll::ServerStatus::Running) || !EngineManager::isValid(engine) + || engine->isDestroying()) + return; + std::thread([this, engine, req, &resp] { + if ((ll::getServerStatus() != ll::ServerStatus::Running) || !EngineManager::isValid(engine) + || engine->isDestroying()) + return; + EngineScope enter(engine); + auto reqObj = new HttpRequestClass(req); + auto respObj = new HttpResponseClass(resp); + this->postRoutingCallback.func.get().call({}, reqObj, respObj); + resp = *respObj->get(); + }).join(); + }); + return this->getScriptObject(); + } + CATCH("Fail in onPostRouting!"); } -Local HttpServerClass::onError(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kFunction); - - try { - errorCallback = {EngineScope::currentEngine(), - script::Global{args[0].asFunction()}}; - svr->set_error_handler([this, engine = EngineScope::currentEngine()]( - const Request &req, Response &resp) { - if ((ll::getServerStatus() != ll::ServerStatus::Running) || - !EngineManager::isValid(engine) || engine->isDestroying()) - return; - std::thread([this, engine, req, &resp] { - if ((ll::getServerStatus() != ll::ServerStatus::Running) || - !EngineManager::isValid(engine) || engine->isDestroying()) - return; - EngineScope enter(engine); - auto reqObj = new HttpRequestClass(req); - auto respObj = new HttpResponseClass(resp); - this->errorCallback.func.get().call({}, reqObj, respObj); - resp = *respObj->get(); - }).join(); - }); - return this->getScriptObject(); - } - CATCH("Fail in onError!"); +Local HttpServerClass::onError(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kFunction); + + try { + errorCallback = {EngineScope::currentEngine(), script::Global{args[0].asFunction()}}; + svr->set_error_handler([this, engine = EngineScope::currentEngine()](const Request& req, Response& resp) { + if ((ll::getServerStatus() != ll::ServerStatus::Running) || !EngineManager::isValid(engine) + || engine->isDestroying()) + return; + std::thread([this, engine, req, &resp] { + if ((ll::getServerStatus() != ll::ServerStatus::Running) || !EngineManager::isValid(engine) + || engine->isDestroying()) + return; + EngineScope enter(engine); + auto reqObj = new HttpRequestClass(req); + auto respObj = new HttpResponseClass(resp); + this->errorCallback.func.get().call({}, reqObj, respObj); + resp = *respObj->get(); + }).join(); + }); + return this->getScriptObject(); + } + CATCH("Fail in onError!"); } -Local HttpServerClass::onException(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kFunction); - - try { - exceptionCallback = {EngineScope::currentEngine(), - script::Global{args[0].asFunction()}}; - svr->set_exception_handler( - [this, engine = EngineScope::currentEngine()]( - const Request &req, Response &resp, std::exception_ptr e) { - if ((ll::getServerStatus() != ll::ServerStatus::Running) || - !EngineManager::isValid(engine) || engine->isDestroying()) - return; - std::thread([this, engine, req, &resp, e] { - if ((ll::getServerStatus() != ll::ServerStatus::Running) || - !EngineManager::isValid(engine) || engine->isDestroying()) - return; - EngineScope enter(engine); - auto reqObj = new HttpRequestClass(req); - auto respObj = new HttpResponseClass(resp); - try { - if (e) { - std::rethrow_exception(e); - } - } catch (const std::exception &exp) { - this->exceptionCallback.func.get().call( - {}, reqObj, respObj, String::newString(exp.what())); +Local HttpServerClass::onException(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kFunction); + + try { + exceptionCallback = {EngineScope::currentEngine(), script::Global{args[0].asFunction()}}; + svr->set_exception_handler( + [this, engine = EngineScope::currentEngine()](const Request& req, Response& resp, std::exception_ptr e) { + if ((ll::getServerStatus() != ll::ServerStatus::Running) || !EngineManager::isValid(engine) + || engine->isDestroying()) + return; + std::thread([this, engine, req, &resp, e] { + if ((ll::getServerStatus() != ll::ServerStatus::Running) || !EngineManager::isValid(engine) + || engine->isDestroying()) + return; + EngineScope enter(engine); + auto reqObj = new HttpRequestClass(req); + auto respObj = new HttpResponseClass(resp); + try { + if (e) { + std::rethrow_exception(e); + } + } catch (const std::exception& exp) { + this->exceptionCallback.func.get().call({}, reqObj, respObj, String::newString(exp.what())); + } + resp = *respObj->get(); + }).join(); } - resp = *respObj->get(); - }).join(); - }); - return this->getScriptObject(); - } - CATCH("Fail in onException!"); + ); + return this->getScriptObject(); + } + CATCH("Fail in onException!"); } -Local HttpServerClass::listen(const Arguments &args) { - if (args.size() == 1) { - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - } else if (args.size() == 2) { - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - - try { - string addr = "127.0.0.1"; - int port = 80; - if (args.size() == 2) { - addr = args[0].toStr(); - port = args[1].asNumber().toInt32(); +Local HttpServerClass::listen(const Arguments& args) { + if (args.size() == 1) { + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + } else if (args.size() == 2) { + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); } else { - port = args[0].asNumber().toInt32(); - } - if (port < 0 || port > 65535) { - throw script::Exception("Invalid port number! (0~65535)"); + LOG_WRONG_ARG_TYPE(); + return Local(); } - RecordOperation(ENGINE_OWN_DATA()->pluginName, "StartHttpServer", - fmt::format("on {}:{}", addr, port)); + try { + string addr = "127.0.0.1"; + int port = 80; + if (args.size() == 2) { + addr = args[0].toStr(); + port = args[1].asNumber().toInt32(); + } else { + port = args[0].asNumber().toInt32(); + } + if (port < 0 || port > 65535) { + throw script::Exception("Invalid port number! (0~65535)"); + } - std::thread th( - [this](string addr, int port) { svr->listen(addr.c_str(), port); }, - addr, port); - th.detach(); - return this->getScriptObject(); // return self - } - CATCH("Fail in listen!"); + RecordOperation(ENGINE_OWN_DATA()->pluginName, "StartHttpServer", fmt::format("on {}:{}", addr, port)); + + std::thread th([this](string addr, int port) { svr->listen(addr.c_str(), port); }, addr, port); + th.detach(); + return this->getScriptObject(); // return self + } + CATCH("Fail in listen!"); } -Local HttpServerClass::stop(const Arguments &args) { - CHECK_ARGS_COUNT(args, 0); +Local HttpServerClass::stop(const Arguments& args) { + CHECK_ARGS_COUNT(args, 0); - try { - RecordOperation(ENGINE_OWN_DATA()->pluginName, "StopHttpServer", ""); - svr->stop(); - return Local(); - } - CATCH("Fail in stop!"); + try { + RecordOperation(ENGINE_OWN_DATA()->pluginName, "StopHttpServer", ""); + svr->stop(); + return Local(); + } + CATCH("Fail in stop!"); } -Local HttpServerClass::isRunning(const Arguments &args) { - CHECK_ARGS_COUNT(args, 0); +Local HttpServerClass::isRunning(const Arguments& args) { + CHECK_ARGS_COUNT(args, 0); - try { - return Boolean::newBoolean(svr->is_running()); - } - CATCH("Fail in isRunning!"); + try { + return Boolean::newBoolean(svr->is_running()); + } + CATCH("Fail in isRunning!"); } -Local Headers2Object(const Headers &headers) { - auto obj = Object::newObject(); - for (auto &header : headers) { - obj.set(header.first, Array::newArray()); - } - for (auto &header : headers) { - auto arr = obj.get(header.first).asArray(); - arr.add(String::newString(header.second)); - obj.set(header.first, arr); - } - return obj; +Local Headers2Object(const Headers& headers) { + auto obj = Object::newObject(); + for (auto& header : headers) { + obj.set(header.first, Array::newArray()); + } + for (auto& header : headers) { + auto arr = obj.get(header.first).asArray(); + arr.add(String::newString(header.second)); + obj.set(header.first, arr); + } + return obj; } -Local Params2Object(const Params ¶ms) { - auto obj = Object::newObject(); - for (auto ¶m : params) { - if (params.count(param.first) == 1) - obj.set(param.first, param.second); - else { - if (!obj.has(param.first)) { - obj.set(param.first, Array::newArray()); - } - auto arr = obj.get(param.first).asArray(); - arr.add(String::newString(param.second)); - obj.set(param.first, arr); +Local Params2Object(const Params& params) { + auto obj = Object::newObject(); + for (auto& param : params) { + if (params.count(param.first) == 1) obj.set(param.first, param.second); + else { + if (!obj.has(param.first)) { + obj.set(param.first, Array::newArray()); + } + auto arr = obj.get(param.first).asArray(); + arr.add(String::newString(param.second)); + obj.set(param.first, arr); + } } - } - return obj; + return obj; } -HttpRequestClass::HttpRequestClass(const Local &scriptObj, - const Request &req) - : ScriptClass(scriptObj), req(new Request(req)) {} -HttpRequestClass::HttpRequestClass(const Request &req) - : ScriptClass(ScriptClass::ConstructFromCpp{}), - req(new Request(req)) {} +HttpRequestClass::HttpRequestClass(const Local& scriptObj, const Request& req) +: ScriptClass(scriptObj), + req(new Request(req)) {} +HttpRequestClass::HttpRequestClass(const Request& req) +: ScriptClass(ScriptClass::ConstructFromCpp{}), + req(new Request(req)) {} std::shared_ptr HttpRequestClass::get() { return req; } Local HttpRequestClass::getHeaders() { - try { - return Headers2Object(req->headers); - } - CATCH("Fail in getHeaders!"); + try { + return Headers2Object(req->headers); + } + CATCH("Fail in getHeaders!"); } -Local HttpRequestClass::getHeader(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - auto key = args[0].toStr(); - if (req->headers.count(key) == 0) - return Array::newArray(); - auto value = req->headers.equal_range(key); - auto arr = Array::newArray(); - for (auto it = value.first; it != value.second; ++it) { - arr.add(String::newString(it->second)); +Local HttpRequestClass::getHeader(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + auto key = args[0].toStr(); + if (req->headers.count(key) == 0) return Array::newArray(); + auto value = req->headers.equal_range(key); + auto arr = Array::newArray(); + for (auto it = value.first; it != value.second; ++it) { + arr.add(String::newString(it->second)); + } + return arr; } - return arr; - } - CATCH("Fail in getHeader!"); + CATCH("Fail in getHeader!"); } Local HttpRequestClass::getBody() { - try { - return String::newString(req->body); - } - CATCH("Fail in getBody!"); + try { + return String::newString(req->body); + } + CATCH("Fail in getBody!"); } Local HttpRequestClass::getMethod() { - try { - return String::newString(req->method); - } - CATCH("Fail in getMethod!"); + try { + return String::newString(req->method); + } + CATCH("Fail in getMethod!"); } Local HttpRequestClass::getPath() { - try { - return String::newString(req->path); - } - CATCH("Fail in getPath!"); + try { + return String::newString(req->path); + } + CATCH("Fail in getPath!"); } Local HttpRequestClass::getParams() { - try { - return Params2Object(req->params); - } - CATCH("Fail in getParams!"); + try { + return Params2Object(req->params); + } + CATCH("Fail in getParams!"); } Local HttpRequestClass::getRemoteAddr() { - try { - return String::newString(req->remote_addr); - } - CATCH("Fail in getRemoteAddr!"); + try { + return String::newString(req->remote_addr); + } + CATCH("Fail in getRemoteAddr!"); } Local HttpRequestClass::getRemotePort() { - try { - return Number::newNumber(req->remote_port); - } - CATCH("Fail in getRemotePort!"); + try { + return Number::newNumber(req->remote_port); + } + CATCH("Fail in getRemotePort!"); } Local HttpRequestClass::getVersion() { - try { - return String::newString(req->version); - } - CATCH("Fail in getVersion!"); + try { + return String::newString(req->version); + } + CATCH("Fail in getVersion!"); } Local HttpRequestClass::getRegexMatches() { - try { - auto smt = req->matches; - auto arr = Array::newArray(); - for (auto &match : smt) { - arr.add(String::newString(match)); + try { + auto smt = req->matches; + auto arr = Array::newArray(); + for (auto& match : smt) { + arr.add(String::newString(match)); + } + return arr; } - return arr; - } - CATCH("Fail in getRegexMatches!"); + CATCH("Fail in getRegexMatches!"); } -HttpResponseClass::HttpResponseClass(const Local &scriptObj, - const Response &resp) - : ScriptClass(scriptObj), resp(new Response(resp)) {} -HttpResponseClass::HttpResponseClass(const Response &resp) - : ScriptClass(ScriptClass::ConstructFromCpp{}), - resp(new Response(resp)) {} +HttpResponseClass::HttpResponseClass(const Local& scriptObj, const Response& resp) +: ScriptClass(scriptObj), + resp(new Response(resp)) {} +HttpResponseClass::HttpResponseClass(const Response& resp) +: ScriptClass(ScriptClass::ConstructFromCpp{}), + resp(new Response(resp)) {} std::shared_ptr HttpResponseClass::get() { return resp; } -Local HttpResponseClass::setHeader(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - auto key = args[0].toStr(); - string value; - if (args[1].isString()) - value = args[1].toStr(); - else - value = ValueToString(args[1]); - resp->headers.insert(make_pair(key, value)); - return this->getScriptObject(); // return self - } - CATCH("Fail in setHeader!"); +Local HttpResponseClass::setHeader(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + auto key = args[0].toStr(); + string value; + if (args[1].isString()) value = args[1].toStr(); + else value = ValueToString(args[1]); + resp->headers.insert(make_pair(key, value)); + return this->getScriptObject(); // return self + } + CATCH("Fail in setHeader!"); } -Local HttpResponseClass::getHeader(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - auto key = args[0].toStr(); - if (resp->headers.count(key) == 0) - return Array::newArray(); - auto value = resp->headers.equal_range(key); - auto arr = Array::newArray(); - for (auto it = value.first; it != value.second; ++it) { - arr.add(String::newString(it->second)); +Local HttpResponseClass::getHeader(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + auto key = args[0].toStr(); + if (resp->headers.count(key) == 0) return Array::newArray(); + auto value = resp->headers.equal_range(key); + auto arr = Array::newArray(); + for (auto it = value.first; it != value.second; ++it) { + arr.add(String::newString(it->second)); + } + return arr; } - return arr; - } - CATCH("Fail in getHeader!"); + CATCH("Fail in getHeader!"); } -Local HttpResponseClass::write(const Arguments &args) { - try { - for (size_t i = 0ULL, mEnd = args.size(); i < mEnd; ++i) { - resp->body += ValueToString(args[i]); +Local HttpResponseClass::write(const Arguments& args) { + try { + for (size_t i = 0ULL, mEnd = args.size(); i < mEnd; ++i) { + resp->body += ValueToString(args[i]); + } + return this->getScriptObject(); } - return this->getScriptObject(); - } - CATCH("Fail in write!"); + CATCH("Fail in write!"); } -void HttpResponseClass::setHeaders(const Local &headers) { - CHECK_ARG_TYPE_S(headers, ValueKind::kObject); - - try { - auto keys = headers.asObject().getKeys(); - for (auto &key : keys) { - auto key_str = key.toString(); - auto value = headers.asObject().get(key); - if (value.isArray()) { - for (size_t i = 0ULL; i < value.asArray().size(); ++i) { - resp->headers.insert( - make_pair(key_str, ValueToString(value.asArray().get(i)))); +void HttpResponseClass::setHeaders(const Local& headers) { + CHECK_ARG_TYPE_S(headers, ValueKind::kObject); + + try { + auto keys = headers.asObject().getKeys(); + for (auto& key : keys) { + auto key_str = key.toString(); + auto value = headers.asObject().get(key); + if (value.isArray()) { + for (size_t i = 0ULL; i < value.asArray().size(); ++i) { + resp->headers.insert(make_pair(key_str, ValueToString(value.asArray().get(i)))); + } + return; + } + auto val_str = ValueToString(value); + resp->headers.insert(make_pair(key_str, val_str)); } - return; - } - auto val_str = ValueToString(value); - resp->headers.insert(make_pair(key_str, val_str)); } - } - CATCH_S("Fail in setHeaders!"); + CATCH_S("Fail in setHeaders!"); } -void HttpResponseClass::setStatus(const Local &status) { - CHECK_ARG_TYPE_S(status, ValueKind::kNumber); +void HttpResponseClass::setStatus(const Local& status) { + CHECK_ARG_TYPE_S(status, ValueKind::kNumber); - try { - resp->status = status.toInt(); - } - CATCH_S("Fail in setStatus!"); + try { + resp->status = status.toInt(); + } + CATCH_S("Fail in setStatus!"); } -void HttpResponseClass::setBody(const Local &body) { - CHECK_ARG_TYPE_S(body, ValueKind::kString); +void HttpResponseClass::setBody(const Local& body) { + CHECK_ARG_TYPE_S(body, ValueKind::kString); - try { - resp->body = body.toStr(); - } - CATCH_S("Fail in setBody!"); + try { + resp->body = body.toStr(); + } + CATCH_S("Fail in setBody!"); } -void HttpResponseClass::setReason(const Local &reason) { - CHECK_ARG_TYPE_S(reason, ValueKind::kString); +void HttpResponseClass::setReason(const Local& reason) { + CHECK_ARG_TYPE_S(reason, ValueKind::kString); - try { - resp->reason = reason.toStr(); - } - CATCH_S("Fail in setReason!"); + try { + resp->reason = reason.toStr(); + } + CATCH_S("Fail in setReason!"); } -void HttpResponseClass::setVersion(const Local &version) { - CHECK_ARG_TYPE_S(version, ValueKind::kString); +void HttpResponseClass::setVersion(const Local& version) { + CHECK_ARG_TYPE_S(version, ValueKind::kString); - try { - resp->version = version.toStr(); - } - CATCH_S("Fail in setVersion!"); + try { + resp->version = version.toStr(); + } + CATCH_S("Fail in setVersion!"); } Local HttpResponseClass::getHeaders() { - try { - return Headers2Object(resp->headers); - } - CATCH("Fail in getHeaders!"); + try { + return Headers2Object(resp->headers); + } + CATCH("Fail in getHeaders!"); } Local HttpResponseClass::getStatus() { - try { - return Number::newNumber(resp->status); - } - CATCH("Fail in getStatus!"); + try { + return Number::newNumber(resp->status); + } + CATCH("Fail in getStatus!"); } Local HttpResponseClass::getBody() { - try { - return String::newString(resp->body); - } - CATCH("Fail in getBody!"); + try { + return String::newString(resp->body); + } + CATCH("Fail in getBody!"); } Local HttpResponseClass::getReason() { - try { - return String::newString(resp->reason); - } - CATCH("Fail in getReason!"); + try { + return String::newString(resp->reason); + } + CATCH("Fail in getReason!"); } Local HttpResponseClass::getVersion() { - try { - return String::newString(resp->version); - } - CATCH("Fail in getVersion!"); + try { + return String::newString(resp->version); + } + CATCH("Fail in getVersion!"); } //////////////////// APIs //////////////////// -void SplitHttpUrl(const std::string &url, string &host, string &path) { - host = url; +void SplitHttpUrl(const std::string& url, string& host, string& path) { + host = url; - bool foundProtocol = host.find('/') != string::npos; + bool foundProtocol = host.find('/') != string::npos; - auto splitPos = - host.find('/', foundProtocol ? host.find('/') + 2 - : 0); // 查找协议后的第一个/分割host与路径 - if (splitPos == string::npos) { - path = "/"; - } else { - path = host.substr(splitPos); - host = host.substr(0, splitPos); - } + auto splitPos = host.find('/', foundProtocol ? host.find('/') + 2 : 0); // 查找协议后的第一个/分割host与路径 + if (splitPos == string::npos) { + path = "/"; + } else { + path = host.substr(splitPos); + host = host.substr(0, splitPos); + } } -bool HttpGet(const std::string &url, const httplib::Headers &headers, - const std::function &callback, - int timeout = -1) { - string host, path; - SplitHttpUrl(url, host, path); - - auto *cli = new httplib::Client(host.c_str()); - if (!cli->is_valid()) { - delete cli; - return false; - } - if (timeout > 0) - cli->set_connection_timeout(timeout, 0); - - std::thread([cli, headers, callback, path{std::move(path)}]() { - try { - auto response = cli->Get(path.c_str(), headers); - delete cli; - - if (!response) - callback(-1, ""); - else - callback(response->status, response->body); - } catch (...) { +bool HttpGet( + const std::string& url, + const httplib::Headers& headers, + const std::function& callback, + int timeout = -1 +) { + string host, path; + SplitHttpUrl(url, host, path); + + auto* cli = new httplib::Client(host.c_str()); + if (!cli->is_valid()) { + delete cli; + return false; } - }).detach(); + if (timeout > 0) cli->set_connection_timeout(timeout, 0); + + std::thread([cli, headers, callback, path{std::move(path)}]() { + try { + auto response = cli->Get(path.c_str(), headers); + delete cli; + + if (!response) callback(-1, ""); + else callback(response->status, response->body); + } catch (...) {} + }).detach(); - return true; + return true; } -bool HttpGet(const std::string &url, - const std::function &callback, - int timeout = -1) { - return HttpGet(url, {}, callback, timeout); +bool HttpGet(const std::string& url, const std::function& callback, int timeout = -1) { + return HttpGet(url, {}, callback, timeout); } -bool HttpPost(const std::string &url, const httplib::Headers &headers, - const std::string &data, const std::string &type, - const std::function &callback, - int timeout = -1) { - std::string host, path; - SplitHttpUrl(url, host, path); - auto *cli = new httplib::Client(host.c_str()); - if (!cli->is_valid()) { - delete cli; - return false; - } - if (timeout > 0) - cli->set_connection_timeout(timeout, 0); - - std::thread([cli, headers, data, type, callback, path{std::move(path)}]() { - try { - auto response = cli->Post(path.c_str(), headers, data, type.c_str()); - delete cli; - if (!response) - callback(-1, ""); - else - callback(response->status, response->body); - } catch (...) { +bool HttpPost( + const std::string& url, + const httplib::Headers& headers, + const std::string& data, + const std::string& type, + const std::function& callback, + int timeout = -1 +) { + std::string host, path; + SplitHttpUrl(url, host, path); + auto* cli = new httplib::Client(host.c_str()); + if (!cli->is_valid()) { + delete cli; + return false; } - }).detach(); - return true; + if (timeout > 0) cli->set_connection_timeout(timeout, 0); + + std::thread([cli, headers, data, type, callback, path{std::move(path)}]() { + try { + auto response = cli->Post(path.c_str(), headers, data, type.c_str()); + delete cli; + if (!response) callback(-1, ""); + else callback(response->status, response->body); + } catch (...) {} + }).detach(); + return true; } -bool HttpPost(const string &url, const string &data, const string &type, - const std::function &callback, - int timeout = -1) { - return HttpPost(url, {}, data, type, callback, timeout); +bool HttpPost( + const string& url, + const string& data, + const string& type, + const std::function& callback, + int timeout = -1 +) { + return HttpPost(url, {}, data, type, callback, timeout); } -bool HttpGetSync(const std::string &url, int *statusRtn, std::string *dataRtn, - int timeout = -1) { - string host, path; - SplitHttpUrl(url, host, path); - - httplib::Client cli(host.c_str()); - if (!cli.is_valid()) { - return false; - } - if (timeout > 0) - cli.set_connection_timeout(timeout, 0); - - auto response = cli.Get(path.c_str()); - - if (!response) - return false; - else { - if (statusRtn) - *statusRtn = response->status; - if (dataRtn) - *dataRtn = response->body; - } - return true; +bool HttpGetSync(const std::string& url, int* statusRtn, std::string* dataRtn, int timeout = -1) { + string host, path; + SplitHttpUrl(url, host, path); + + httplib::Client cli(host.c_str()); + if (!cli.is_valid()) { + return false; + } + if (timeout > 0) cli.set_connection_timeout(timeout, 0); + + auto response = cli.Get(path.c_str()); + + if (!response) return false; + else { + if (statusRtn) *statusRtn = response->status; + if (dataRtn) *dataRtn = response->body; + } + return true; } -Local NetworkClass::httpGet(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - if (args.size() > 2) { - CHECK_ARG_TYPE(args[1], ValueKind::kObject); - CHECK_ARG_TYPE(args[2], ValueKind::kFunction); - } else { - CHECK_ARG_TYPE(args[1], ValueKind::kFunction); - } - - try { - string target = args[0].toStr(); - RecordOperation(ENGINE_OWN_DATA()->pluginName, "HttpGet", target); - script::Global callbackFunc{args[args.size() - 1].asFunction()}; - - auto lambda = [callback{std::move(callbackFunc)}, - engine{EngineScope::currentEngine()}](int status, - string body) { - if ((ll::getServerStatus() != ll::ServerStatus::Running) || - !EngineManager::isValid(engine) || engine->isDestroying()) - return; - - EngineScope scope(engine); - try { - NewTimeout(callback.get(), - {Number::newNumber(status), String::newString(body)}, 1); - // callback.get().call({}, {Number::newNumber(status), - // String::newString(body)}); - } - CATCH_IN_CALLBACK("HttpGet") - }; +Local NetworkClass::httpGet(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); if (args.size() > 2) { - httplib::Headers maps; - auto obj = args[1].asObject(); - auto keys = obj.getKeyNames(); - if (keys.size() > 0) { - for (size_t i = 0ULL, mEnd = keys.size(); i < mEnd; ++i) { - maps.insert({keys[i], obj.get(keys[i]).toStr()}); + CHECK_ARG_TYPE(args[1], ValueKind::kObject); + CHECK_ARG_TYPE(args[2], ValueKind::kFunction); + } else { + CHECK_ARG_TYPE(args[1], ValueKind::kFunction); + } + + try { + string target = args[0].toStr(); + RecordOperation(ENGINE_OWN_DATA()->pluginName, "HttpGet", target); + script::Global callbackFunc{args[args.size() - 1].asFunction()}; + + auto lambda = [callback{std::move(callbackFunc)}, + engine{EngineScope::currentEngine()}](int status, string body) { + if ((ll::getServerStatus() != ll::ServerStatus::Running) || !EngineManager::isValid(engine) + || engine->isDestroying()) + return; + + EngineScope scope(engine); + try { + NewTimeout(callback.get(), {Number::newNumber(status), String::newString(body)}, 1); + // callback.get().call({}, {Number::newNumber(status), + // String::newString(body)}); + } + CATCH_IN_CALLBACK("HttpGet") + }; + if (args.size() > 2) { + httplib::Headers maps; + auto obj = args[1].asObject(); + auto keys = obj.getKeyNames(); + if (keys.size() > 0) { + for (size_t i = 0ULL, mEnd = keys.size(); i < mEnd; ++i) { + maps.insert({keys[i], obj.get(keys[i]).toStr()}); + } + } + return Boolean::newBoolean(HttpGet(target, maps, lambda)); } - } - return Boolean::newBoolean(HttpGet(target, maps, lambda)); + return Boolean::newBoolean(HttpGet(target, lambda)); } - return Boolean::newBoolean(HttpGet(target, lambda)); - } - CATCH("Fail in HttpGet"); + CATCH("Fail in HttpGet"); } -Local NetworkClass::httpPost(const Arguments &args) { - CHECK_ARGS_COUNT(args, 4); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[2], ValueKind::kString); - if (args.size() > 4) { - CHECK_ARG_TYPE(args[1], ValueKind::kObject); - CHECK_ARG_TYPE(args[3], ValueKind::kString); - CHECK_ARG_TYPE(args[4], ValueKind::kFunction); - } else { - CHECK_ARG_TYPE(args[1], ValueKind::kString); - CHECK_ARG_TYPE(args[3], ValueKind::kFunction); - } - - try { - string target = args[0].toStr(); - RecordOperation(ENGINE_OWN_DATA()->pluginName, "HttpPost", target); - script::Global callbackFunc{args[args.size() - 1].asFunction()}; - - auto lambda = [callback{std::move(callbackFunc)}, - engine{EngineScope::currentEngine()}](int status, - string body) { - if ((ll::getServerStatus() != ll::ServerStatus::Running) || - !EngineManager::isValid(engine) || engine->isDestroying()) - return; - - EngineScope scope(engine); - try { - NewTimeout(callback.get(), - {Number::newNumber(status), String::newString(body)}, 1); - // callback.get().call({}, {Number::newNumber(status), - // String::newString(body)}); - } - CATCH_IN_CALLBACK("HttpPost") - }; +Local NetworkClass::httpPost(const Arguments& args) { + CHECK_ARGS_COUNT(args, 4); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[2], ValueKind::kString); if (args.size() > 4) { - httplib::Headers maps; - auto obj = args[1].asObject(); - auto keys = obj.getKeyNames(); - if (keys.size() > 0) { - for (size_t i = 0ULL, mEnd = keys.size(); i < mEnd; ++i) { - maps.insert({keys[i], obj.get(keys[i]).toStr()}); - } - } + CHECK_ARG_TYPE(args[1], ValueKind::kObject); + CHECK_ARG_TYPE(args[3], ValueKind::kString); + CHECK_ARG_TYPE(args[4], ValueKind::kFunction); + } else { + CHECK_ARG_TYPE(args[1], ValueKind::kString); + CHECK_ARG_TYPE(args[3], ValueKind::kFunction); + } + + try { + string target = args[0].toStr(); + RecordOperation(ENGINE_OWN_DATA()->pluginName, "HttpPost", target); + script::Global callbackFunc{args[args.size() - 1].asFunction()}; + + auto lambda = [callback{std::move(callbackFunc)}, + engine{EngineScope::currentEngine()}](int status, string body) { + if ((ll::getServerStatus() != ll::ServerStatus::Running) || !EngineManager::isValid(engine) + || engine->isDestroying()) + return; - return Boolean::newBoolean( - HttpPost(target, maps, args[2].toStr(), args[3].toStr(), lambda)); + EngineScope scope(engine); + try { + NewTimeout(callback.get(), {Number::newNumber(status), String::newString(body)}, 1); + // callback.get().call({}, {Number::newNumber(status), + // String::newString(body)}); + } + CATCH_IN_CALLBACK("HttpPost") + }; + if (args.size() > 4) { + httplib::Headers maps; + auto obj = args[1].asObject(); + auto keys = obj.getKeyNames(); + if (keys.size() > 0) { + for (size_t i = 0ULL, mEnd = keys.size(); i < mEnd; ++i) { + maps.insert({keys[i], obj.get(keys[i]).toStr()}); + } + } + + return Boolean::newBoolean(HttpPost(target, maps, args[2].toStr(), args[3].toStr(), lambda)); + } + return Boolean::newBoolean(HttpPost(target, args[1].toStr(), args[2].toStr(), lambda)); } - return Boolean::newBoolean( - HttpPost(target, args[1].toStr(), args[2].toStr(), lambda)); - } - CATCH("Fail in HttpPost"); + CATCH("Fail in HttpPost"); } -Local NetworkClass::httpGetSync(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - string target = args[0].toStr(); - RecordOperation(ENGINE_OWN_DATA()->pluginName, "HttpGetSync", target); - - int status; - string result; - HttpGetSync(target, &status, &result); - Local res = Object::newObject(); - res.set("status", status); - res.set("data", result); - return res; - } - CATCH("Fail in HttpGetSync"); +Local NetworkClass::httpGetSync(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + string target = args[0].toStr(); + RecordOperation(ENGINE_OWN_DATA()->pluginName, "HttpGetSync", target); + + int status; + string result; + HttpGetSync(target, &status, &result); + Local res = Object::newObject(); + res.set("status", status); + res.set("data", result); + return res; + } + CATCH("Fail in HttpGetSync"); } // For compatibility -Local NetworkClass::newWebSocket(const Arguments &args) { - auto newp = new WSClientClass(); - return newp->getScriptObject(); +Local NetworkClass::newWebSocket(const Arguments& args) { + auto newp = new WSClientClass(); + return newp->getScriptObject(); } Local WSClientClass::newWSClient() { - auto newp = new WSClientClass(); - return newp->getScriptObject(); + auto newp = new WSClientClass(); + return newp->getScriptObject(); } diff --git a/src/api/NetworkAPI.h b/src/api/NetworkAPI.h index 1e078a14..6e39e8c3 100644 --- a/src/api/NetworkAPI.h +++ b/src/api/NetworkAPI.h @@ -9,46 +9,32 @@ using namespace cyanray; //////////////////// Types //////////////////// -enum class WSClientEvents : char { - onTextReceived = 0, - onBinaryReceived, - onError, - onLostConnection, - EVENT_COUNT -}; +enum class WSClientEvents : char { onTextReceived = 0, onBinaryReceived, onError, onLostConnection, EVENT_COUNT }; struct ListenerListType { - ScriptEngine *engine; - script::Global func; + ScriptEngine* engine; + script::Global func; }; -enum class HttpRequestType : char { - Get = 0, - Post, - Put, - Delete, - Options, - Patch, - Head -}; +enum class HttpRequestType : char { Get = 0, Post, Put, Delete, Options, Patch, Head }; struct HttpServerCallback { - ScriptEngine *engine; - script::Global func; - HttpRequestType type; - std::string path; + ScriptEngine* engine; + script::Global func; + HttpRequestType type; + std::string path; }; //////////////////// Network Static //////////////////// class NetworkClass { public: - static Local httpGet(const Arguments &args); - static Local httpPost(const Arguments &args); - static Local httpGetSync(const Arguments &args); + static Local httpGet(const Arguments& args); + static Local httpPost(const Arguments& args); + static Local httpGetSync(const Arguments& args); - // For Compatibility - static Local newWebSocket(const Arguments &args); + // For Compatibility + static Local newWebSocket(const Arguments& args); }; extern ClassDefine NetworkClassBuilder; @@ -56,114 +42,111 @@ extern ClassDefine NetworkClassBuilder; class WSClientClass : public ScriptClass { private: - std::shared_ptr ws; - std::list listeners[(int)WSClientEvents::EVENT_COUNT]; - void addListener(const string &event, Local func); + std::shared_ptr ws; + std::list listeners[(int)WSClientEvents::EVENT_COUNT]; + void addListener(const string& event, Local func); public: - explicit WSClientClass(const Local &scriptObj); - explicit WSClientClass(); - void initListeners(); - void initListeners_s(); - void clearListeners(); - ~WSClientClass() { ws->Shutdown(); } - static WSClientClass *constructor(const Arguments &args); - - Local getStatus(); - - Local connect(const Arguments &args); - Local connectAsync(const Arguments &args); - Local send(const Arguments &args); - Local listen(const Arguments &args); - Local close(const Arguments &args); - Local shutdown(const Arguments &args); - Local errorCode(const Arguments &args); - - // For Compatibility - static Local newWSClient(); + explicit WSClientClass(const Local& scriptObj); + explicit WSClientClass(); + void initListeners(); + void initListeners_s(); + void clearListeners(); + ~WSClientClass() { ws->Shutdown(); } + static WSClientClass* constructor(const Arguments& args); + + Local getStatus(); + + Local connect(const Arguments& args); + Local connectAsync(const Arguments& args); + Local send(const Arguments& args); + Local listen(const Arguments& args); + Local close(const Arguments& args); + Local shutdown(const Arguments& args); + Local errorCode(const Arguments& args); + + // For Compatibility + static Local newWSClient(); }; extern ClassDefine WSClientClassBuilder; class HttpServerClass : public ScriptClass { protected: - std::shared_ptr svr = nullptr; - std::multimap callbacks; - HttpServerCallback errorCallback, exceptionCallback, preRoutingCallback, - postRoutingCallback; + std::shared_ptr svr = nullptr; + std::multimap callbacks; + HttpServerCallback errorCallback, exceptionCallback, preRoutingCallback, postRoutingCallback; public: - HttpServerClass(const Local &scriptObj); - HttpServerClass(); - ~HttpServerClass(); - static HttpServerClass *constructor(const Arguments &args); - - Local onGet(const Arguments &args); - Local onPut(const Arguments &args); - Local onPost(const Arguments &args); - Local onPatch(const Arguments &args); - Local onDelete(const Arguments &args); - Local onOptions(const Arguments &args); - - Local onPreRouting(const Arguments &args); - Local onPostRouting(const Arguments &args); - Local onError(const Arguments &args); - Local onException(const Arguments &args); - - Local listen(const Arguments &args); - Local stop(const Arguments &args); - Local isRunning(const Arguments &args); + HttpServerClass(const Local& scriptObj); + HttpServerClass(); + ~HttpServerClass(); + static HttpServerClass* constructor(const Arguments& args); + + Local onGet(const Arguments& args); + Local onPut(const Arguments& args); + Local onPost(const Arguments& args); + Local onPatch(const Arguments& args); + Local onDelete(const Arguments& args); + Local onOptions(const Arguments& args); + + Local onPreRouting(const Arguments& args); + Local onPostRouting(const Arguments& args); + Local onError(const Arguments& args); + Local onException(const Arguments& args); + + Local listen(const Arguments& args); + Local stop(const Arguments& args); + Local isRunning(const Arguments& args); }; extern ClassDefine HttpServerClassBuilder; class HttpRequestClass : public ScriptClass { - std::shared_ptr req; + std::shared_ptr req; public: - HttpRequestClass(const Local &scriptObj, - const httplib::Request &req = {}); - HttpRequestClass(const httplib::Request &req = {}); - // static HttpRequestClass* constructor(const Arguments& args); - std::shared_ptr get(); - - Local getHeaders(); - Local getHeader(const Arguments &args); - Local getBody(); - Local getMethod(); - Local getPath(); - Local getParams(); - Local getRemoteAddr(); - Local getRemotePort(); - Local getVersion(); - Local getRegexMatches(); - // Local getMultiFormData(); + HttpRequestClass(const Local& scriptObj, const httplib::Request& req = {}); + HttpRequestClass(const httplib::Request& req = {}); + // static HttpRequestClass* constructor(const Arguments& args); + std::shared_ptr get(); + + Local getHeaders(); + Local getHeader(const Arguments& args); + Local getBody(); + Local getMethod(); + Local getPath(); + Local getParams(); + Local getRemoteAddr(); + Local getRemotePort(); + Local getVersion(); + Local getRegexMatches(); + // Local getMultiFormData(); }; extern ClassDefine HttpRequestClassBuilder; class HttpResponseClass : public ScriptClass { - std::shared_ptr resp; + std::shared_ptr resp; public: - HttpResponseClass(const Local &scriptObj, - const httplib::Response &resp = {}); - HttpResponseClass(const httplib::Response &resp); - // static HttpResponseClass* constructor(const Arguments& args); - std::shared_ptr get(); - - Local setHeader(const Arguments &args); - Local getHeader(const Arguments &args); - Local write(const Arguments &args); - - void setHeaders(const Local &headers); - void setStatus(const Local &status); - void setBody(const Local &body); - void setReason(const Local &reason); - void setVersion(const Local &version); - - Local getHeaders(); - Local getStatus(); - Local getBody(); - Local getReason(); - Local getVersion(); + HttpResponseClass(const Local& scriptObj, const httplib::Response& resp = {}); + HttpResponseClass(const httplib::Response& resp); + // static HttpResponseClass* constructor(const Arguments& args); + std::shared_ptr get(); + + Local setHeader(const Arguments& args); + Local getHeader(const Arguments& args); + Local write(const Arguments& args); + + void setHeaders(const Local& headers); + void setStatus(const Local& status); + void setBody(const Local& body); + void setReason(const Local& reason); + void setVersion(const Local& version); + + Local getHeaders(); + Local getStatus(); + Local getBody(); + Local getReason(); + Local getVersion(); }; extern ClassDefine HttpResponseClassBuilder; \ No newline at end of file diff --git a/src/api/PacketAPI.cpp b/src/api/PacketAPI.cpp index 27619d08..dfb06eaa 100644 --- a/src/api/PacketAPI.cpp +++ b/src/api/PacketAPI.cpp @@ -9,20 +9,19 @@ #include "api/NativeAPI.h" #include "api/NbtAPI.h" #include "mc/deps/core/utility/BinaryStream.h" -#include "mc/network/packet/Packet.h" #include "mc/network/MinecraftPackets.h" +#include "mc/network/packet/Packet.h" //////////////////// Class Definition //////////////////// -ClassDefine PacketClassBuilder = - defineClass("LLSE_Packet") - .constructor(nullptr) - .instanceFunction("asPointer", &PacketClass::asPointer) - .instanceFunction("getName", &PacketClass::getName) - .instanceFunction("getId", &PacketClass::getId) - - .build(); +ClassDefine PacketClassBuilder = defineClass("LLSE_Packet") + .constructor(nullptr) + .instanceFunction("asPointer", &PacketClass::asPointer) + .instanceFunction("getName", &PacketClass::getName) + .instanceFunction("getId", &PacketClass::getId) + + .build(); ClassDefine BinaryStreamClassBuilder = defineClass("BinaryStream") @@ -55,8 +54,7 @@ ClassDefine BinaryStreamClassBuilder = //////////////////// Packet Classes //////////////////// -PacketClass::PacketClass(std::shared_ptr p) -: ScriptClass(ScriptClass::ConstructFromCpp{}) { +PacketClass::PacketClass(std::shared_ptr p) : ScriptClass(ScriptClass::ConstructFromCpp{}) { set(p); } @@ -69,8 +67,7 @@ Local PacketClass::newPacket(std::shared_ptr pkt) { std::shared_ptr PacketClass::extract(Local v) { if (EngineScope::currentEngine()->isInstanceOf(v)) return EngineScope::currentEngine()->getNativeInstance(v)->get(); - else - return nullptr; + else return nullptr; } // member function @@ -78,10 +75,8 @@ std::shared_ptr PacketClass::extract(Local v) { Local PacketClass::asPointer(const Arguments& args) { try { std::shared_ptr pkt = get(); - if (!pkt) - return Local(); - else - return NativePointer::newNativePointer(pkt.get()); + if (!pkt) return Local(); + else return NativePointer::newNativePointer(pkt.get()); } CATCH("Fail in asPointer!") } @@ -158,10 +153,9 @@ Local BinaryStreamClass::reserve(const Arguments& args) { CHECK_ARGS_COUNT(args, 1); CHECK_ARG_TYPE(args[0], ValueKind::kNumber); try { - return Boolean::newBoolean(true); - } - CATCH("Fail in BinaryStream reserve!"); - + return Boolean::newBoolean(true); + } + CATCH("Fail in BinaryStream reserve!"); } Local BinaryStreamClass::writeBool(const Arguments& args) { @@ -207,200 +201,200 @@ Local BinaryStreamClass::writeDouble(const Arguments& args) { } Local BinaryStreamClass::writeFloat(const Arguments& args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - BinaryStream* pkt = get(); - if (!pkt) { - return Local(); - } - pkt->writeFloat(args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in BinaryStream writeFloat!"); + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + try { + BinaryStream* pkt = get(); + if (!pkt) { + return Local(); + } + pkt->writeFloat(args[0].asNumber().toFloat()); + return Boolean::newBoolean(true); + } + CATCH("Fail in BinaryStream writeFloat!"); } Local BinaryStreamClass::writeSignedBigEndianInt(const Arguments& args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - BinaryStream* pkt = get(); - if (!pkt) { - return Local(); - } - pkt->writeSignedBigEndianInt(args[0].asNumber().toInt32()); - return Boolean::newBoolean(true); - } - CATCH("Fail in BinaryStream writeSignedBigEndianInt!"); + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + try { + BinaryStream* pkt = get(); + if (!pkt) { + return Local(); + } + pkt->writeSignedBigEndianInt(args[0].asNumber().toInt32()); + return Boolean::newBoolean(true); + } + CATCH("Fail in BinaryStream writeSignedBigEndianInt!"); } Local BinaryStreamClass::writeSignedInt(const Arguments& args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - BinaryStream* pkt = get(); - if (!pkt) { - return Local(); - } - pkt->writeSignedInt(args[0].asNumber().toInt32()); - return Boolean::newBoolean(true); - } - CATCH("Fail in BinaryStream writeSignedInt!"); + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + try { + BinaryStream* pkt = get(); + if (!pkt) { + return Local(); + } + pkt->writeSignedInt(args[0].asNumber().toInt32()); + return Boolean::newBoolean(true); + } + CATCH("Fail in BinaryStream writeSignedInt!"); } Local BinaryStreamClass::writeSignedInt64(const Arguments& args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - BinaryStream* pkt = get(); - if (!pkt) { - return Local(); - } - pkt->writeSignedInt64(args[0].asNumber().toInt64()); - return Boolean::newBoolean(true); - } - CATCH("Fail in BinaryStream writeSignedInt64!"); + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + try { + BinaryStream* pkt = get(); + if (!pkt) { + return Local(); + } + pkt->writeSignedInt64(args[0].asNumber().toInt64()); + return Boolean::newBoolean(true); + } + CATCH("Fail in BinaryStream writeSignedInt64!"); } Local BinaryStreamClass::writeSignedShort(const Arguments& args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - BinaryStream* pkt = get(); - if (!pkt) { - return Local(); - } - pkt->writeSignedShort(args[0].asNumber().toInt32()); - return Boolean::newBoolean(true); - } - CATCH("Fail in BinaryStream writeSignedShort!"); + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + try { + BinaryStream* pkt = get(); + if (!pkt) { + return Local(); + } + pkt->writeSignedShort(args[0].asNumber().toInt32()); + return Boolean::newBoolean(true); + } + CATCH("Fail in BinaryStream writeSignedShort!"); } Local BinaryStreamClass::writeString(const Arguments& args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - BinaryStream* pkt = get(); - if (!pkt) { - return Local(); - } - pkt->writeString(args[0].asString().toString()); - return Boolean::newBoolean(true); - } - CATCH("Fail in BinaryStream writeString!"); + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + try { + BinaryStream* pkt = get(); + if (!pkt) { + return Local(); + } + pkt->writeString(args[0].asString().toString()); + return Boolean::newBoolean(true); + } + CATCH("Fail in BinaryStream writeString!"); } Local BinaryStreamClass::writeUnsignedChar(const Arguments& args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - BinaryStream* pkt = get(); - if (!pkt) { - return Local(); - } - pkt->writeUnsignedChar(args[0].asNumber().toInt32()); - return Boolean::newBoolean(true); - } - CATCH("Fail in BinaryStream writeUnsignedChar!"); + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + try { + BinaryStream* pkt = get(); + if (!pkt) { + return Local(); + } + pkt->writeUnsignedChar(args[0].asNumber().toInt32()); + return Boolean::newBoolean(true); + } + CATCH("Fail in BinaryStream writeUnsignedChar!"); } Local BinaryStreamClass::writeUnsignedInt(const Arguments& args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - BinaryStream* pkt = get(); - if (!pkt) { - return Local(); - } - pkt->writeUnsignedInt((uint32_t)args[0].asNumber().toInt32()); - return Boolean::newBoolean(true); - } - CATCH("Fail in BinaryStream writeUnsignedInt!"); + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + try { + BinaryStream* pkt = get(); + if (!pkt) { + return Local(); + } + pkt->writeUnsignedInt((uint32_t)args[0].asNumber().toInt32()); + return Boolean::newBoolean(true); + } + CATCH("Fail in BinaryStream writeUnsignedInt!"); } Local BinaryStreamClass::writeUnsignedInt64(const Arguments& args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - BinaryStream* pkt = get(); - if (!pkt) { - return Local(); - } - pkt->writeUnsignedInt64((uint64_t)args[0].asNumber().toInt64()); - return Boolean::newBoolean(true); - } - CATCH("Fail in BinaryStream writeUnsignedInt64!"); + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + try { + BinaryStream* pkt = get(); + if (!pkt) { + return Local(); + } + pkt->writeUnsignedInt64((uint64_t)args[0].asNumber().toInt64()); + return Boolean::newBoolean(true); + } + CATCH("Fail in BinaryStream writeUnsignedInt64!"); } Local BinaryStreamClass::writeUnsignedShort(const Arguments& args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - BinaryStream* pkt = get(); - if (!pkt) { - return Local(); - } - pkt->writeUnsignedShort((uint16_t)args[0].asNumber().toInt32()); - return Boolean::newBoolean(true); - } - CATCH("Fail in BinaryStream writeUnsignedShort!"); + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + try { + BinaryStream* pkt = get(); + if (!pkt) { + return Local(); + } + pkt->writeUnsignedShort((uint16_t)args[0].asNumber().toInt32()); + return Boolean::newBoolean(true); + } + CATCH("Fail in BinaryStream writeUnsignedShort!"); } Local BinaryStreamClass::writeUnsignedVarInt(const Arguments& args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - BinaryStream* pkt = get(); - if (!pkt) { - return Local(); - } - pkt->writeUnsignedVarInt((uint32_t)args[0].asNumber().toInt32()); - return Boolean::newBoolean(true); - } - CATCH("Fail in BinaryStream writeUnsignedVarInt!"); + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + try { + BinaryStream* pkt = get(); + if (!pkt) { + return Local(); + } + pkt->writeUnsignedVarInt((uint32_t)args[0].asNumber().toInt32()); + return Boolean::newBoolean(true); + } + CATCH("Fail in BinaryStream writeUnsignedVarInt!"); } Local BinaryStreamClass::writeUnsignedVarInt64(const Arguments& args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - BinaryStream* pkt = get(); - if (!pkt) { - return Local(); - } - pkt->writeUnsignedVarInt64((uint64_t)args[0].asNumber().toInt64()); - return Boolean::newBoolean(true); - } - CATCH("Fail in BinaryStream writeUnsignedVarInt64!"); + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + try { + BinaryStream* pkt = get(); + if (!pkt) { + return Local(); + } + pkt->writeUnsignedVarInt64((uint64_t)args[0].asNumber().toInt64()); + return Boolean::newBoolean(true); + } + CATCH("Fail in BinaryStream writeUnsignedVarInt64!"); } Local BinaryStreamClass::writeVarInt(const Arguments& args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - BinaryStream* pkt = get(); - if (!pkt) { - return Local(); - } - pkt->writeVarInt(args[0].asNumber().toInt32()); - return Boolean::newBoolean(true); - } - CATCH("Fail in BinaryStream writeVarInt!"); + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + try { + BinaryStream* pkt = get(); + if (!pkt) { + return Local(); + } + pkt->writeVarInt(args[0].asNumber().toInt32()); + return Boolean::newBoolean(true); + } + CATCH("Fail in BinaryStream writeVarInt!"); } Local BinaryStreamClass::writeVarInt64(const Arguments& args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - BinaryStream* pkt = get(); - if (!pkt) { - return Local(); - } - pkt->writeVarInt64(args[0].asNumber().toInt64()); - return Boolean::newBoolean(true); - } - CATCH("Fail in BinaryStream writeVarInt64!"); + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + try { + BinaryStream* pkt = get(); + if (!pkt) { + return Local(); + } + pkt->writeVarInt64(args[0].asNumber().toInt64()); + return Boolean::newBoolean(true); + } + CATCH("Fail in BinaryStream writeVarInt64!"); } Local BinaryStreamClass::writeVec3(const Arguments& args) { @@ -421,7 +415,7 @@ Local BinaryStreamClass::writeVec3(const Arguments& args) { CATCH("Fail in BinaryStream writeVec3!"); } -Local BinaryStreamClass::writeCompoundTag(const Arguments& args){ +Local BinaryStreamClass::writeCompoundTag(const Arguments& args) { CHECK_ARGS_COUNT(args, 1); try { BinaryStream* pkt = get(); @@ -439,7 +433,7 @@ Local BinaryStreamClass::writeCompoundTag(const Arguments& args){ CATCH("Fail in BinaryStream writeCompoundTag!"); } - Local BinaryStreamClass::createPacket(const Arguments& args) { +Local BinaryStreamClass::createPacket(const Arguments& args) { CHECK_ARGS_COUNT(args, 1); try { BinaryStream* bs = get(); @@ -452,4 +446,3 @@ Local BinaryStreamClass::writeCompoundTag(const Arguments& args){ } CATCH("Fail in BinaryStream createPacket!"); } - diff --git a/src/api/PacketAPI.h b/src/api/PacketAPI.h index 70e4d6fb..a475acad 100644 --- a/src/api/PacketAPI.h +++ b/src/api/PacketAPI.h @@ -1,6 +1,6 @@ #pragma once #include "api/APIHelp.h" -#include "main/Global.hpp" +#include "main/Global.h" #include "mc/deps/core/utility/BinaryStream.h" #include @@ -10,64 +10,63 @@ class BinaryStream; class PacketClass : public ScriptClass { private: - std::shared_ptr packet; + std::shared_ptr packet; public: - explicit PacketClass(std::shared_ptr p); - static std::shared_ptr extract(Local v); + explicit PacketClass(std::shared_ptr p); + static std::shared_ptr extract(Local v); - std::shared_ptr get() { return packet; } + std::shared_ptr get() { return packet; } - void set(std::shared_ptr pkt) { packet = pkt; }; + void set(std::shared_ptr pkt) { packet = pkt; }; - static Local newPacket(std::shared_ptr pkt); + static Local newPacket(std::shared_ptr pkt); - Local asPointer(const Arguments &args); - Local getId(); - Local getName(); + Local asPointer(const Arguments& args); + Local getId(); + Local getName(); }; extern ClassDefine PacketClassBuilder; class BinaryStreamClass : public ScriptClass { private: - BinaryStream *bs; + BinaryStream* bs; public: - explicit BinaryStreamClass(BinaryStream *p); + explicit BinaryStreamClass(BinaryStream* p); - BinaryStreamClass(const Local &scriptObj) - : ScriptClass(scriptObj), bs(new BinaryStream) {} + BinaryStreamClass(const Local& scriptObj) : ScriptClass(scriptObj), bs(new BinaryStream) {} - BinaryStream *get() { return bs; } - void set(BinaryStream *pkt) { bs = pkt; }; + BinaryStream* get() { return bs; } + void set(BinaryStream* pkt) { bs = pkt; }; - static Local newBinaryStream(); - static BinaryStreamClass *constructor(const Arguments &args); + static Local newBinaryStream(); + static BinaryStreamClass* constructor(const Arguments& args); - Local getAndReleaseData(); - Local reset(); + Local getAndReleaseData(); + Local reset(); - Local reserve(const Arguments &args); - Local writeBool(const Arguments &args); - Local writeByte(const Arguments &args); - Local writeDouble(const Arguments &args); - Local writeFloat(const Arguments &args); - Local writeSignedBigEndianInt(const Arguments &args); - Local writeSignedInt(const Arguments &args); - Local writeSignedInt64(const Arguments &args); - Local writeSignedShort(const Arguments &args); - Local writeString(const Arguments &args); - Local writeUnsignedChar(const Arguments &args); - Local writeUnsignedInt(const Arguments &args); - Local writeUnsignedInt64(const Arguments &args); - Local writeUnsignedShort(const Arguments &args); - Local writeUnsignedVarInt(const Arguments &args); - Local writeUnsignedVarInt64(const Arguments &args); - Local writeVarInt(const Arguments &args); - Local writeVarInt64(const Arguments &args); - Local writeVec3(const Arguments &args); - Local writeCompoundTag(const Arguments &args); + Local reserve(const Arguments& args); + Local writeBool(const Arguments& args); + Local writeByte(const Arguments& args); + Local writeDouble(const Arguments& args); + Local writeFloat(const Arguments& args); + Local writeSignedBigEndianInt(const Arguments& args); + Local writeSignedInt(const Arguments& args); + Local writeSignedInt64(const Arguments& args); + Local writeSignedShort(const Arguments& args); + Local writeString(const Arguments& args); + Local writeUnsignedChar(const Arguments& args); + Local writeUnsignedInt(const Arguments& args); + Local writeUnsignedInt64(const Arguments& args); + Local writeUnsignedShort(const Arguments& args); + Local writeUnsignedVarInt(const Arguments& args); + Local writeUnsignedVarInt64(const Arguments& args); + Local writeVarInt(const Arguments& args); + Local writeVarInt64(const Arguments& args); + Local writeVec3(const Arguments& args); + Local writeCompoundTag(const Arguments& args); - Local createPacket(const Arguments &args); + Local createPacket(const Arguments& args); }; -extern ClassDefine BinaryStreamClassBuilder; \ No newline at end of file +extern ClassDefine BinaryStreamClassBuilder; diff --git a/src/api/ParticleAPI.cpp b/src/api/ParticleAPI.cpp index a6549e72..0749e066 100644 --- a/src/api/ParticleAPI.cpp +++ b/src/api/ParticleAPI.cpp @@ -5,357 +5,340 @@ #include "McAPI.h" #include "mc/deps/core/mce/Color.h" -#define GETVEC3(v, d, u) \ - if (IsInstanceOf(u)) { \ - auto pos2 = EngineScope::currentEngine() -> getNativeInstance(u); \ - v = Vec3(pos2->x, pos2->y, pos2->z); \ - v += 0.5f; \ - d = pos2->dim; \ - } else if (IsInstanceOf(u)) { \ - auto pos2 = \ - EngineScope::currentEngine() -> getNativeInstance(u); \ - v = Vec3(pos2->x, pos2->y, pos2->z); \ - d = pos2->dim; \ - } else { \ - LOG_WRONG_ARG_TYPE(); \ - return Local(); \ - } +#define GETVEC3(v, d, u) \ + if (IsInstanceOf(u)) { \ + auto pos2 = EngineScope::currentEngine()->getNativeInstance(u); \ + v = Vec3(pos2->x, pos2->y, pos2->z); \ + v += 0.5f; \ + d = pos2->dim; \ + } else if (IsInstanceOf(u)) { \ + auto pos2 = EngineScope::currentEngine()->getNativeInstance(u); \ + v = Vec3(pos2->x, pos2->y, pos2->z); \ + d = pos2->dim; \ + } else { \ + LOG_WRONG_ARG_TYPE(); \ + return Local(); \ + } namespace { -template std::string fto_string(const T a_value) { - std::ostringstream out; - out << a_value; - return out.str(); +template +std::string fto_string(const T a_value) { + std::ostringstream out; + out << a_value; + return out.str(); } ParticleCUI::ColorPalette getColorType(std::string s) { - switch (s[0]) { - case 'B': - return ParticleCUI::ColorPalette::BLACK; - break; - case 'I': - return ParticleCUI::ColorPalette::INDIGO; - break; - case 'L': - return ParticleCUI::ColorPalette::LAVENDER; - break; - case 'T': - return ParticleCUI::ColorPalette::TEAL; - break; - case 'C': - return ParticleCUI::ColorPalette::COCOA; - break; - case 'D': - return ParticleCUI::ColorPalette::DARK; - break; - case 'O': - return ParticleCUI::ColorPalette::OATMEAL; - break; - case 'W': - return ParticleCUI::ColorPalette::WHITE; - break; - case 'R': - return ParticleCUI::ColorPalette::RED; - break; - case 'A': - return ParticleCUI::ColorPalette::APRICOT; - break; - case 'Y': - return ParticleCUI::ColorPalette::YELLOW; - break; - case 'G': - return ParticleCUI::ColorPalette::GREEN; - break; - case 'V': - return ParticleCUI::ColorPalette::VATBLUE; - break; - case 'S': - return ParticleCUI::ColorPalette::SLATE; - break; - case 'P': - return ParticleCUI::ColorPalette::PINK; - break; - case 'F': - return ParticleCUI::ColorPalette::FAWN; - break; - default: - return ParticleCUI::ColorPalette::WHITE; - break; - } + switch (s[0]) { + case 'B': + return ParticleCUI::ColorPalette::BLACK; + break; + case 'I': + return ParticleCUI::ColorPalette::INDIGO; + break; + case 'L': + return ParticleCUI::ColorPalette::LAVENDER; + break; + case 'T': + return ParticleCUI::ColorPalette::TEAL; + break; + case 'C': + return ParticleCUI::ColorPalette::COCOA; + break; + case 'D': + return ParticleCUI::ColorPalette::DARK; + break; + case 'O': + return ParticleCUI::ColorPalette::OATMEAL; + break; + case 'W': + return ParticleCUI::ColorPalette::WHITE; + break; + case 'R': + return ParticleCUI::ColorPalette::RED; + break; + case 'A': + return ParticleCUI::ColorPalette::APRICOT; + break; + case 'Y': + return ParticleCUI::ColorPalette::YELLOW; + break; + case 'G': + return ParticleCUI::ColorPalette::GREEN; + break; + case 'V': + return ParticleCUI::ColorPalette::VATBLUE; + break; + case 'S': + return ParticleCUI::ColorPalette::SLATE; + break; + case 'P': + return ParticleCUI::ColorPalette::PINK; + break; + case 'F': + return ParticleCUI::ColorPalette::FAWN; + break; + default: + return ParticleCUI::ColorPalette::WHITE; + break; + } } } // namespace -ParticleSpawner *ParticleSpawner::create(const Arguments &args) { - if (args.size() < 3) - return nullptr; - try { - ParticleSpawner *p = new ParticleSpawner(args.thiz()); - p->displayRadius = args[0].asNumber().toInt64(); - p->highDetial = args[1].asBoolean().value(); - p->doubleSide = args[2].asBoolean().value(); - return p; - } catch (...) { - return nullptr; - } +ParticleSpawner* ParticleSpawner::create(const Arguments& args) { + if (args.size() < 3) return nullptr; + try { + ParticleSpawner* p = new ParticleSpawner(args.thiz()); + p->displayRadius = args[0].asNumber().toInt64(); + p->highDetial = args[1].asBoolean().value(); + p->doubleSide = args[2].asBoolean().value(); + return p; + } catch (...) { + return nullptr; + } } -Local McClass::newParticleSpawner(const Arguments &args) { - auto size = args.size(); - unsigned int displayRadius = UINT_MAX; - bool highDetial = true; - bool doubleSide = true; +Local McClass::newParticleSpawner(const Arguments& args) { + auto size = args.size(); + unsigned int displayRadius = UINT_MAX; + bool highDetial = true; + bool doubleSide = true; - if (size > 0) { - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - displayRadius = args[0].asNumber().toInt64(); - } - if (size > 1) { - CHECK_ARG_TYPE(args[1], ValueKind::kBoolean); - highDetial = args[1].asBoolean().value(); - } - if (size > 2) { - CHECK_ARG_TYPE(args[2], ValueKind::kBoolean); - doubleSide = args[2].asBoolean().value(); - } - return EngineScope::currentEngine()->newNativeClass( - displayRadius, highDetial, doubleSide); + if (size > 0) { + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + displayRadius = args[0].asNumber().toInt64(); + } + if (size > 1) { + CHECK_ARG_TYPE(args[1], ValueKind::kBoolean); + highDetial = args[1].asBoolean().value(); + } + if (size > 2) { + CHECK_ARG_TYPE(args[2], ValueKind::kBoolean); + doubleSide = args[2].asBoolean().value(); + } + return EngineScope::currentEngine()->newNativeClass(displayRadius, highDetial, doubleSide); } -Local ParticleSpawner::spawnParticle(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - Vec3 pos; - int dimId; - std::string particleName; - GETVEC3(pos, dimId, args[0]) - CHECK_ARG_TYPE(args[1], ValueKind::kString); - particleName = args[1].asString().toString(); - ParticleCUI::spawnParticle(pos, particleName, dimId); - return Boolean::newBoolean(true); +Local ParticleSpawner::spawnParticle(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + Vec3 pos; + int dimId; + std::string particleName; + GETVEC3(pos, dimId, args[0]) + CHECK_ARG_TYPE(args[1], ValueKind::kString); + particleName = args[1].asString().toString(); + ParticleCUI::spawnParticle(pos, particleName, dimId); + return Boolean::newBoolean(true); } -Local ParticleSpawner::drawPoint(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - Vec3 pos; - int dimId; - GETVEC3(pos, dimId, args[0]) - auto pointSize = ParticleCUI::PointSize::PX4; +Local ParticleSpawner::drawPoint(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + Vec3 pos; + int dimId; + GETVEC3(pos, dimId, args[0]) + auto pointSize = ParticleCUI::PointSize::PX4; - if (args.size() > 1) { - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - pointSize = - static_cast(args[1].asNumber().toInt32()); - } - std::string color = "W"; - if (args.size() > 2) { - CHECK_ARG_TYPE(args[2], ValueKind::kString); - color = args[2].asString().toString(); - } - ParticleCUI::drawPoint(pos, dimId, pointSize, getColorType(color)); - return Boolean::newBoolean(true); + if (args.size() > 1) { + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + pointSize = static_cast(args[1].asNumber().toInt32()); + } + std::string color = "W"; + if (args.size() > 2) { + CHECK_ARG_TYPE(args[2], ValueKind::kString); + color = args[2].asString().toString(); + } + ParticleCUI::drawPoint(pos, dimId, pointSize, getColorType(color)); + return Boolean::newBoolean(true); } -Local ParticleSpawner::drawNumber(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - Vec3 pos; - int dimId; - GETVEC3(pos, dimId, args[0]) - std::string numName; - std::string color = "W"; - if (args.size() > 2) { - CHECK_ARG_TYPE(args[2], ValueKind::kString); - color = args[2].asString().toString(); - } - if (args[1].getKind() == ValueKind::kNumber) { - numName = std::to_string(args[1].asNumber().toInt64()); - } else if (args[1].getKind() == ValueKind::kString) { - numName = args[1].asString().toString(); - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - ParticleCUI::spawnParticle(pos, std::string("ll:num") + numName + color, - dimId); - return Boolean::newBoolean(true); +Local ParticleSpawner::drawNumber(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + Vec3 pos; + int dimId; + GETVEC3(pos, dimId, args[0]) + std::string numName; + std::string color = "W"; + if (args.size() > 2) { + CHECK_ARG_TYPE(args[2], ValueKind::kString); + color = args[2].asString().toString(); + } + if (args[1].getKind() == ValueKind::kNumber) { + numName = std::to_string(args[1].asNumber().toInt64()); + } else if (args[1].getKind() == ValueKind::kString) { + numName = args[1].asString().toString(); + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + ParticleCUI::spawnParticle(pos, std::string("ll:num") + numName + color, dimId); + return Boolean::newBoolean(true); } -Local ParticleSpawner::drawAxialLine(const Arguments &args) { - CHECK_ARGS_COUNT(args, 3); - Vec3 pos; - int dimId; - ParticleCUI::Direction direction; - double length; - GETVEC3(pos, dimId, args[0]) - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - direction = static_cast(args[1].asNumber().toInt32()); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - length = args[2].asNumber().toDouble(); - std::string color = "W"; - if (args.size() > 3) { - CHECK_ARG_TYPE(args[3], ValueKind::kString); - color = args[3].asString().toString(); - } - ParticleCUI::drawAxialLine(pos, direction, length, dimId, - getColorType(color)); - return Boolean::newBoolean(true); +Local ParticleSpawner::drawAxialLine(const Arguments& args) { + CHECK_ARGS_COUNT(args, 3); + Vec3 pos; + int dimId; + ParticleCUI::Direction direction; + double length; + GETVEC3(pos, dimId, args[0]) + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + direction = static_cast(args[1].asNumber().toInt32()); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + length = args[2].asNumber().toDouble(); + std::string color = "W"; + if (args.size() > 3) { + CHECK_ARG_TYPE(args[3], ValueKind::kString); + color = args[3].asString().toString(); + } + ParticleCUI::drawAxialLine(pos, direction, length, dimId, getColorType(color)); + return Boolean::newBoolean(true); } -Local ParticleSpawner::drawOrientedLine(const Arguments &args) { - auto size = args.size(); - CHECK_ARGS_COUNT(args, 2); - Vec3 start; - Vec3 end; - int dimId1; - int dimId2; - auto lineWidth = ParticleCUI::PointSize::PX4; - double minSpacing = 1; - int maxParticlesNum = 64; - GETVEC3(start, dimId1, args[0]) - GETVEC3(end, dimId2, args[1]) - if (dimId1 != dimId2) { - LOG_ERROR_WITH_SCRIPT_INFO("Pos should in the same dimension!"); - return Local(); - } +Local ParticleSpawner::drawOrientedLine(const Arguments& args) { + auto size = args.size(); + CHECK_ARGS_COUNT(args, 2); + Vec3 start; + Vec3 end; + int dimId1; + int dimId2; + auto lineWidth = ParticleCUI::PointSize::PX4; + double minSpacing = 1; + int maxParticlesNum = 64; + GETVEC3(start, dimId1, args[0]) + GETVEC3(end, dimId2, args[1]) + if (dimId1 != dimId2) { + LOG_ERROR_WITH_SCRIPT_INFO("Pos should in the same dimension!"); + return Local(); + } - if (size > 2) { - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - lineWidth = - static_cast(args[2].asNumber().toInt32()); - } + if (size > 2) { + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + lineWidth = static_cast(args[2].asNumber().toInt32()); + } - if (size > 3) { - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - minSpacing = args[3].asNumber().toDouble(); - } + if (size > 3) { + CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + minSpacing = args[3].asNumber().toDouble(); + } - if (size > 4) { - CHECK_ARG_TYPE(args[4], ValueKind::kNumber); - maxParticlesNum = args[4].asNumber().toInt32(); - } + if (size > 4) { + CHECK_ARG_TYPE(args[4], ValueKind::kNumber); + maxParticlesNum = args[4].asNumber().toInt32(); + } - std::string color = "W"; - if (args.size() > 5) { - CHECK_ARG_TYPE(args[5], ValueKind::kString); - color = args[5].asString().toString(); - } + std::string color = "W"; + if (args.size() > 5) { + CHECK_ARG_TYPE(args[5], ValueKind::kString); + color = args[5].asString().toString(); + } - ParticleCUI::drawOrientedLine(start, end, dimId1, lineWidth, minSpacing, - maxParticlesNum, getColorType(color)); + ParticleCUI::drawOrientedLine(start, end, dimId1, lineWidth, minSpacing, maxParticlesNum, getColorType(color)); - return Boolean::newBoolean(true); + return Boolean::newBoolean(true); } -Local ParticleSpawner::drawCuboid(const Arguments &args) { - auto size = args.size(); - CHECK_ARGS_COUNT(args, 1); - Vec3 min; - Vec3 max; - int dimId1; - int dimId2 = -1; - std::string color = "W"; +Local ParticleSpawner::drawCuboid(const Arguments& args) { + auto size = args.size(); + CHECK_ARGS_COUNT(args, 1); + Vec3 min; + Vec3 max; + int dimId1; + int dimId2 = -1; + std::string color = "W"; - if (IsInstanceOf(args[0])) { - auto pos2 = - EngineScope::currentEngine()->getNativeInstance(args[0]); - min = Vec3(pos2->x, pos2->y, pos2->z); - dimId1 = pos2->dim; - } else if (IsInstanceOf(args[0])) { - auto pos2 = - EngineScope::currentEngine()->getNativeInstance(args[0]); - min = Vec3(pos2->x, pos2->y, pos2->z); - dimId1 = pos2->dim; - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - if (size > 1) { - if (IsInstanceOf(args[1])) { - auto pos2 = - EngineScope::currentEngine()->getNativeInstance(args[1]); - max = Vec3(pos2->x, pos2->y, pos2->z) + 1; - dimId2 = pos2->dim; - } else if (IsInstanceOf(args[1])) { - auto pos2 = - EngineScope::currentEngine()->getNativeInstance(args[1]); - max = Vec3(pos2->x, pos2->y, pos2->z); - dimId2 = pos2->dim; + if (IsInstanceOf(args[0])) { + auto pos2 = EngineScope::currentEngine()->getNativeInstance(args[0]); + min = Vec3(pos2->x, pos2->y, pos2->z); + dimId1 = pos2->dim; + } else if (IsInstanceOf(args[0])) { + auto pos2 = EngineScope::currentEngine()->getNativeInstance(args[0]); + min = Vec3(pos2->x, pos2->y, pos2->z); + dimId1 = pos2->dim; + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + if (size > 1) { + if (IsInstanceOf(args[1])) { + auto pos2 = EngineScope::currentEngine()->getNativeInstance(args[1]); + max = Vec3(pos2->x, pos2->y, pos2->z) + 1; + dimId2 = pos2->dim; + } else if (IsInstanceOf(args[1])) { + auto pos2 = EngineScope::currentEngine()->getNativeInstance(args[1]); + max = Vec3(pos2->x, pos2->y, pos2->z); + dimId2 = pos2->dim; + } else { + max = min + 1; + CHECK_ARG_TYPE(args[1], ValueKind::kString); + color = args[1].asString().toString(); + } } else { - max = min + 1; - CHECK_ARG_TYPE(args[1], ValueKind::kString); - color = args[1].asString().toString(); + max = min + 1; } - } else { - max = min + 1; - } - if (dimId2 != -1 && dimId1 != dimId2) { - LOG_ERROR_WITH_SCRIPT_INFO("Pos should in the same dimension!"); - return Local(); - } + if (dimId2 != -1 && dimId1 != dimId2) { + LOG_ERROR_WITH_SCRIPT_INFO("Pos should in the same dimension!"); + return Local(); + } - if (size > 2) { - CHECK_ARG_TYPE(args[2], ValueKind::kString); - color = args[2].asString().toString(); - } + if (size > 2) { + CHECK_ARG_TYPE(args[2], ValueKind::kString); + color = args[2].asString().toString(); + } - ParticleCUI::drawCuboid(AABB(min, max), dimId1, getColorType(color)); + ParticleCUI::drawCuboid(AABB(min, max), dimId1, getColorType(color)); - return Boolean::newBoolean(true); + return Boolean::newBoolean(true); } -Local ParticleSpawner::drawCircle(const Arguments &args) { - auto size = args.size(); - CHECK_ARGS_COUNT(args, 3); - Vec3 pos; - int dimId; - ParticleCUI::Direction facing; - double radius; - GETVEC3(pos, dimId, args[0]) - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - facing = static_cast(args[1].asNumber().toInt32()); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - radius = args[2].asNumber().toDouble(); +Local ParticleSpawner::drawCircle(const Arguments& args) { + auto size = args.size(); + CHECK_ARGS_COUNT(args, 3); + Vec3 pos; + int dimId; + ParticleCUI::Direction facing; + double radius; + GETVEC3(pos, dimId, args[0]) + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + facing = static_cast(args[1].asNumber().toInt32()); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + radius = args[2].asNumber().toDouble(); - auto lineWidth = ParticleCUI::PointSize::PX4; - double minSpacing = 1; - int maxParticlesNum = 64; + auto lineWidth = ParticleCUI::PointSize::PX4; + double minSpacing = 1; + int maxParticlesNum = 64; - if (size > 3) { - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - lineWidth = - static_cast(args[3].asNumber().toInt32()); - } + if (size > 3) { + CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + lineWidth = static_cast(args[3].asNumber().toInt32()); + } - if (size > 4) { - CHECK_ARG_TYPE(args[4], ValueKind::kNumber); - minSpacing = args[4].asNumber().toDouble(); - } + if (size > 4) { + CHECK_ARG_TYPE(args[4], ValueKind::kNumber); + minSpacing = args[4].asNumber().toDouble(); + } - if (size > 5) { - CHECK_ARG_TYPE(args[5], ValueKind::kNumber); - maxParticlesNum = args[5].asNumber().toInt32(); - } + if (size > 5) { + CHECK_ARG_TYPE(args[5], ValueKind::kNumber); + maxParticlesNum = args[5].asNumber().toInt32(); + } - std::string color = "W"; - if (args.size() > 6) { - CHECK_ARG_TYPE(args[6], ValueKind::kString); - color = args[6].asString().toString(); - } + std::string color = "W"; + if (args.size() > 6) { + CHECK_ARG_TYPE(args[6], ValueKind::kString); + color = args[6].asString().toString(); + } - ParticleCUI::drawCircle(pos, facing, radius, dimId, lineWidth, minSpacing, - maxParticlesNum, getColorType(color)); + ParticleCUI::drawCircle(pos, facing, radius, dimId, lineWidth, minSpacing, maxParticlesNum, getColorType(color)); - return Boolean::newBoolean(true); + return Boolean::newBoolean(true); } ClassDefine ParticleSpawnerBuilder = defineClass("ParticleSpawner") .constructor(&ParticleSpawner::create) - .instanceProperty("displayRadius", &ParticleSpawner::getDisplayRadius, - &ParticleSpawner::setDisplayRadius) - .instanceProperty("highDetial", &ParticleSpawner::getHighDetial, - &ParticleSpawner::setHighDetial) - .instanceProperty("doubleSide", &ParticleSpawner::getDoubleSide, - &ParticleSpawner::setDoubleSide) + .instanceProperty("displayRadius", &ParticleSpawner::getDisplayRadius, &ParticleSpawner::setDisplayRadius) + .instanceProperty("highDetial", &ParticleSpawner::getHighDetial, &ParticleSpawner::setHighDetial) + .instanceProperty("doubleSide", &ParticleSpawner::getDoubleSide, &ParticleSpawner::setDoubleSide) .instanceFunction("spawnParticle", &ParticleSpawner::spawnParticle) .instanceFunction("drawPoint", &ParticleSpawner::drawPoint) .instanceFunction("drawNumber", &ParticleSpawner::drawNumber) .instanceFunction("drawAxialLine", &ParticleSpawner::drawAxialLine) - .instanceFunction("drawOrientedLine", - &ParticleSpawner::drawOrientedLine) + .instanceFunction("drawOrientedLine", &ParticleSpawner::drawOrientedLine) .instanceFunction("drawCuboid", &ParticleSpawner::drawCuboid) .instanceFunction("drawCircle", &ParticleSpawner::drawCircle) .build(); diff --git a/src/api/ParticleAPI.h b/src/api/ParticleAPI.h index abae35a1..8233dfab 100644 --- a/src/api/ParticleAPI.h +++ b/src/api/ParticleAPI.h @@ -7,36 +7,27 @@ class ParticleSpawner : public ParticleCUI, public ScriptClass { public: - explicit ParticleSpawner(const Local &scriptObj) - : ScriptClass(scriptObj), ParticleCUI() {} + explicit ParticleSpawner(const Local& scriptObj) : ScriptClass(scriptObj), ParticleCUI() {} - static ParticleSpawner *create(const Arguments &args); + static ParticleSpawner* create(const Arguments& args); - Local getDisplayRadius() { - return Number::newNumber(static_cast(displayRadius)); - } - Local getHighDetial() { return Boolean::newBoolean(highDetial); } - Local getDoubleSide() { return Boolean::newBoolean(doubleSide); } - void setDisplayRadius(const Local &value) { - displayRadius = value.asNumber().toInt64(); - } - void setHighDetial(const Local &value) { - highDetial = value.asBoolean().value(); - } - void setDoubleSide(const Local &value) { - doubleSide = value.asBoolean().value(); - } + Local getDisplayRadius() { return Number::newNumber(static_cast(displayRadius)); } + Local getHighDetial() { return Boolean::newBoolean(highDetial); } + Local getDoubleSide() { return Boolean::newBoolean(doubleSide); } + void setDisplayRadius(const Local& value) { displayRadius = value.asNumber().toInt64(); } + void setHighDetial(const Local& value) { highDetial = value.asBoolean().value(); } + void setDoubleSide(const Local& value) { doubleSide = value.asBoolean().value(); } - Local spawnParticle(const Arguments &args); + Local spawnParticle(const Arguments& args); - Local drawPoint(const Arguments &args); - Local drawNumber(const Arguments &args); - Local drawAxialLine(const Arguments &args); - Local drawOrientedLine(const Arguments &args); - Local drawCuboid(const Arguments &args); - Local drawCircle(const Arguments &args); + Local drawPoint(const Arguments& args); + Local drawNumber(const Arguments& args); + Local drawAxialLine(const Arguments& args); + Local drawOrientedLine(const Arguments& args); + Local drawCuboid(const Arguments& args); + Local drawCircle(const Arguments& args); }; extern ClassDefine ParticleSpawnerBuilder; -extern ClassDefine ParticleColorBuilder; -extern ClassDefine DirectionBuilder; +extern ClassDefine ParticleColorBuilder; +extern ClassDefine DirectionBuilder; diff --git a/src/api/PlayerAPI.cpp b/src/api/PlayerAPI.cpp index 2048fdf6..ebba4acf 100644 --- a/src/api/PlayerAPI.cpp +++ b/src/api/PlayerAPI.cpp @@ -114,8 +114,7 @@ ClassDefine PlayerClassBuilder = .instanceProperty("canFreeze", &PlayerClass::getCanFreeze) .instanceProperty("canSeeDaylight", &PlayerClass::getCanSeeDaylight) .instanceProperty("canShowNameTag", &PlayerClass::getCanShowNameTag) - .instanceProperty("canStartSleepInBed", - &PlayerClass::getCanStartSleepInBed) + .instanceProperty("canStartSleepInBed", &PlayerClass::getCanStartSleepInBed) .instanceProperty("canPickupItems", &PlayerClass::getCanPickupItems) .instanceProperty("maxHealth", &PlayerClass::getMaxHealth) .instanceProperty("health", &PlayerClass::getHealth) @@ -137,8 +136,7 @@ ClassDefine PlayerClassBuilder = .instanceProperty("isInsidePortal", &PlayerClass::isInsidePortal) .instanceProperty("isHurt", &PlayerClass::isHurt) .instanceProperty("isTrusting", &PlayerClass::isTrusting) - .instanceProperty("isTouchingDamageBlock", - &PlayerClass::isTouchingDamageBlock) + .instanceProperty("isTouchingDamageBlock", &PlayerClass::isTouchingDamageBlock) .instanceProperty("isHungry", &PlayerClass::isHungry) .instanceProperty("isOnFire", &PlayerClass::isOnFire) .instanceProperty("isOnGround", &PlayerClass::isOnGround) @@ -180,17 +178,13 @@ ClassDefine PlayerClassBuilder = .instanceFunction("setMaxHealth", &PlayerClass::setMaxHealth) .instanceFunction("setAbsorption", &PlayerClass::setAbsorption) .instanceFunction("setAttackDamage", &PlayerClass::setAttackDamage) - .instanceFunction("setMaxAttackDamage", - &PlayerClass::setMaxAttackDamage) + .instanceFunction("setMaxAttackDamage", &PlayerClass::setMaxAttackDamage) .instanceFunction("setFollowRange", &PlayerClass::setFollowRange) - .instanceFunction("setKnockbackResistance", - &PlayerClass::setKnockbackResistance) + .instanceFunction("setKnockbackResistance", &PlayerClass::setKnockbackResistance) .instanceFunction("setLuck", &PlayerClass::setLuck) .instanceFunction("setMovementSpeed", &PlayerClass::setMovementSpeed) - .instanceFunction("setUnderwaterMovementSpeed", - &PlayerClass::setUnderwaterMovementSpeed) - .instanceFunction("setLavaMovementSpeed", - &PlayerClass::setLavaMovementSpeed) + .instanceFunction("setUnderwaterMovementSpeed", &PlayerClass::setUnderwaterMovementSpeed) + .instanceFunction("setLavaMovementSpeed", &PlayerClass::setLavaMovementSpeed) .instanceFunction("setHungry", &PlayerClass::setHungry) .instanceFunction("refreshChunks", &PlayerClass::refreshChunks) .instanceFunction("giveItem", &PlayerClass::giveItem) @@ -201,18 +195,15 @@ ClassDefine PlayerClassBuilder = .instanceFunction("distanceTo", &PlayerClass::distanceTo) .instanceFunction("distanceToSqr", &PlayerClass::distanceToSqr) - .instanceFunction("getBlockStandingOn", - &PlayerClass::getBlockStandingOn) + .instanceFunction("getBlockStandingOn", &PlayerClass::getBlockStandingOn) .instanceFunction("getDevice", &PlayerClass::getDevice) .instanceFunction("getHand", &PlayerClass::getHand) .instanceFunction("getOffHand", &PlayerClass::getOffHand) .instanceFunction("getInventory", &PlayerClass::getInventory) .instanceFunction("getArmor", &PlayerClass::getArmor) .instanceFunction("getEnderChest", &PlayerClass::getEnderChest) - .instanceFunction("getRespawnPosition", - &PlayerClass::getRespawnPosition) - .instanceFunction("setRespawnPosition", - &PlayerClass::setRespawnPosition) + .instanceFunction("getRespawnPosition", &PlayerClass::getRespawnPosition) + .instanceFunction("setRespawnPosition", &PlayerClass::setRespawnPosition) .instanceFunction("refreshItems", &PlayerClass::refreshItems) .instanceFunction("getScore", &PlayerClass::getScore) @@ -232,16 +223,11 @@ ClassDefine PlayerClassBuilder = .instanceFunction("resetLevel", &PlayerClass::resetLevel) .instanceFunction("addExperience", &PlayerClass::addExperience) .instanceFunction("reduceExperience", &PlayerClass::reduceExperience) - .instanceFunction("getCurrentExperience", - &PlayerClass::getCurrentExperience) - .instanceFunction("setCurrentExperience", - &PlayerClass::setCurrentExperience) - .instanceFunction("getTotalExperience", - &PlayerClass::getTotalExperience) - .instanceFunction("setTotalExperience", - &PlayerClass::setTotalExperience) - .instanceFunction("getXpNeededForNextLevel", - &PlayerClass::getXpNeededForNextLevel) + .instanceFunction("getCurrentExperience", &PlayerClass::getCurrentExperience) + .instanceFunction("setCurrentExperience", &PlayerClass::setCurrentExperience) + .instanceFunction("getTotalExperience", &PlayerClass::getTotalExperience) + .instanceFunction("setTotalExperience", &PlayerClass::setTotalExperience) + .instanceFunction("getXpNeededForNextLevel", &PlayerClass::getXpNeededForNextLevel) .instanceFunction("setAbility", &PlayerClass::setAbility) .instanceFunction("getBiomeId", &PlayerClass::getBiomeId) .instanceFunction("getBiomeName", &PlayerClass::getBiomeName) @@ -268,12 +254,9 @@ ClassDefine PlayerClassBuilder = .instanceFunction("getAllTags", &PlayerClass::getAllTags) .instanceFunction("getAbilities", &PlayerClass::getAbilities) .instanceFunction("getAttributes", &PlayerClass::getAttributes) - .instanceFunction("getEntityFromViewVector", - &PlayerClass::getEntityFromViewVector) - .instanceFunction("getBlockFromViewVector", - &PlayerClass::getBlockFromViewVector) - .instanceFunction("quickEvalMolangScript", - &PlayerClass::quickEvalMolangScript) + .instanceFunction("getEntityFromViewVector", &PlayerClass::getEntityFromViewVector) + .instanceFunction("getBlockFromViewVector", &PlayerClass::getBlockFromViewVector) + .instanceFunction("quickEvalMolangScript", &PlayerClass::quickEvalMolangScript) // LLMoney .instanceFunction("getMoney", &PlayerClass::getMoney) @@ -288,8 +271,7 @@ ClassDefine PlayerClassBuilder = .instanceFunction("simulateSneak", &PlayerClass::simulateSneak) .instanceFunction("simulateAttack", &PlayerClass::simulateAttack) .instanceFunction("simulateDestroy", &PlayerClass::simulateDestroy) - .instanceFunction("simulateDisconnect", - &PlayerClass::simulateDisconnect) + .instanceFunction("simulateDisconnect", &PlayerClass::simulateDisconnect) .instanceFunction("simulateInteract", &PlayerClass::simulateInteract) .instanceFunction("simulateRespawn", &PlayerClass::simulateRespawn) .instanceFunction("simulateJump", &PlayerClass::simulateJump) @@ -297,21 +279,14 @@ ClassDefine PlayerClassBuilder = .instanceFunction("simulateWorldMove", &PlayerClass::simulateWorldMove) .instanceFunction("simulateMoveTo", &PlayerClass::simulateMoveTo) .instanceFunction("simulateLookAt", &PlayerClass::simulateLookAt) - .instanceFunction("simulateSetBodyRotation", - &PlayerClass::simulateSetBodyRotation) - .instanceFunction("simulateNavigateTo", - &PlayerClass::simulateNavigateTo) + .instanceFunction("simulateSetBodyRotation", &PlayerClass::simulateSetBodyRotation) + .instanceFunction("simulateNavigateTo", &PlayerClass::simulateNavigateTo) .instanceFunction("simulateUseItem", &PlayerClass::simulateUseItem) - .instanceFunction("simulateStopDestroyingBlock", - &PlayerClass::simulateStopDestroyingBlock) - .instanceFunction("simulateStopInteracting", - &PlayerClass::simulateStopInteracting) - .instanceFunction("simulateStopMoving", - &PlayerClass::simulateStopMoving) - .instanceFunction("simulateStopUsingItem", - &PlayerClass::simulateStopUsingItem) - .instanceFunction("simulateStopSneaking", - &PlayerClass::simulateStopSneaking) + .instanceFunction("simulateStopDestroyingBlock", &PlayerClass::simulateStopDestroyingBlock) + .instanceFunction("simulateStopInteracting", &PlayerClass::simulateStopInteracting) + .instanceFunction("simulateStopMoving", &PlayerClass::simulateStopMoving) + .instanceFunction("simulateStopUsingItem", &PlayerClass::simulateStopUsingItem) + .instanceFunction("simulateStopSneaking", &PlayerClass::simulateStopSneaking) // For Compatibility .instanceProperty("sneaking", &PlayerClass::isSneaking) @@ -328,3350 +303,3123 @@ ClassDefine PlayerClassBuilder = //////////////////// Classes //////////////////// // 生成函数 -PlayerClass::PlayerClass(Player *p) - : ScriptClass(ScriptClass::ConstructFromCpp{}) { - set(p); -} +PlayerClass::PlayerClass(Player* p) : ScriptClass(ScriptClass::ConstructFromCpp{}) { set(p); } -Local PlayerClass::newPlayer(Player *p) { - auto newp = new PlayerClass(p); - return newp->getScriptObject(); +Local PlayerClass::newPlayer(Player* p) { + auto newp = new PlayerClass(p); + return newp->getScriptObject(); } -Player *PlayerClass::extract(Local v) { - if (EngineScope::currentEngine()->isInstanceOf(v)) - return EngineScope::currentEngine() - ->getNativeInstance(v) - ->get(); - else - return nullptr; +Player* PlayerClass::extract(Local v) { + if (EngineScope::currentEngine()->isInstanceOf(v)) + return EngineScope::currentEngine()->getNativeInstance(v)->get(); + else return nullptr; } // 公用API -Local McClass::getPlayerNbt(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - auto uuid = mce::UUID::fromString(args[0].asString().toString()); - CompoundTag tag; - Player *pl = ll::service::getLevel()->getPlayer(uuid); - if (pl) { - pl->save(tag); - } - // else { - // std::string serverId = pl->getServerId(); - // if (!serverId.empty()) { - // if (MoreGlobal::getDBStorage()->hasKey(serverId, - // DBHelpers::Category::Player)) - // { - // tag = MoreGlobal::getDBStorage()->getCompoundTag( - // serverId, DBHelpers::Category::Player); - // } - // } - // } - if (!tag.isEmpty()) { - return NbtCompoundClass::pack(&tag); - } else { - return Local(); - } - } - CATCH("Fail in getPlayerNbt!") -} - -Local McClass::setPlayerNbt(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - auto uuid = mce::UUID::fromString(args[0].asString().toString()); - auto tag = NbtCompoundClass::extract(args[1]); - Player *pl = ll::service::getLevel()->getPlayer(uuid); - if (pl) { - pl->load(*tag, ll::defaultDataLoadHelper); - } - return Boolean::newBoolean(true); - } - CATCH("Fail in setPlayerNbt!") -} - -Local McClass::setPlayerNbtTags(const Arguments &args) { - CHECK_ARGS_COUNT(args, 3); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[2], ValueKind::kArray); - try { - auto uuid = mce::UUID::fromString(args[0].asString().toString()); - auto nbt = NbtCompoundClass::extract(args[1]); - auto arr = args[2].asArray(); - std::vector tags; - for (int i = 0; i < arr.size(); ++i) { - auto value = arr.get(i); - if (value.getKind() == ValueKind::kString) { - tags.push_back(value.asString().toString()); - } - } - ll::service::getLevel()->getPlayer(uuid)->load(*nbt); - return Boolean::newBoolean(true); - } - CATCH("Fail in setPlayerNbtTags!") -} - -Local McClass::deletePlayerNbt(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - auto uuid = mce::UUID::fromString(args[0].asString().toString()); - ll::service::getLevel()->getLevelStorage().deleteData( - "player_" + uuid.asString(), DBHelpers::Category::Player); - return Boolean::newBoolean(true); - } - CATCH("Fail in deletePlayerNbt!") -} - -Local McClass::getPlayerScore(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - try { - auto obj = args[1].asString().toString(); - Scoreboard &board = ll::service::getLevel()->getScoreboard(); - Objective *objective = board.getObjective(obj); - ScoreboardId sid = board.getScoreboardId( - PlayerScoreboardId(std::atoll(args[0].asString().toString().c_str()))); - if (!objective || !sid.isValid() || !objective->hasScore(sid)) { - return {}; - } - return Number::newNumber(objective->getPlayerScore(sid).mScore); - } - CATCH("Fail in getPlayerScore!") -} - -Local McClass::setPlayerScore(const Arguments &args) { - CHECK_ARGS_COUNT(args, 3); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - try { - auto uuid = mce::UUID::fromString(args[0].asString().toString()); - Scoreboard &scoreboard = ll::service::getLevel()->getScoreboard(); - Objective *objective = - scoreboard.getObjective(args[1].asString().toString()); - if (!objective) { - return Boolean::newBoolean(false); - } - const ScoreboardId &id = scoreboard.getScoreboardId( - PlayerScoreboardId(std::atoll(args[0].asString().toString().c_str()))); - if (!id.isValid()) { - Player *pl = ll::service::getLevel()->getPlayer(uuid); - if (pl) { - scoreboard.createScoreboardId(*pl); - } else { - return Boolean::newBoolean(false); - } - } - bool isSuccess = false; - scoreboard.modifyPlayerScore(isSuccess, id, *objective, - args[2].asNumber().toInt32(), - PlayerScoreSetFunction::Set); - return Boolean::newBoolean(isSuccess); - } - CATCH("Fail in setPlayerScore!") -} - -Local McClass::addPlayerScore(const Arguments &args) { - CHECK_ARGS_COUNT(args, 3); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - try { - auto uuid = mce::UUID::fromString(args[0].asString().toString()); - Scoreboard &scoreboard = ll::service::getLevel()->getScoreboard(); - Objective *objective = - scoreboard.getObjective(args[1].asString().toString()); - if (!objective) { - return Boolean::newBoolean(false); - } - const ScoreboardId &id = scoreboard.getScoreboardId( - PlayerScoreboardId(std::atoll(args[0].asString().toString().c_str()))); - if (!id.isValid()) { - Player *pl = ll::service::getLevel()->getPlayer(uuid); - if (pl) { - scoreboard.createScoreboardId(*pl); - } else { - return Boolean::newBoolean(false); - } - } - bool isSuccess = false; - scoreboard.modifyPlayerScore(isSuccess, id, *objective, - args[2].asNumber().toInt32(), - PlayerScoreSetFunction::Add); - return Boolean::newBoolean(isSuccess); - } - CATCH("Fail in addPlayerScore!") -} - -Local McClass::reducePlayerScore(const Arguments &args) { - CHECK_ARGS_COUNT(args, 3); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - try { - auto uuid = mce::UUID::fromString(args[0].asString().toString()); - Scoreboard &scoreboard = ll::service::getLevel()->getScoreboard(); - Objective *objective = - scoreboard.getObjective(args[1].asString().toString()); - if (!objective) { - return Boolean::newBoolean(false); - } - const ScoreboardId &id = scoreboard.getScoreboardId( - PlayerScoreboardId(std::atoll(args[0].asString().toString().c_str()))); - if (!id.isValid()) { - Player *pl = ll::service::getLevel()->getPlayer(uuid); - if (pl) { - scoreboard.createScoreboardId(*pl); - } else { - return Boolean::newBoolean(false); - } - } - bool isSuccess = false; - scoreboard.modifyPlayerScore(isSuccess, id, *objective, - args[2].asNumber().toInt32(), - PlayerScoreSetFunction::Subtract); - return Boolean::newBoolean(isSuccess); - } - CATCH("Fail in reducePlayerScore!") -} - -Local McClass::deletePlayerScore(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - try { - Scoreboard &scoreboard = ll::service::getLevel()->getScoreboard(); - Objective *objective = - scoreboard.getObjective(args[1].asString().toString()); - if (!objective) { - return Boolean::newBoolean(false); - } - const ScoreboardId &id = scoreboard.getScoreboardId( - PlayerScoreboardId(std::atoll(args[0].asString().toString().c_str()))); - if (!id.isValid()) { - return Boolean::newBoolean(true); - } - return Boolean::newBoolean( - scoreboard.getScoreboardIdentityRef(id)->removeFromObjective( - scoreboard, *objective)); - } - CATCH("Fail in deletePlayerScore!") -} - -Local McClass::getPlayer(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - CHECK_ARG_TYPE(args[0], ValueKind::kString) - - try { - string target = args[0].toStr(); - if (target.empty()) - return Local(); - - transform(target.begin(), target.end(), target.begin(), - ::tolower); // lower case the string - std::vector playerList; - int delta = 2147483647; // c++ int max - Player *found = nullptr; - ll::service::getLevel()->forEachPlayer([&](Player &player) { - playerList.push_back(&player); - return true; - }); - - for (Player *p : playerList) { - if (p->getXuid() == target || - std::to_string(p->getOrCreateUniqueID().id) == target) - return PlayerClass::newPlayer(p); - - string pName = p->getName(); - transform(pName.begin(), pName.end(), pName.begin(), ::tolower); - - if (pName.find(target) == 0) { - // 0 ís the index where the "target" appear in "pName" - int curDelta = pName.length() - target.length(); - if (curDelta == 0) - return PlayerClass::newPlayer(p); - - if (curDelta < delta) { - found = p; - delta = curDelta; - } - } - } - return found ? PlayerClass::newPlayer(found) - : Local(); // Player/Null - } - CATCH("Fail in GetPlayer!") -} - -Local McClass::getOnlinePlayers(const Arguments &args) { - try { - Local list = Array::newArray(); - ll::service::getLevel()->forEachPlayer([&](Player &player) { - list.add(PlayerClass::newPlayer(&player)); - return true; - }); - return list; - } - CATCH("Fail in GetOnlinePlayers!") -} - -Local McClass::broadcast(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - CHECK_ARG_TYPE(args[0], ValueKind::kString) - - try { - TextPacketType type = TextPacketType::Raw; - if (args.size() >= 2 && args[1].isNumber()) { - int newType = args[1].asNumber().toInt32(); - if (newType >= 0 && newType <= 11) - type = (TextPacketType)newType; - } - TextPacket pkt = TextPacket(); - pkt.mType = type; - pkt.mMessage = args[0].asString().toString(); - pkt.sendToClients(); - return Boolean::newBoolean(true); - } - CATCH("Fail in Broadcast!") +Local McClass::getPlayerNbt(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + try { + auto uuid = mce::UUID::fromString(args[0].asString().toString()); + CompoundTag tag; + Player* pl = ll::service::getLevel()->getPlayer(uuid); + if (pl) { + pl->save(tag); + } + // else { + // std::string serverId = pl->getServerId(); + // if (!serverId.empty()) { + // if (MoreGlobal::getDBStorage()->hasKey(serverId, + // DBHelpers::Category::Player)) + // { + // tag = MoreGlobal::getDBStorage()->getCompoundTag( + // serverId, DBHelpers::Category::Player); + // } + // } + // } + if (!tag.isEmpty()) { + return NbtCompoundClass::pack(&tag); + } else { + return Local(); + } + } + CATCH("Fail in getPlayerNbt!") +} + +Local McClass::setPlayerNbt(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + try { + auto uuid = mce::UUID::fromString(args[0].asString().toString()); + auto tag = NbtCompoundClass::extract(args[1]); + Player* pl = ll::service::getLevel()->getPlayer(uuid); + if (pl) { + pl->load(*tag, ll::defaultDataLoadHelper); + } + return Boolean::newBoolean(true); + } + CATCH("Fail in setPlayerNbt!") +} + +Local McClass::setPlayerNbtTags(const Arguments& args) { + CHECK_ARGS_COUNT(args, 3); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[2], ValueKind::kArray); + try { + auto uuid = mce::UUID::fromString(args[0].asString().toString()); + auto nbt = NbtCompoundClass::extract(args[1]); + auto arr = args[2].asArray(); + std::vector tags; + for (int i = 0; i < arr.size(); ++i) { + auto value = arr.get(i); + if (value.getKind() == ValueKind::kString) { + tags.push_back(value.asString().toString()); + } + } + ll::service::getLevel()->getPlayer(uuid)->load(*nbt); + return Boolean::newBoolean(true); + } + CATCH("Fail in setPlayerNbtTags!") +} + +Local McClass::deletePlayerNbt(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + try { + auto uuid = mce::UUID::fromString(args[0].asString().toString()); + ll::service::getLevel()->getLevelStorage().deleteData("player_" + uuid.asString(), DBHelpers::Category::Player); + return Boolean::newBoolean(true); + } + CATCH("Fail in deletePlayerNbt!") +} + +Local McClass::getPlayerScore(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + try { + auto obj = args[1].asString().toString(); + Scoreboard& board = ll::service::getLevel()->getScoreboard(); + Objective* objective = board.getObjective(obj); + ScoreboardId sid = board.getScoreboardId(PlayerScoreboardId(std::atoll(args[0].asString().toString().c_str()))); + if (!objective || !sid.isValid() || !objective->hasScore(sid)) { + return {}; + } + return Number::newNumber(objective->getPlayerScore(sid).mScore); + } + CATCH("Fail in getPlayerScore!") +} + +Local McClass::setPlayerScore(const Arguments& args) { + CHECK_ARGS_COUNT(args, 3); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + try { + auto uuid = mce::UUID::fromString(args[0].asString().toString()); + Scoreboard& scoreboard = ll::service::getLevel()->getScoreboard(); + Objective* objective = scoreboard.getObjective(args[1].asString().toString()); + if (!objective) { + return Boolean::newBoolean(false); + } + const ScoreboardId& id = + scoreboard.getScoreboardId(PlayerScoreboardId(std::atoll(args[0].asString().toString().c_str()))); + if (!id.isValid()) { + Player* pl = ll::service::getLevel()->getPlayer(uuid); + if (pl) { + scoreboard.createScoreboardId(*pl); + } else { + return Boolean::newBoolean(false); + } + } + bool isSuccess = false; + scoreboard + .modifyPlayerScore(isSuccess, id, *objective, args[2].asNumber().toInt32(), PlayerScoreSetFunction::Set); + return Boolean::newBoolean(isSuccess); + } + CATCH("Fail in setPlayerScore!") +} + +Local McClass::addPlayerScore(const Arguments& args) { + CHECK_ARGS_COUNT(args, 3); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + try { + auto uuid = mce::UUID::fromString(args[0].asString().toString()); + Scoreboard& scoreboard = ll::service::getLevel()->getScoreboard(); + Objective* objective = scoreboard.getObjective(args[1].asString().toString()); + if (!objective) { + return Boolean::newBoolean(false); + } + const ScoreboardId& id = + scoreboard.getScoreboardId(PlayerScoreboardId(std::atoll(args[0].asString().toString().c_str()))); + if (!id.isValid()) { + Player* pl = ll::service::getLevel()->getPlayer(uuid); + if (pl) { + scoreboard.createScoreboardId(*pl); + } else { + return Boolean::newBoolean(false); + } + } + bool isSuccess = false; + scoreboard + .modifyPlayerScore(isSuccess, id, *objective, args[2].asNumber().toInt32(), PlayerScoreSetFunction::Add); + return Boolean::newBoolean(isSuccess); + } + CATCH("Fail in addPlayerScore!") +} + +Local McClass::reducePlayerScore(const Arguments& args) { + CHECK_ARGS_COUNT(args, 3); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + try { + auto uuid = mce::UUID::fromString(args[0].asString().toString()); + Scoreboard& scoreboard = ll::service::getLevel()->getScoreboard(); + Objective* objective = scoreboard.getObjective(args[1].asString().toString()); + if (!objective) { + return Boolean::newBoolean(false); + } + const ScoreboardId& id = + scoreboard.getScoreboardId(PlayerScoreboardId(std::atoll(args[0].asString().toString().c_str()))); + if (!id.isValid()) { + Player* pl = ll::service::getLevel()->getPlayer(uuid); + if (pl) { + scoreboard.createScoreboardId(*pl); + } else { + return Boolean::newBoolean(false); + } + } + bool isSuccess = false; + scoreboard.modifyPlayerScore( + isSuccess, + id, + *objective, + args[2].asNumber().toInt32(), + PlayerScoreSetFunction::Subtract + ); + return Boolean::newBoolean(isSuccess); + } + CATCH("Fail in reducePlayerScore!") +} + +Local McClass::deletePlayerScore(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + try { + Scoreboard& scoreboard = ll::service::getLevel()->getScoreboard(); + Objective* objective = scoreboard.getObjective(args[1].asString().toString()); + if (!objective) { + return Boolean::newBoolean(false); + } + const ScoreboardId& id = + scoreboard.getScoreboardId(PlayerScoreboardId(std::atoll(args[0].asString().toString().c_str()))); + if (!id.isValid()) { + return Boolean::newBoolean(true); + } + return Boolean::newBoolean(scoreboard.getScoreboardIdentityRef(id)->removeFromObjective(scoreboard, *objective) + ); + } + CATCH("Fail in deletePlayerScore!") +} + +Local McClass::getPlayer(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + CHECK_ARG_TYPE(args[0], ValueKind::kString) + + try { + string target = args[0].toStr(); + if (target.empty()) return Local(); + + transform(target.begin(), target.end(), target.begin(), + ::tolower); // lower case the string + std::vector playerList; + int delta = 2147483647; // c++ int max + Player* found = nullptr; + ll::service::getLevel()->forEachPlayer([&](Player& player) { + playerList.push_back(&player); + return true; + }); + + for (Player* p : playerList) { + if (p->getXuid() == target || std::to_string(p->getOrCreateUniqueID().id) == target) + return PlayerClass::newPlayer(p); + + string pName = p->getName(); + transform(pName.begin(), pName.end(), pName.begin(), ::tolower); + + if (pName.find(target) == 0) { + // 0 ís the index where the "target" appear in "pName" + int curDelta = pName.length() - target.length(); + if (curDelta == 0) return PlayerClass::newPlayer(p); + + if (curDelta < delta) { + found = p; + delta = curDelta; + } + } + } + return found ? PlayerClass::newPlayer(found) : Local(); // Player/Null + } + CATCH("Fail in GetPlayer!") +} + +Local McClass::getOnlinePlayers(const Arguments& args) { + try { + Local list = Array::newArray(); + ll::service::getLevel()->forEachPlayer([&](Player& player) { + list.add(PlayerClass::newPlayer(&player)); + return true; + }); + return list; + } + CATCH("Fail in GetOnlinePlayers!") +} + +Local McClass::broadcast(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + CHECK_ARG_TYPE(args[0], ValueKind::kString) + + try { + TextPacketType type = TextPacketType::Raw; + if (args.size() >= 2 && args[1].isNumber()) { + int newType = args[1].asNumber().toInt32(); + if (newType >= 0 && newType <= 11) type = (TextPacketType)newType; + } + TextPacket pkt = TextPacket(); + pkt.mType = type; + pkt.mMessage = args[0].asString().toString(); + pkt.sendToClients(); + return Boolean::newBoolean(true); + } + CATCH("Fail in Broadcast!") } // 成员函数 -void PlayerClass::set(Player *player) { - __try { - id = player->getOrCreateUniqueID(); - } __except (EXCEPTION_EXECUTE_HANDLER) { - isValid = false; - } +void PlayerClass::set(Player* player) { + __try { + id = player->getOrCreateUniqueID(); + } __except (EXCEPTION_EXECUTE_HANDLER) { + isValid = false; + } } -Player *PlayerClass::get() { - if (!isValid) - return nullptr; - else - return ll::service::getLevel()->getPlayer(id); +Player* PlayerClass::get() { + if (!isValid) return nullptr; + else return ll::service::getLevel()->getPlayer(id); } Local PlayerClass::getName() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - return String::newString(player->getName()); - } - CATCH("Fail in getPlayerName!") + return String::newString(player->getName()); + } + CATCH("Fail in getPlayerName!") } Local PlayerClass::getPos() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - return FloatPos::newPos(player->getPosition(), player->getDimensionId()); - } - CATCH("Fail in getPlayerPos!") + return FloatPos::newPos(player->getPosition(), player->getDimensionId()); + } + CATCH("Fail in getPlayerPos!") } Local PlayerClass::getFeetPos() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - return FloatPos::newPos(player->getFeetPos(), player->getDimensionId()); - } - CATCH("Fail in getPlayerFeetPos!") + return FloatPos::newPos(player->getFeetPos(), player->getDimensionId()); + } + CATCH("Fail in getPlayerFeetPos!") } Local PlayerClass::getBlockPos() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - return IntPos::newPos(player->getFeetBlockPos(), player->getDimensionId()); - } - CATCH("Fail in getPlayerBlockPos!") + return IntPos::newPos(player->getFeetBlockPos(), player->getDimensionId()); + } + CATCH("Fail in getPlayerBlockPos!") } Local PlayerClass::getLastDeathPos() { - try { - Player *player = get(); - if (!player) { - return Local(); - } - auto pos = player->getLastDeathPos(); - auto dim = player->getLastDeathDimension(); - if (dim == -1) { - return Local(); + try { + Player* player = get(); + if (!player) { + return Local(); + } + auto pos = player->getLastDeathPos(); + auto dim = player->getLastDeathDimension(); + if (dim == -1) { + return Local(); + } + return IntPos::newPos(pos.value(), dim->id); } - return IntPos::newPos(pos.value(), dim->id); - } - CATCH("Fail in getLastDeathPos!") + CATCH("Fail in getLastDeathPos!") } Local PlayerClass::getXuid() { - try { - Player *player = get(); - if (!player) - return Local(); - - string xuid; try { - xuid = player->getXuid(); - } catch (...) { - logger.debug("Fail in getXuid!"); - xuid = ll::service::PlayerInfo::getInstance() - .fromName(player->getRealName()) - ->xuid; + Player* player = get(); + if (!player) return Local(); + + string xuid; + try { + xuid = player->getXuid(); + } catch (...) { + logger.debug("Fail in getXuid!"); + xuid = ll::service::PlayerInfo::getInstance().fromName(player->getRealName())->xuid; + } + return String::newString(xuid); } - return String::newString(xuid); - } - CATCH("Fail in getXuid!") + CATCH("Fail in getXuid!") } Local PlayerClass::getUuid() { - try { - Player *player = get(); - if (!player) - return Local(); - - string uuid; try { - uuid = player->getUuid().asString(); - } catch (...) { - logger.debug("Fail in getUuid!"); - uuid = ll::service::PlayerInfo::getInstance() - .fromName(player->getRealName()) - ->uuid.asString(); + Player* player = get(); + if (!player) return Local(); + + string uuid; + try { + uuid = player->getUuid().asString(); + } catch (...) { + logger.debug("Fail in getUuid!"); + uuid = ll::service::PlayerInfo::getInstance().fromName(player->getRealName())->uuid.asString(); + } + return String::newString(uuid); } - return String::newString(uuid); - } - CATCH("Fail in getUuid!") + CATCH("Fail in getUuid!") } Local PlayerClass::getRealName() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - return String::newString(player->getRealName()); - } - CATCH("Fail in getRealName!") + return String::newString(player->getRealName()); + } + CATCH("Fail in getRealName!") } Local PlayerClass::getIP() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - return String::newString(player->getNetworkIdentifier().getAddress()); - } - CATCH("Fail in GetIP!") + return String::newString(player->getNetworkIdentifier().getAddress()); + } + CATCH("Fail in GetIP!") } Local PlayerClass::getPermLevel() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - return Number::newNumber( - magic_enum::enum_integer(player->getCommandPermissionLevel())); - } - CATCH("Fail in getPlayerPermLevel!") + return Number::newNumber(magic_enum::enum_integer(player->getCommandPermissionLevel())); + } + CATCH("Fail in getPlayerPermLevel!") } Local PlayerClass::getGameMode() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - return Number::newNumber((int)player->getPlayerGameType()); //==========??? - } - CATCH("Fail in getGameMode!") + return Number::newNumber((int)player->getPlayerGameType()); //==========??? + } + CATCH("Fail in getGameMode!") } Local PlayerClass::getCanSleep() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - return Boolean::newBoolean(player->canSleep()); - } - CATCH("Fail in getCanSleep!") + return Boolean::newBoolean(player->canSleep()); + } + CATCH("Fail in getCanSleep!") } Local PlayerClass::getCanFly() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - return Boolean::newBoolean(player->canFly()); - } - CATCH("Fail in getCanFly!") + return Boolean::newBoolean(player->canFly()); + } + CATCH("Fail in getCanFly!") } Local PlayerClass::getCanBeSeenOnMap() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->canBeSeenOnMap()); - } - CATCH("Fail in getCanBeSeenOnMap!") + return Boolean::newBoolean(player->canBeSeenOnMap()); + } + CATCH("Fail in getCanBeSeenOnMap!") } Local PlayerClass::getCanFreeze() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->canFreeze()); - } - CATCH("Fail in getCanFreeze!") + return Boolean::newBoolean(player->canFreeze()); + } + CATCH("Fail in getCanFreeze!") } Local PlayerClass::getCanSeeDaylight() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->canSeeDaylight()); - } - CATCH("Fail in getCanSeeDaylight!") + return Boolean::newBoolean(player->canSeeDaylight()); + } + CATCH("Fail in getCanSeeDaylight!") } Local PlayerClass::getCanShowNameTag() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->canShowNameTag()); - } - CATCH("Fail in getCanShowNameTag!") + return Boolean::newBoolean(player->canShowNameTag()); + } + CATCH("Fail in getCanShowNameTag!") } Local PlayerClass::getCanStartSleepInBed() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->canStartSleepInBed()); - } - CATCH("Fail in getCanStartSleepInBed!") + return Boolean::newBoolean(player->canStartSleepInBed()); + } + CATCH("Fail in getCanStartSleepInBed!") } Local PlayerClass::getCanPickupItems() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->getCanPickupItems()); - } - CATCH("Fail in getCanPickupItems!") + return Boolean::newBoolean(player->getCanPickupItems()); + } + CATCH("Fail in getCanPickupItems!") } Local PlayerClass::isSneaking() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - return Boolean::newBoolean(player->isSneaking()); - } - CATCH("Fail in isSneaking!") + return Boolean::newBoolean(player->isSneaking()); + } + CATCH("Fail in isSneaking!") } Local PlayerClass::getSpeed() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - return Number::newNumber(player->getSpeed()); - } - CATCH("Fail in getSpeed!") + return Number::newNumber(player->getSpeed()); + } + CATCH("Fail in getSpeed!") } Local PlayerClass::getDirection() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - Vec2 rot = player->getRotation(); - return DirectionAngle::newAngle(rot.x, rot.y); - } - CATCH("Fail in getDirection!") + Vec2 rot = player->getRotation(); + return DirectionAngle::newAngle(rot.x, rot.y); + } + CATCH("Fail in getDirection!") } Local PlayerClass::getMaxHealth() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - return Number::newNumber(player->getMaxHealth()); - } - CATCH("Fail in GetMaxHealth!") + return Number::newNumber(player->getMaxHealth()); + } + CATCH("Fail in GetMaxHealth!") } Local PlayerClass::getHealth() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - return Number::newNumber(player->getHealth()); - } - CATCH("Fail in GetHealth!") + return Number::newNumber(player->getHealth()); + } + CATCH("Fail in GetHealth!") } Local PlayerClass::getInAir() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - return Boolean::newBoolean(!player->isOnGround() && !player->isInWater()); - } - CATCH("Fail in GetInAir!") + return Boolean::newBoolean(!player->isOnGround() && !player->isInWater()); + } + CATCH("Fail in GetInAir!") } Local PlayerClass::getInWater() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - return Boolean::newBoolean(player->isInWater()); - } - CATCH("Fail in getInWater!") + return Boolean::newBoolean(player->isInWater()); + } + CATCH("Fail in getInWater!") } Local PlayerClass::getInLava() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - return Boolean::newBoolean(ActorMobilityUtils::shouldApplyLava( - *(IConstBlockSource *)&player->getDimensionBlockSourceConst(), - player->getEntityContext())); - } - CATCH("Fail in getInLava!") + return Boolean::newBoolean(ActorMobilityUtils::shouldApplyLava( + *(IConstBlockSource*)&player->getDimensionBlockSourceConst(), + player->getEntityContext() + )); + } + CATCH("Fail in getInLava!") } Local PlayerClass::getInRain() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - return Boolean::newBoolean(player->isInRain()); - } - CATCH("Fail in getInRain!") + return Boolean::newBoolean(player->isInRain()); + } + CATCH("Fail in getInRain!") } Local PlayerClass::getInSnow() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - return Boolean::newBoolean(player->isInSnow()); - } - CATCH("Fail in getInSnow!") + return Boolean::newBoolean(player->isInSnow()); + } + CATCH("Fail in getInSnow!") } Local PlayerClass::getInWall() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - return Boolean::newBoolean(player->isInWall()); - } - CATCH("Fail in getInWall!") + return Boolean::newBoolean(player->isInWall()); + } + CATCH("Fail in getInWall!") } Local PlayerClass::getInWaterOrRain() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - return Boolean::newBoolean(player->isInWaterOrRain()); - } - CATCH("Fail in getInWaterOrRain!") + return Boolean::newBoolean(player->isInWaterOrRain()); + } + CATCH("Fail in getInWaterOrRain!") } Local PlayerClass::getInWorld() { - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - return Boolean::newBoolean(player->isInWorld()); - } - CATCH("Fail in getInWorld!") + return Boolean::newBoolean(player->isInWorld()); + } + CATCH("Fail in getInWorld!") } Local PlayerClass::getInClouds() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->isInClouds()); - } - CATCH("Fail in getInClouds!") + return Boolean::newBoolean(player->isInClouds()); + } + CATCH("Fail in getInClouds!") } -Local PlayerClass::asPointer(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); - else - return NativePointer::newNativePointer(player); - } - CATCH("Fail in asPointer!") +Local PlayerClass::asPointer(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); + else return NativePointer::newNativePointer(player); + } + CATCH("Fail in asPointer!") } Local PlayerClass::getUniqueID() { - try { - Player *player = get(); - if (!player) - return Local(); - else - return String::newString( - std::to_string(player->getOrCreateUniqueID().id)); - } - CATCH("Fail in getUniqueID!") + try { + Player* player = get(); + if (!player) return Local(); + else return String::newString(std::to_string(player->getOrCreateUniqueID().id)); + } + CATCH("Fail in getUniqueID!") } Local PlayerClass::getLangCode() { - try { - std::string result = "unknown"; - auto map = ll::service::getServerNetworkHandler() - ->fetchConnectionRequest(get()->getNetworkIdentifier()) - .mRawToken.get() - ->mDataInfo.value_.map_; - for (auto &iter : *map) { - string s(iter.first.c_str()); - if (s.find("LanguageCode") != std::string::npos) { - result = iter.second.value_.string_; - } - } - return String::newString(result); - } - CATCH("Fail in getLangCode!"); + try { + std::string result = "unknown"; + auto map = ll::service::getServerNetworkHandler() + ->fetchConnectionRequest(get()->getNetworkIdentifier()) + .mRawToken.get() + ->mDataInfo.value_.map_; + for (auto& iter : *map) { + string s(iter.first.c_str()); + if (s.find("LanguageCode") != std::string::npos) { + result = iter.second.value_.string_; + } + } + return String::newString(result); + } + CATCH("Fail in getLangCode!"); } Local PlayerClass::isLoading() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->isLoading()); - } - CATCH("Fail in isLoading!") + return Boolean::newBoolean(player->isLoading()); + } + CATCH("Fail in isLoading!") } Local PlayerClass::isInvisible() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->isInvisible()); - } - CATCH("Fail in isInvisible!") + return Boolean::newBoolean(player->isInvisible()); + } + CATCH("Fail in isInvisible!") } Local PlayerClass::isInsidePortal() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->isInsidePortal()); - } - CATCH("Fail in isInsidePortal!") + return Boolean::newBoolean(player->isInsidePortal()); + } + CATCH("Fail in isInsidePortal!") } Local PlayerClass::isHurt() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->isHurt()); - } - CATCH("Fail in isHurt!") + return Boolean::newBoolean(player->isHurt()); + } + CATCH("Fail in isHurt!") } Local PlayerClass::isTrusting() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->isTrusting()); - } - CATCH("Fail in isTrusting!") + return Boolean::newBoolean(player->isTrusting()); + } + CATCH("Fail in isTrusting!") } Local PlayerClass::isTouchingDamageBlock() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->isTouchingDamageBlock()); - } - CATCH("Fail in isTouchingDamageBlock!") + return Boolean::newBoolean(player->isTouchingDamageBlock()); + } + CATCH("Fail in isTouchingDamageBlock!") } Local PlayerClass::isHungry() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->isHungry()); - } - CATCH("Fail in isHungry!") + return Boolean::newBoolean(player->isHungry()); + } + CATCH("Fail in isHungry!") } Local PlayerClass::isOnFire() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->isOnFire()); - } - CATCH("Fail in isOnFire!") + return Boolean::newBoolean(player->isOnFire()); + } + CATCH("Fail in isOnFire!") } Local PlayerClass::isOnGround() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->isOnGround()); - } - CATCH("Fail in isOnGround!") + return Boolean::newBoolean(player->isOnGround()); + } + CATCH("Fail in isOnGround!") } Local PlayerClass::isOnHotBlock() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->isOnHotBlock()); - } - CATCH("Fail in isOnHotBlock!") + return Boolean::newBoolean(player->isOnHotBlock()); + } + CATCH("Fail in isOnHotBlock!") } Local PlayerClass::isTrading() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->isTrading()); - } - CATCH("Fail in isTrading!") + return Boolean::newBoolean(player->isTrading()); + } + CATCH("Fail in isTrading!") } Local PlayerClass::isAdventure() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->isAdventure()); - } - CATCH("Fail in isAdventure!") + return Boolean::newBoolean(player->isAdventure()); + } + CATCH("Fail in isAdventure!") } Local PlayerClass::isGliding() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->isGliding()); - } - CATCH("Fail in isGliding!") + return Boolean::newBoolean(player->isGliding()); + } + CATCH("Fail in isGliding!") } Local PlayerClass::isSurvival() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->isSurvival()); - } - CATCH("Fail in isSurvival!") + return Boolean::newBoolean(player->isSurvival()); + } + CATCH("Fail in isSurvival!") } Local PlayerClass::isSpectator() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->isSpectator()); - } - CATCH("Fail in isSpectator!") + return Boolean::newBoolean(player->isSpectator()); + } + CATCH("Fail in isSpectator!") } Local PlayerClass::isRiding() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->isRiding()); - } - CATCH("Fail in isRiding!") + return Boolean::newBoolean(player->isRiding()); + } + CATCH("Fail in isRiding!") } Local PlayerClass::isDancing() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->isDancing()); - } - CATCH("Fail in isDancing!") + return Boolean::newBoolean(player->isDancing()); + } + CATCH("Fail in isDancing!") } Local PlayerClass::isCreative() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->isCreative()); - } - CATCH("Fail in isCreative!") + return Boolean::newBoolean(player->isCreative()); + } + CATCH("Fail in isCreative!") } Local PlayerClass::isFlying() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->isFlying()); - } - CATCH("Fail in isFlying!") + return Boolean::newBoolean(player->isFlying()); + } + CATCH("Fail in isFlying!") } Local PlayerClass::isSleeping() { - try { - Player *player = get(); - if (!player) { - return Local(); - } + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Boolean::newBoolean(player->isSleeping()); - } - CATCH("Fail in isSleeping!") + return Boolean::newBoolean(player->isSleeping()); + } + CATCH("Fail in isSleeping!") } Local PlayerClass::isMoving() { - try { - Player *player = get(); - if (!player) { - return Local(); - } - - return Boolean::newBoolean(player->isMoving()); - } - CATCH("Fail in isMoving!") -} - -Local PlayerClass::teleport(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - - try { - Player *player = get(); - if (!player) - return Boolean::newBoolean(false); - Vec2 angle; - FloatVec4 pos; - bool rotationIsValid = false; - - if (args.size() <= 2) { - if (IsInstanceOf(args[0])) { - // IntPos - IntPos *posObj = IntPos::extractPos(args[0]); - if (posObj->dim < 0) - return Boolean::newBoolean(false); - else { - pos.x = posObj->x; - pos.y = posObj->y; - pos.z = posObj->z; - pos.dim = posObj->dim; - } - } else if (IsInstanceOf(args[0])) { - // FloatPos - FloatPos *posObj = FloatPos::extractPos(args[0]); - if (posObj->dim < 0) - return Boolean::newBoolean(false); - else { - pos = *posObj; - } - } else { - LOG_WRONG_ARG_TYPE(); - return Boolean::newBoolean(false); - } - if (args.size() == 2 && IsInstanceOf(args[1])) { - auto ang = DirectionAngle::extract(args[1]); - angle.x = ang->pitch; - angle.y = ang->yaw; - rotationIsValid = true; - } - } else if (args.size() <= 5) { // teleport(x,y,z,dimid[,rot]) - // number pos - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - - pos.x = args[0].asNumber().toFloat(); - pos.y = args[1].asNumber().toFloat(); - pos.z = args[2].asNumber().toFloat(); - pos.dim = args[3].toInt(); - if (args.size() == 5 && IsInstanceOf(args[4])) { - auto ang = DirectionAngle::extract(args[4]); - angle.x = ang->pitch; - angle.y = ang->yaw; - rotationIsValid = true; - } - } else { - LOG_WRONG_ARG_TYPE(); - return Boolean::newBoolean(false); - } - if (!rotationIsValid) { - angle = player->getRotation(); - } - player->teleport(pos.getVec3(), pos.dim, angle); - return Boolean::newBoolean(true); - } - CATCH("Fail in TeleportPlayer!") -} - -Local PlayerClass::kill(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); - - player->kill(); - return Boolean::newBoolean(true); //=======??? - } - CATCH("Fail in KillPlayer!") -} - -Local PlayerClass::isOP(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); - - return Boolean::newBoolean(player->isOperator()); - } - CATCH("Fail in IsOP!") -} - -Local PlayerClass::setPermLevel(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - - try { - Player *player = get(); - if (!player) - return Local(); - - bool res = false; - int newPerm = args[0].asNumber().toInt32(); - if (newPerm >= 0 && newPerm <= 4) { - RecordOperation(ENGINE_OWN_DATA()->pluginName, "Set Permission Level", - fmt::format("Set Player {} Permission Level as {}.", - player->getRealName(), newPerm)); - player->setPermissions((CommandPermissionLevel)newPerm); - if (newPerm >= 1) { - player->getAbilities().setPlayerPermissions( - PlayerPermissionLevel::Operator); - } else { - player->getAbilities().setPlayerPermissions( - PlayerPermissionLevel::Member); - } - UpdateAbilitiesPacket uPkt(player->getOrCreateUniqueID(), - player->getAbilities()); - player->sendNetworkPacket(uPkt); - res = true; - } - return Boolean::newBoolean(res); - } - CATCH("Fail in setPlayerPermLevel!"); -} - -Local PlayerClass::setGameMode(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - - try { - Player *player = get(); - if (!player) - return Local(); - - bool res = false; - int newMode = args[0].asNumber().toInt32(); - if (newMode >= 0 || newMode <= 3) { - player->setPlayerGameType((GameType)newMode); - res = true; - } - return Boolean::newBoolean(res); - } - CATCH("Fail in setGameMode!"); -} - -Local PlayerClass::runcmd(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - Player *player = get(); - if (!player) - return Local(); - CommandContext context = CommandContext( - args[0].asString().toString(), - std::make_unique(PlayerCommandOrigin(*get()))); - ll::service::getMinecraft()->getCommands().executeCommand(context); - return Boolean::newBoolean(true); - } - CATCH("Fail in runcmd!"); -} - -Local PlayerClass::kick(const Arguments &args) { - if (args.size() >= 1) + try { + Player* player = get(); + if (!player) { + return Local(); + } + + return Boolean::newBoolean(player->isMoving()); + } + CATCH("Fail in isMoving!") +} + +Local PlayerClass::teleport(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + + try { + Player* player = get(); + if (!player) return Boolean::newBoolean(false); + Vec2 angle; + FloatVec4 pos; + bool rotationIsValid = false; + + if (args.size() <= 2) { + if (IsInstanceOf(args[0])) { + // IntPos + IntPos* posObj = IntPos::extractPos(args[0]); + if (posObj->dim < 0) return Boolean::newBoolean(false); + else { + pos.x = posObj->x; + pos.y = posObj->y; + pos.z = posObj->z; + pos.dim = posObj->dim; + } + } else if (IsInstanceOf(args[0])) { + // FloatPos + FloatPos* posObj = FloatPos::extractPos(args[0]); + if (posObj->dim < 0) return Boolean::newBoolean(false); + else { + pos = *posObj; + } + } else { + LOG_WRONG_ARG_TYPE(); + return Boolean::newBoolean(false); + } + if (args.size() == 2 && IsInstanceOf(args[1])) { + auto ang = DirectionAngle::extract(args[1]); + angle.x = ang->pitch; + angle.y = ang->yaw; + rotationIsValid = true; + } + } else if (args.size() <= 5) { // teleport(x,y,z,dimid[,rot]) + // number pos + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + + pos.x = args[0].asNumber().toFloat(); + pos.y = args[1].asNumber().toFloat(); + pos.z = args[2].asNumber().toFloat(); + pos.dim = args[3].toInt(); + if (args.size() == 5 && IsInstanceOf(args[4])) { + auto ang = DirectionAngle::extract(args[4]); + angle.x = ang->pitch; + angle.y = ang->yaw; + rotationIsValid = true; + } + } else { + LOG_WRONG_ARG_TYPE(); + return Boolean::newBoolean(false); + } + if (!rotationIsValid) { + angle = player->getRotation(); + } + player->teleport(pos.getVec3(), pos.dim, angle); + return Boolean::newBoolean(true); + } + CATCH("Fail in TeleportPlayer!") +} + +Local PlayerClass::kill(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); + + player->kill(); + return Boolean::newBoolean(true); //=======??? + } + CATCH("Fail in KillPlayer!") +} + +Local PlayerClass::isOP(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); + + return Boolean::newBoolean(player->isOperator()); + } + CATCH("Fail in IsOP!") +} + +Local PlayerClass::setPermLevel(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + + try { + Player* player = get(); + if (!player) return Local(); + + bool res = false; + int newPerm = args[0].asNumber().toInt32(); + if (newPerm >= 0 && newPerm <= 4) { + RecordOperation( + ENGINE_OWN_DATA()->pluginName, + "Set Permission Level", + fmt::format("Set Player {} Permission Level as {}.", player->getRealName(), newPerm) + ); + player->setPermissions((CommandPermissionLevel)newPerm); + if (newPerm >= 1) { + player->getAbilities().setPlayerPermissions(PlayerPermissionLevel::Operator); + } else { + player->getAbilities().setPlayerPermissions(PlayerPermissionLevel::Member); + } + UpdateAbilitiesPacket uPkt(player->getOrCreateUniqueID(), player->getAbilities()); + player->sendNetworkPacket(uPkt); + res = true; + } + return Boolean::newBoolean(res); + } + CATCH("Fail in setPlayerPermLevel!"); +} + +Local PlayerClass::setGameMode(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + + try { + Player* player = get(); + if (!player) return Local(); + + bool res = false; + int newMode = args[0].asNumber().toInt32(); + if (newMode >= 0 || newMode <= 3) { + player->setPlayerGameType((GameType)newMode); + res = true; + } + return Boolean::newBoolean(res); + } + CATCH("Fail in setGameMode!"); +} + +Local PlayerClass::runcmd(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - Player *player = get(); - if (!player) - return Local(); - - string msg = "disconnectionScreen.disconnected"; - if (args.size() >= 1) - msg = args[0].toStr(); - - player->disconnect(msg); - return Boolean::newBoolean(true); //=======??? - } - CATCH("Fail in kickPlayer!"); -} - -Local PlayerClass::tell(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - Player *player = get(); - if (!player) - return Local(); - - TextPacketType type = TextPacketType::Raw; - if (args.size() >= 2 && args[1].isNumber()) { - int newType = args[1].asNumber().toInt32(); - if (newType >= 0 && newType <= 11) - type = (TextPacketType)newType; - } - - TextPacket pkt = TextPacket(); - pkt.mType = type; - pkt.mMessage = args[0].asString().toString(); - player->sendNetworkPacket(pkt); - return Boolean::newBoolean(true); - } - CATCH("Fail in tell!"); -} - -Local PlayerClass::setTitle(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - - try { - Player *player = get(); - if (!player) - return Local(); - - string content; - SetTitlePacket::TitleType type = SetTitlePacket::TitleType::Title; - int fadeInTime = 10; - int stayTime = 70; - int fadeOutTime = 20; - - if (args.size() >= 1) { - CHECK_ARG_TYPE(args[0], ValueKind::kString); - content = args[0].toStr(); - } - if (args.size() >= 2) { - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - type = (SetTitlePacket::TitleType)args[1].toInt(); - } - if (args.size() >= 5) { - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - CHECK_ARG_TYPE(args[4], ValueKind::kNumber); - fadeInTime = args[2].toInt(); - stayTime = args[3].toInt(); - fadeOutTime = args[4].toInt(); - } - - SetTitlePacket pkt = SetTitlePacket(type, content); - pkt.mFadeInTime = fadeInTime; - pkt.mStayTime = stayTime; - pkt.mFadeOutTime = fadeOutTime; - player->sendNetworkPacket(pkt); - return Boolean::newBoolean(true); - } - CATCH("Fail in setTitle!"); -} - -Local PlayerClass::talkAs(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - Player *player = get(); - if (!player) - return Local(); - - TextPacket pkt = TextPacket(); - pkt.createChat(player->getRealName(), args[0].asString().toString(), - player->getXuid(), player->getPlatformOnlineId()); - ll::service::getServerNetworkHandler()->handle( - player->getNetworkIdentifier(), pkt); - return Boolean::newBoolean(true); - } - CATCH("Fail in talkAs!"); -} - -Local PlayerClass::talkTo(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - Player *target = PlayerClass::extract(args[1]); - if (!target) - return Local(); - Player *player = get(); - if (!player) - return Local(); - - TextPacket pkt = TextPacket(); - pkt.createChat(player->getRealName(), args[0].asString().toString(), - player->getXuid(), player->getPlatformOnlineId()); - target->sendNetworkPacket(pkt); - return Boolean::newBoolean(true); - } - CATCH("Fail in talkTo!"); -} - -Local PlayerClass::getHand(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); - - return ItemClass::newItem( - const_cast(&player->getSelectedItem())); - } - CATCH("Fail in getHand!"); -} - -Local PlayerClass::getOffHand(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); - - return ItemClass::newItem((ItemStack *)&player->getOffhandSlot()); - } - CATCH("Fail in getOffHand!"); -} - -Local PlayerClass::getInventory(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); - - return ContainerClass::newContainer(&player->getInventory()); - } - CATCH("Fail in getInventory!"); -} - -Local PlayerClass::getArmor(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); - - return ContainerClass::newContainer(&player->getArmorContainer()); - } - CATCH("Fail in getArmor!"); -} - -Local PlayerClass::getEnderChest(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); - - return ContainerClass::newContainer(player->getEnderChestContainer()); - } - CATCH("Fail in getEnderChest!"); -} - -Local PlayerClass::getRespawnPosition(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); - BlockPos position = player->getSpawnPosition(); - DimensionType dim = player->getSpawnDimension(); - return IntPos::newPos(position, dim); - } - CATCH("Fail in getRespawnPosition!") -} - -Local PlayerClass::setRespawnPosition(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); - IntVec4 pos; - if (args.size() == 1) { - // IntPos - if (IsInstanceOf(args[0])) { - // IntPos - IntPos *posObj = IntPos::extractPos(args[0]); - if (posObj->dim < 0) - return Boolean::newBoolean(false); - else { - pos = *posObj; - } - } else if (IsInstanceOf(args[0])) { - // FloatPos - FloatPos *posObj = FloatPos::extractPos(args[0]); - if (posObj->dim < 0) - return Boolean::newBoolean(false); - else { - pos = posObj->toIntVec4(); - } - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - } else if (args.size() == 4) { - // Number Pos - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - pos = {args[0].toInt(), args[1].toInt(), args[2].toInt(), - args[3].toInt()}; - } else { - LOG_WRONG_ARGS_COUNT(); - return Local(); + try { + Player* player = get(); + if (!player) return Local(); + CommandContext context = CommandContext( + args[0].asString().toString(), + std::make_unique(PlayerCommandOrigin(*get())) + ); + ll::service::getMinecraft()->getCommands().executeCommand(context); + return Boolean::newBoolean(true); + } + CATCH("Fail in runcmd!"); +} + +Local PlayerClass::kick(const Arguments& args) { + if (args.size() >= 1) CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + Player* player = get(); + if (!player) return Local(); + + string msg = "disconnectionScreen.disconnected"; + if (args.size() >= 1) msg = args[0].toStr(); + + player->disconnect(msg); + return Boolean::newBoolean(true); //=======??? + } + CATCH("Fail in kickPlayer!"); +} + +Local PlayerClass::tell(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + Player* player = get(); + if (!player) return Local(); + + TextPacketType type = TextPacketType::Raw; + if (args.size() >= 2 && args[1].isNumber()) { + int newType = args[1].asNumber().toInt32(); + if (newType >= 0 && newType <= 11) type = (TextPacketType)newType; + } + + TextPacket pkt = TextPacket(); + pkt.mType = type; + pkt.mMessage = args[0].asString().toString(); + player->sendNetworkPacket(pkt); + return Boolean::newBoolean(true); + } + CATCH("Fail in tell!"); +} + +Local PlayerClass::setTitle(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + + try { + Player* player = get(); + if (!player) return Local(); + + string content; + SetTitlePacket::TitleType type = SetTitlePacket::TitleType::Title; + int fadeInTime = 10; + int stayTime = 70; + int fadeOutTime = 20; + + if (args.size() >= 1) { + CHECK_ARG_TYPE(args[0], ValueKind::kString); + content = args[0].toStr(); + } + if (args.size() >= 2) { + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + type = (SetTitlePacket::TitleType)args[1].toInt(); + } + if (args.size() >= 5) { + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + CHECK_ARG_TYPE(args[4], ValueKind::kNumber); + fadeInTime = args[2].toInt(); + stayTime = args[3].toInt(); + fadeOutTime = args[4].toInt(); + } + + SetTitlePacket pkt = SetTitlePacket(type, content); + pkt.mFadeInTime = fadeInTime; + pkt.mStayTime = stayTime; + pkt.mFadeOutTime = fadeOutTime; + player->sendNetworkPacket(pkt); + return Boolean::newBoolean(true); + } + CATCH("Fail in setTitle!"); +} + +Local PlayerClass::talkAs(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + Player* player = get(); + if (!player) return Local(); + + TextPacket pkt = TextPacket(); + pkt.createChat( + player->getRealName(), + args[0].asString().toString(), + player->getXuid(), + player->getPlatformOnlineId() + ); + ll::service::getServerNetworkHandler()->handle(player->getNetworkIdentifier(), pkt); + return Boolean::newBoolean(true); + } + CATCH("Fail in talkAs!"); +} + +Local PlayerClass::talkTo(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + Player* target = PlayerClass::extract(args[1]); + if (!target) return Local(); + Player* player = get(); + if (!player) return Local(); + + TextPacket pkt = TextPacket(); + pkt.createChat( + player->getRealName(), + args[0].asString().toString(), + player->getXuid(), + player->getPlatformOnlineId() + ); + target->sendNetworkPacket(pkt); + return Boolean::newBoolean(true); + } + CATCH("Fail in talkTo!"); +} + +Local PlayerClass::getHand(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); + + return ItemClass::newItem(const_cast(&player->getSelectedItem())); + } + CATCH("Fail in getHand!"); +} + +Local PlayerClass::getOffHand(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); + + return ItemClass::newItem((ItemStack*)&player->getOffhandSlot()); + } + CATCH("Fail in getOffHand!"); +} + +Local PlayerClass::getInventory(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); + + return ContainerClass::newContainer(&player->getInventory()); + } + CATCH("Fail in getInventory!"); +} + +Local PlayerClass::getArmor(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); + + return ContainerClass::newContainer(&player->getArmorContainer()); + } + CATCH("Fail in getArmor!"); +} + +Local PlayerClass::getEnderChest(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); + + return ContainerClass::newContainer(player->getEnderChestContainer()); + } + CATCH("Fail in getEnderChest!"); +} + +Local PlayerClass::getRespawnPosition(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); + BlockPos position = player->getSpawnPosition(); + DimensionType dim = player->getSpawnDimension(); + return IntPos::newPos(position, dim); + } + CATCH("Fail in getRespawnPosition!") +} + +Local PlayerClass::setRespawnPosition(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); + IntVec4 pos; + if (args.size() == 1) { + // IntPos + if (IsInstanceOf(args[0])) { + // IntPos + IntPos* posObj = IntPos::extractPos(args[0]); + if (posObj->dim < 0) return Boolean::newBoolean(false); + else { + pos = *posObj; + } + } else if (IsInstanceOf(args[0])) { + // FloatPos + FloatPos* posObj = FloatPos::extractPos(args[0]); + if (posObj->dim < 0) return Boolean::newBoolean(false); + else { + pos = posObj->toIntVec4(); + } + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + } else if (args.size() == 4) { + // Number Pos + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + pos = {args[0].toInt(), args[1].toInt(), args[2].toInt(), args[3].toInt()}; + } else { + LOG_WRONG_ARGS_COUNT(); + return Local(); + } + player->setRespawnPosition(pos.getBlockPos(), pos.dim); + return Boolean::newBoolean(true); + } + CATCH("Fail in setRespawnPosition!") +} + +Local PlayerClass::refreshItems(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); + + player->refreshInventory(); + return Boolean::newBoolean(true); + } + CATCH("Fail in refreshItems!"); +} + +Local PlayerClass::rename(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + Player* player = get(); + if (!player) return Local(); + player->setNameTag(args[0].toStr()); + player->_sendDirtyActorData(); + return Boolean::newBoolean(true); + } + CATCH("Fail in RenamePlayer!"); +} + +Local PlayerClass::addLevel(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + + try { + Player* player = get(); + if (!player) return Local(); + + player->addLevels(args[0].toInt()); + return Boolean::newBoolean(true); + } + CATCH("Fail in addLevel!"); +} + +Local PlayerClass::reduceLevel(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + + try { + Player* player = get(); + if (!player) { + return Local(); + } + + player->addLevels(-args[0].toInt()); + return Boolean::newBoolean(true); + } + CATCH("Fail in reduceLevel!"); +} + +Local PlayerClass::getLevel(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); + + return Number::newNumber(player->getPlayerLevel()); + } + CATCH("Fail in getLevel!") +} + +Local PlayerClass::setLevel(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + + try { + Player* player = get(); + if (!player) return Local(); + + player->addLevels(args[0].toInt() - player->getPlayerLevel()); + return Boolean::newBoolean(true); } - player->setRespawnPosition(pos.getBlockPos(), pos.dim); - return Boolean::newBoolean(true); - } - CATCH("Fail in setRespawnPosition!") + CATCH("Fail in setLevel!"); } -Local PlayerClass::refreshItems(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); +Local PlayerClass::setScale(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - player->refreshInventory(); - return Boolean::newBoolean(true); - } - CATCH("Fail in refreshItems!"); + try { + Player* player = get(); + if (!player) return Local(); + + player->getEntityData().set((ushort)ActorDataIDs::Scale, args[0].asNumber().toFloat()); + return Boolean::newBoolean(true); + } + CATCH("Fail in setScale!"); } -Local PlayerClass::rename(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local PlayerClass::resetLevel(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); - try { - Player *player = get(); - if (!player) - return Local(); - player->setNameTag(args[0].toStr()); - player->_sendDirtyActorData(); - return Boolean::newBoolean(true); - } - CATCH("Fail in RenamePlayer!"); + player->resetPlayerLevel(); + return Boolean::newBoolean(true); + } + CATCH("Fail in resetLevel!") } -Local PlayerClass::addLevel(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local PlayerClass::addExperience(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - player->addLevels(args[0].toInt()); - return Boolean::newBoolean(true); - } - CATCH("Fail in addLevel!"); + player->addExperience(args[0].toInt()); + return Boolean::newBoolean(true); + } + CATCH("Fail in addExperience!"); } -Local PlayerClass::reduceLevel(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local PlayerClass::reduceExperience(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + + try { + Player* player = get(); + if (!player) { + return Local(); + } - try { - Player *player = get(); - if (!player) { - return Local(); + player->addExperience(-args[0].toInt()); + return Boolean::newBoolean(true); } + CATCH("Fail in reduceExperience!"); +} - player->addLevels(-args[0].toInt()); - return Boolean::newBoolean(true); - } - CATCH("Fail in reduceLevel!"); +Local PlayerClass::getCurrentExperience(const Arguments& arg) { + try { + Player* player = get(); + if (!player) { + return Local(); + } + return Number::newNumber(player->getXpEarnedAtCurrentLevel()); + } + CATCH("Fail in getCurrentExperience!") } -Local PlayerClass::getLevel(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); +Local PlayerClass::setCurrentExperience(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + + try { + Player* player = get(); + if (!player) { + return Local(); + } - return Number::newNumber(player->getPlayerLevel()); - } - CATCH("Fail in getLevel!") + AttributeInstance* attr = player->getMutableAttribute(Player::EXPERIENCE); + attr->setCurrentValue(args[0].asNumber().toFloat()); // Not sure about that + return Boolean::newBoolean(true); + } + CATCH("Fail in setCurrentExperience!"); } -Local PlayerClass::setLevel(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local PlayerClass::getTotalExperience(const Arguments& arg) { + try { + Player* player = get(); + if (!player) { + return Local(); + } + return Number::newNumber( + (int32_t)player->getXpNeededForLevelRange(0, player->getPlayerLevel()) + player->getXpEarnedAtCurrentLevel() + ); + } + CATCH("Fail in getTotalExperience!") +} - try { - Player *player = get(); - if (!player) - return Local(); +Local PlayerClass::setTotalExperience(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - player->addLevels(args[0].toInt() - player->getPlayerLevel()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setLevel!"); + try { + Player* player = get(); + if (!player) { + return Local(); + } + player->resetPlayerLevel(); + player->addExperience(args[0].asNumber().toInt32()); + return Boolean::newBoolean(true); + } + CATCH("Fail in setTotalExperience!"); } -Local PlayerClass::setScale(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local PlayerClass::getXpNeededForNextLevel(const Arguments& args) { + try { + Player* player = get(); + if (!player) { + return Local(); + } - try { - Player *player = get(); - if (!player) - return Local(); + return Number::newNumber(player->getXpNeededForNextLevel()); + } + CATCH("Fail in getXpNeededForNextLevel!") +} + +Local PlayerClass::transServer(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2) + CHECK_ARG_TYPE(args[0], ValueKind::kString) + CHECK_ARG_TYPE(args[1], ValueKind::kNumber) + + try { + Player* player = get(); + if (!player) return Local(); + + TransferPacket pkt = TransferPacket(args[0].toStr(), args[1].toInt()); + player->sendNetworkPacket(pkt); + return Boolean::newBoolean(true); + } + CATCH("Fail in transServer!"); +} + +Local PlayerClass::crash(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); + + RecordOperation( + ENGINE_OWN_DATA()->pluginName, + "Crash Player", + "Execute player.crash() to crash player <" + player->getRealName() + ">" + ); + LevelChunkPacket pkt = LevelChunkPacket(); + pkt.mCacheEnabled = true; + player->sendNetworkPacket(pkt); + return Boolean::newBoolean(false); + } + CATCH("Fail in crashPlayer!"); +} - player->getEntityData().set((ushort)ActorDataIDs::Scale, - args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setScale!"); +Local PlayerClass::getBlockStandingOn(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); + + return BlockClass::newBlock(player->getBlockPosCurrentlyStandingOn(nullptr), player->getDimensionId()); + } + CATCH("Fail in getBlockStandingOn!"); } -Local PlayerClass::resetLevel(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); +Local PlayerClass::getDevice(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); - player->resetPlayerLevel(); - return Boolean::newBoolean(true); - } - CATCH("Fail in resetLevel!") + return DeviceClass::newDevice(player); + } + CATCH("Fail in getDevice!"); } -Local PlayerClass::addExperience(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local PlayerClass::getScore(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - player->addExperience(args[0].toInt()); - return Boolean::newBoolean(true); - } - CATCH("Fail in addExperience!"); + Scoreboard& scoreboard = ll::service::getLevel()->getScoreboard(); + Objective* obj = scoreboard.getObjective(args[0].asString().toString()); + if (!obj) { + throw std::invalid_argument("Objective " + args[0].asString().toString() + " not found"); + } + const ScoreboardId& id = scoreboard.getScoreboardId(player->getOrCreateUniqueID()); + if (!id.isValid()) { + scoreboard.createScoreboardId(*player); + } + return Number::newNumber(obj->getPlayerScore(id).mScore); + } + CATCH("Fail in getScore!"); } -Local PlayerClass::reduceExperience(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local PlayerClass::setScore(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + + try { + Player* player = get(); + if (!player) return Local(); - try { - Player *player = get(); - if (!player) { - return Local(); + Scoreboard& scoreboard = ll::service::getLevel()->getScoreboard(); + Objective* obj = scoreboard.getObjective(args[0].asString().toString()); + if (!obj) { + return Boolean::newBoolean(false); + } + const ScoreboardId& id = scoreboard.getScoreboardId(player->getOrCreateUniqueID()); + if (!id.isValid()) { + scoreboard.createScoreboardId(*player); + } + bool isSuccess = false; + scoreboard.modifyPlayerScore(isSuccess, id, *obj, args[1].asNumber().toInt32(), PlayerScoreSetFunction::Set); + return Boolean::newBoolean(isSuccess); } + CATCH("Fail in setScore!"); +} + +Local PlayerClass::addScore(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + + try { + Player* player = get(); + if (!player) return Local(); - player->addExperience(-args[0].toInt()); - return Boolean::newBoolean(true); - } - CATCH("Fail in reduceExperience!"); + Scoreboard& scoreboard = ll::service::getLevel()->getScoreboard(); + Objective* obj = scoreboard.getObjective(args[0].asString().toString()); + if (!obj) { + return Boolean::newBoolean(false); + } + const ScoreboardId& id = scoreboard.getScoreboardId(player->getOrCreateUniqueID()); + if (!id.isValid()) { + scoreboard.createScoreboardId(*player); + } + bool isSuccess = false; + scoreboard.modifyPlayerScore(isSuccess, id, *obj, args[1].asNumber().toInt32(), PlayerScoreSetFunction::Add); + return Boolean::newBoolean(isSuccess); + } + CATCH("Fail in addScore!"); } -Local PlayerClass::getCurrentExperience(const Arguments &arg) { - try { - Player *player = get(); - if (!player) { - return Local(); +Local PlayerClass::reduceScore(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + + try { + Player* player = get(); + if (!player) return Local(); + + Scoreboard& scoreboard = ll::service::getLevel()->getScoreboard(); + Objective* obj = scoreboard.getObjective(args[0].asString().toString()); + if (!obj) { + return Boolean::newBoolean(false); + } + const ScoreboardId& id = scoreboard.getScoreboardId(player->getOrCreateUniqueID()); + if (!id.isValid()) { + scoreboard.createScoreboardId(*player); + } + bool isSuccess = false; + scoreboard + .modifyPlayerScore(isSuccess, id, *obj, args[1].asNumber().toInt32(), PlayerScoreSetFunction::Subtract); + return Boolean::newBoolean(isSuccess); + } + CATCH("Fail in reduceScore!"); +} + +Local PlayerClass::deleteScore(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + Player* player = get(); + if (!player) return Local(); + + Scoreboard& scoreboard = ll::service::getLevel()->getScoreboard(); + Objective* obj = scoreboard.getObjective(args[0].asString().toString()); + if (!obj) { + return Boolean::newBoolean(false); + } + const ScoreboardId& id = scoreboard.getScoreboardId(player->getOrCreateUniqueID()); + if (!id.isValid()) { + return Boolean::newBoolean(true); + } + return Boolean::newBoolean(scoreboard.getScoreboardIdentityRef(id)->removeFromObjective(scoreboard, *obj)); + } + CATCH("Fail in deleteScore!"); +} + +Local PlayerClass::setSidebar(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kObject); + if (args.size() >= 3) CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + + try { + Player* player = get(); + if (!player) return Local(); + + std::vector> data; + auto source = args[1].asObject(); + auto keys = source.getKeyNames(); + for (auto& key : keys) { + data.push_back(make_pair(key, source.get(key).toInt())); + } + + int sortOrder = 1; + if (args.size() >= 3) sortOrder = args[2].toInt(); + + SetDisplayObjectivePacket disObjPkt = SetDisplayObjectivePacket( + "sidebar", + "FakeScoreObj", + args[0].asString().toString(), + "dummy", + (ObjectiveSortOrder)sortOrder + ); + player->sendNetworkPacket(disObjPkt); + std::vector info; + static std::set scoreIds; // Store scoreboard ids + uint64_t Id = 0; + do { + Id = (uint64_t)((rand() << 16) + rand() + 1145140); + } while (scoreIds.find(Id) != scoreIds.end()); // Generate random id + const ScoreboardId& boardId = ScoreboardId(Id); + for (auto& i : data) { + ScorePacketInfo pktInfo = ScorePacketInfo(); + pktInfo.mScoreboardId = boardId; + pktInfo.mObjectiveName = "FakeScoreObj"; + pktInfo.mIdentityType = IdentityDefinition::Type::FakePlayer; + pktInfo.mScoreValue = i.second; + pktInfo.mFakePlayerName = i.first; + info.emplace_back(pktInfo); + } + SetScorePacket setPkt = SetScorePacket(); + setPkt.mType = ScorePacketType::Change; + setPkt.mScoreInfo = info; + + player->sendNetworkPacket(disObjPkt); + return Boolean::newBoolean(true); + } + CATCH("Fail in setSidebar!") +} + +Local PlayerClass::removeSidebar(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); + + SetDisplayObjectivePacket disObjPkt = + SetDisplayObjectivePacket("sidebar", "", "", "dummy", ObjectiveSortOrder::Ascending); + player->sendNetworkPacket(disObjPkt); + return Boolean::newBoolean(true); + } + CATCH("Fail in removeSidebar!") +} + +Local PlayerClass::setBossBar(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + if (args[0].getKind() == ValueKind::kNumber) { + CHECK_ARGS_COUNT(args, 4); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + try { + Player* player = get(); + if (!player) return Local(); + + int64_t uid = args[0].asNumber().toInt64(); + int percent = args[2].toInt(); + if (percent < 0) percent = 0; + else if (percent > 100) percent = 100; + float value = (float)percent / 100; + AddEntityPacket entityPkt = AddEntityPacket(); + // Todo + // AddEntityPacket(uid, "player", Vec3(getPos().x, (float)-70, + // getPos().z), + // Vec2{0, 0}, 0); + + BossBarColor color = (BossBarColor)args[3].toInt(); + BossEventPacket pkt = BossEventPacket(); + pkt.mBossID = ActorUniqueID(uid); + pkt.mName = args[1].asString().toString(); + pkt.mHealthPercent = value; + pkt.mColor = color; + player->sendNetworkPacket(entityPkt); + player->sendNetworkPacket(pkt); + return Boolean::newBoolean(true); + } + CATCH("Fail in addBossBar!") + } + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + if (args.size() >= 3) CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + try { + Player* player = get(); + if (!player) return Local(); + + int percent = args[1].toInt(); + if (percent < 0) percent = 0; + else if (percent > 100) percent = 100; + float value = (float)percent / 100; + BossBarColor color = BossBarColor::Red; + if (args.size() >= 3) color = (BossBarColor)args[2].toInt(); + BossEventPacket pkt = BossEventPacket(); + pkt.mEventType = BossEventUpdateType::Add; + pkt.mName = args[0].asString().toString(); + pkt.mHealthPercent = value; + pkt.mColor = color; + player->sendNetworkPacket(pkt); + return Boolean::newBoolean(true); + } + CATCH("Fail in setBossBar!") +} + +Local PlayerClass::removeBossBar(const Arguments& args) { + if (args.size() == 0) { + try { + Player* player = get(); + if (!player) return Local(); + + BossEventPacket pkt = BossEventPacket(); + pkt.mEventType = BossEventUpdateType::Remove; + pkt.mColor = BossBarColor::Red; + player->sendNetworkPacket(pkt); + return Boolean::newBoolean(true); + } + CATCH("Fail in removeBossBar!") + } else { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + try { + Player* player = get(); + if (!player) return Local(); + int64_t uid = args[0].asNumber().toInt64(); + BossEventPacket pkt = BossEventPacket(); + pkt.mBossID = ActorUniqueID(uid); + pkt.mEventType = BossEventUpdateType::Remove; + player->sendNetworkPacket(pkt); + return Boolean::newBoolean(true); + } + CATCH("Fail in removeBossBar!") + } +} + +Local PlayerClass::sendSimpleForm(const Arguments& args) { + CHECK_ARGS_COUNT(args, 4); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + CHECK_ARG_TYPE(args[2], ValueKind::kArray); + CHECK_ARG_TYPE(args[3], ValueKind::kArray); + CHECK_ARG_TYPE(args[4], ValueKind::kFunction); + + try { + Player* player = get(); + if (!player) return Local(); + + // 普通格式 + auto textsArr = args[2].asArray(); + if (textsArr.size() == 0 || !textsArr.get(0).isString()) return Local(); + auto imagesArr = args[3].asArray(); + if (imagesArr.size() != textsArr.size() || !imagesArr.get(0).isString()) return Local(); + + ll::form::SimpleForm form(args[0].asString().toString(), args[1].asString().toString()); + for (int i = 0; i < textsArr.size(); ++i) { + Local img = imagesArr.get(i); + if (img.isString()) { + form.appendButton(textsArr.get(i).asString().toString(), img.asString().toString()); + } else { + form.appendButton(textsArr.get(i).asString().toString()); + } + } + form.sendTo( + *player, + [engine{EngineScope::currentEngine()}, + callback{script::Global(args[4].asFunction())}](Player& pl, int chosen) { + if ((ll::getServerStatus() != ll::ServerStatus::Running)) return; + if (!EngineManager::isValid(engine)) return; + + EngineScope scope(engine); + try { + callback.get().call( + {}, + PlayerClass::newPlayer(&pl), + chosen >= 0 ? Number::newNumber(chosen) : Local() + ); + } + CATCH_IN_CALLBACK("sendSimpleForm") + } + ); + + return Number::newNumber(1); + } + CATCH("Fail in sendSimpleForm!"); +} + +Local PlayerClass::sendModalForm(const Arguments& args) { + CHECK_ARGS_COUNT(args, 5); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + CHECK_ARG_TYPE(args[2], ValueKind::kString); + CHECK_ARG_TYPE(args[3], ValueKind::kString); + CHECK_ARG_TYPE(args[4], ValueKind::kFunction); + + try { + Player* player = get(); + if (!player) return Local(); + + ll::form::ModalForm form( + args[0].asString().toString(), + args[1].asString().toString(), + args[2].asString().toString(), + args[3].asString().toString() + ); + form.sendTo( + *player, + [engine{EngineScope::currentEngine()}, + callback{script::Global(args[4].asFunction())}](Player& pl, bool chosen) { + if ((ll::getServerStatus() != ll::ServerStatus::Running)) return; + if (!EngineManager::isValid(engine)) return; + + EngineScope scope(engine); + try { + callback.get() + .call({}, PlayerClass::newPlayer(&pl), chosen ? Boolean::newBoolean(chosen) : Local()); + } + CATCH_IN_CALLBACK("sendModalForm") + } + ); + + return Number::newNumber(2); + } + CATCH("Fail in sendModalForm!"); +} + +Local PlayerClass::sendCustomForm(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kFunction); + + try { + Player* player = get(); + if (!player) return Local(); + // Todo + // std::string data = ordered_json::parse(args[0].toStr()).dump(); + + // player->sendCustomFormPacket( + // data, [id{player->getOrCreateUniqueID()}, + // engine{EngineScope::currentEngine()}, + // callback{script::Global(args[1].asFunction())}](string result) + // { + // if ((ll::getServerStatus() != ll::ServerStatus::Running)) + // return; + // if (!EngineManager::isValid(engine)) + // return; + + // Player *pl = ll::service::getLevel()->getPlayer(id); + // if (!pl) + // return; + + // EngineScope scope(engine); + // try { + // callback.get().call({}, PlayerClass::newPlayer(pl), + // result != "null" ? JsonToValue(result) + // : Local()); + // } + // CATCH_IN_CALLBACK("sendCustomForm") + // }); + return Number::newNumber(3); + } catch (const ordered_json::exception& e) { + logger.error("Fail to parse Json string in sendCustomForm!"); + logger.error(ll::string_utils::tou8str(e.what())); + PrintScriptStackTrace(); + return Local(); + } + CATCH("Fail in sendCustomForm!"); +} + +Local PlayerClass::sendForm(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[1], ValueKind::kFunction); + + try { + Player* player = get(); + if (!player) return Local(); + + ll::form::SimpleForm* form = SimpleFormClass::extract(args[0]); + if (IsInstanceOf(args[0])) { + Local callback = args[1].asFunction(); + SimpleFormClass::sendForm(SimpleFormClass::extract(args[0]), player, callback); + } else if (IsInstanceOf(args[0])) { + Local callback = args[1].asFunction(); + CustomFormClass::sendForm(CustomFormClass::extract(args[0]), player, callback); + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + return Boolean::newBoolean(true); + } + CATCH("Fail in sendForm!"); +} + +Local PlayerClass::sendPacket(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kObject); + + try { + Player* player = get(); + if (!player) return Local(); + auto pkt = PacketClass::extract(args[0]); + if (!pkt) return Boolean::newBoolean(false); + player->sendNetworkPacket(*pkt); + return Boolean::newBoolean(true); + } + CATCH("Fail in sendPacket"); + return Local(); +} + +Local PlayerClass::setExtraData(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + Player* player = get(); + if (!player) return Local(); + + string key = args[0].toStr(); + if (key.empty()) return Boolean::newBoolean(false); + + ENGINE_OWN_DATA()->playerDataDB[player->getRealName() + "-" + key] = args[1]; + return Boolean::newBoolean(true); } - return Number::newNumber(player->getXpEarnedAtCurrentLevel()); - } - CATCH("Fail in getCurrentExperience!") + CATCH("Fail in setExtraData!"); } -Local PlayerClass::setCurrentExperience(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local PlayerClass::getExtraData(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + Player* player = get(); + if (!player) return Local(); + + string key = args[0].toStr(); + if (key.empty()) return Local(); - try { - Player *player = get(); - if (!player) { - return Local(); + auto& db = ENGINE_OWN_DATA()->playerDataDB; + auto res = db.find(player->getRealName() + "-" + key); + if (res == db.end() || res->second.isEmpty()) return Local(); + else return res->second.get(); } + CATCH("Fail in getExtraData!"); +} + +Local PlayerClass::delExtraData(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + CHECK_ARG_TYPE(args[0], ValueKind::kString) + + try { + Player* player = get(); + if (!player) return Local(); - AttributeInstance *attr = player->getMutableAttribute(Player::EXPERIENCE); - attr->setCurrentValue(args[0].asNumber().toFloat()); // Not sure about that - return Boolean::newBoolean(true); - } - CATCH("Fail in setCurrentExperience!"); -} + string key = args[0].toStr(); + if (key.empty()) return Boolean::newBoolean(false); -Local PlayerClass::getTotalExperience(const Arguments &arg) { - try { - Player *player = get(); - if (!player) { - return Local(); + ENGINE_OWN_DATA()->playerDataDB.erase(player->getRealName() + "-" + key); + return Boolean::newBoolean(true); } - return Number::newNumber( - (int32_t)player->getXpNeededForLevelRange(0, player->getPlayerLevel()) + - player->getXpEarnedAtCurrentLevel()); - } - CATCH("Fail in getTotalExperience!") + CATCH("Fail in delExtraData!") } -Local PlayerClass::setTotalExperience(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local PlayerClass::hurt(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Player *player = get(); - if (!player) { - return Local(); + try { + Player* player = get(); + if (!player) { + return Boolean::newBoolean(false); + } + float damage = args[0].asNumber().toFloat(); + int type = 0; + if (args.size() == 2) { + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + type = args[1].asNumber().toInt32(); + return Boolean::newBoolean(player->hurtByCause(damage, (ActorDamageCause)type)); + } + if (args.size() == 3) { + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + auto source = EntityClass::extract(args[2]); + type = args[1].asNumber().toInt32(); + return Boolean::newBoolean(player->hurtByCause(damage, (ActorDamageCause)type, source)); + } + return Boolean::newBoolean(false); } - player->resetPlayerLevel(); - player->addExperience(args[0].asNumber().toInt32()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setTotalExperience!"); + CATCH("Fail in hurt!"); } -Local PlayerClass::getXpNeededForNextLevel(const Arguments &args) { - try { - Player *player = get(); - if (!player) { - return Local(); - } +Local PlayerClass::heal(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + try { + Player* player = get(); + if (!player) return Local(); - return Number::newNumber(player->getXpNeededForNextLevel()); - } - CATCH("Fail in getXpNeededForNextLevel!") + player->heal(args[0].toInt()); + return Boolean::newBoolean(true); + } + CATCH("Fail in heal!"); } -Local PlayerClass::transServer(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2) - CHECK_ARG_TYPE(args[0], ValueKind::kString) - CHECK_ARG_TYPE(args[1], ValueKind::kNumber) +Local PlayerClass::setHealth(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - TransferPacket pkt = TransferPacket(args[0].toStr(), args[1].toInt()); - player->sendNetworkPacket(pkt); - return Boolean::newBoolean(true); - } - CATCH("Fail in transServer!"); -} + AttributeInstance* healthAttribute = player->getMutableAttribute(SharedAttributes::HEALTH); -Local PlayerClass::crash(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); + healthAttribute->setCurrentValue(args[0].asNumber().toFloat()); - RecordOperation(ENGINE_OWN_DATA()->pluginName, "Crash Player", - "Execute player.crash() to crash player <" + - player->getRealName() + ">"); - LevelChunkPacket pkt = LevelChunkPacket(); - pkt.mCacheEnabled = true; - player->sendNetworkPacket(pkt); - return Boolean::newBoolean(false); - } - CATCH("Fail in crashPlayer!"); -} - -Local PlayerClass::getBlockStandingOn(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); - - return BlockClass::newBlock(player->getBlockPosCurrentlyStandingOn(nullptr), - player->getDimensionId()); - } - CATCH("Fail in getBlockStandingOn!"); -} - -Local PlayerClass::getDevice(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); - - return DeviceClass::newDevice(player); - } - CATCH("Fail in getDevice!"); -} - -Local PlayerClass::getScore(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - Player *player = get(); - if (!player) - return Local(); - - Scoreboard &scoreboard = ll::service::getLevel()->getScoreboard(); - Objective *obj = scoreboard.getObjective(args[0].asString().toString()); - if (!obj) { - throw std::invalid_argument("Objective " + args[0].asString().toString() + - " not found"); - } - const ScoreboardId &id = - scoreboard.getScoreboardId(player->getOrCreateUniqueID()); - if (!id.isValid()) { - scoreboard.createScoreboardId(*player); - } - return Number::newNumber(obj->getPlayerScore(id).mScore); - } - CATCH("Fail in getScore!"); -} - -Local PlayerClass::setScore(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - - try { - Player *player = get(); - if (!player) - return Local(); - - Scoreboard &scoreboard = ll::service::getLevel()->getScoreboard(); - Objective *obj = scoreboard.getObjective(args[0].asString().toString()); - if (!obj) { - return Boolean::newBoolean(false); - } - const ScoreboardId &id = - scoreboard.getScoreboardId(player->getOrCreateUniqueID()); - if (!id.isValid()) { - scoreboard.createScoreboardId(*player); - } - bool isSuccess = false; - scoreboard.modifyPlayerScore(isSuccess, id, *obj, - args[1].asNumber().toInt32(), - PlayerScoreSetFunction::Set); - return Boolean::newBoolean(isSuccess); - } - CATCH("Fail in setScore!"); -} - -Local PlayerClass::addScore(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - - try { - Player *player = get(); - if (!player) - return Local(); - - Scoreboard &scoreboard = ll::service::getLevel()->getScoreboard(); - Objective *obj = scoreboard.getObjective(args[0].asString().toString()); - if (!obj) { - return Boolean::newBoolean(false); - } - const ScoreboardId &id = - scoreboard.getScoreboardId(player->getOrCreateUniqueID()); - if (!id.isValid()) { - scoreboard.createScoreboardId(*player); - } - bool isSuccess = false; - scoreboard.modifyPlayerScore(isSuccess, id, *obj, - args[1].asNumber().toInt32(), - PlayerScoreSetFunction::Add); - return Boolean::newBoolean(isSuccess); - } - CATCH("Fail in addScore!"); -} - -Local PlayerClass::reduceScore(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - - try { - Player *player = get(); - if (!player) - return Local(); - - Scoreboard &scoreboard = ll::service::getLevel()->getScoreboard(); - Objective *obj = scoreboard.getObjective(args[0].asString().toString()); - if (!obj) { - return Boolean::newBoolean(false); - } - const ScoreboardId &id = - scoreboard.getScoreboardId(player->getOrCreateUniqueID()); - if (!id.isValid()) { - scoreboard.createScoreboardId(*player); - } - bool isSuccess = false; - scoreboard.modifyPlayerScore(isSuccess, id, *obj, - args[1].asNumber().toInt32(), - PlayerScoreSetFunction::Subtract); - return Boolean::newBoolean(isSuccess); - } - CATCH("Fail in reduceScore!"); -} - -Local PlayerClass::deleteScore(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - Player *player = get(); - if (!player) - return Local(); - - Scoreboard &scoreboard = ll::service::getLevel()->getScoreboard(); - Objective *obj = scoreboard.getObjective(args[0].asString().toString()); - if (!obj) { - return Boolean::newBoolean(false); - } - const ScoreboardId &id = - scoreboard.getScoreboardId(player->getOrCreateUniqueID()); - if (!id.isValid()) { - return Boolean::newBoolean(true); - } - return Boolean::newBoolean( - scoreboard.getScoreboardIdentityRef(id)->removeFromObjective(scoreboard, - *obj)); - } - CATCH("Fail in deleteScore!"); -} - -Local PlayerClass::setSidebar(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kObject); - if (args.size() >= 3) - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + return Boolean::newBoolean(true); + } + CATCH("Fail in setHealth!"); +} - try { - Player *player = get(); - if (!player) - return Local(); - - std::vector> data; - auto source = args[1].asObject(); - auto keys = source.getKeyNames(); - for (auto &key : keys) { - data.push_back(make_pair(key, source.get(key).toInt())); - } - - int sortOrder = 1; - if (args.size() >= 3) - sortOrder = args[2].toInt(); - - SetDisplayObjectivePacket disObjPkt = SetDisplayObjectivePacket( - "sidebar", "FakeScoreObj", args[0].asString().toString(), "dummy", - (ObjectiveSortOrder)sortOrder); - player->sendNetworkPacket(disObjPkt); - std::vector info; - static std::set scoreIds; // Store scoreboard ids - uint64_t Id = 0; - do { - Id = (uint64_t)((rand() << 16) + rand() + 1145140); - } while (scoreIds.find(Id) != scoreIds.end()); // Generate random id - const ScoreboardId &boardId = ScoreboardId(Id); - for (auto &i : data) { - ScorePacketInfo pktInfo = ScorePacketInfo(); - pktInfo.mScoreboardId = boardId; - pktInfo.mObjectiveName = "FakeScoreObj"; - pktInfo.mIdentityType = IdentityDefinition::Type::FakePlayer; - pktInfo.mScoreValue = i.second; - pktInfo.mFakePlayerName = i.first; - info.emplace_back(pktInfo); - } - SetScorePacket setPkt = SetScorePacket(); - setPkt.mType = ScorePacketType::Change; - setPkt.mScoreInfo = info; - - player->sendNetworkPacket(disObjPkt); - return Boolean::newBoolean(true); - } - CATCH("Fail in setSidebar!") -} - -Local PlayerClass::removeSidebar(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); - - SetDisplayObjectivePacket disObjPkt = SetDisplayObjectivePacket( - "sidebar", "", "", "dummy", ObjectiveSortOrder::Ascending); - player->sendNetworkPacket(disObjPkt); - return Boolean::newBoolean(true); - } - CATCH("Fail in removeSidebar!") -} - -Local PlayerClass::setBossBar(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - if (args[0].getKind() == ValueKind::kNumber) { - CHECK_ARGS_COUNT(args, 4); +Local PlayerClass::setMaxHealth(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + try { - Player *player = get(); - if (!player) - return Local(); + Player* player = get(); + if (!player) return Local(); - int64_t uid = args[0].asNumber().toInt64(); - int percent = args[2].toInt(); - if (percent < 0) - percent = 0; - else if (percent > 100) - percent = 100; - float value = (float)percent / 100; - AddEntityPacket entityPkt = AddEntityPacket(); - // Todo - // AddEntityPacket(uid, "player", Vec3(getPos().x, (float)-70, - // getPos().z), - // Vec2{0, 0}, 0); - - BossBarColor color = (BossBarColor)args[3].toInt(); - BossEventPacket pkt = BossEventPacket(); - pkt.mBossID = ActorUniqueID(uid); - pkt.mName = args[1].asString().toString(); - pkt.mHealthPercent = value; - pkt.mColor = color; - player->sendNetworkPacket(entityPkt); - player->sendNetworkPacket(pkt); - return Boolean::newBoolean(true); - } - CATCH("Fail in addBossBar!") - } - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - if (args.size() >= 3) - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - try { - Player *player = get(); - if (!player) - return Local(); - - int percent = args[1].toInt(); - if (percent < 0) - percent = 0; - else if (percent > 100) - percent = 100; - float value = (float)percent / 100; - BossBarColor color = BossBarColor::Red; - if (args.size() >= 3) - color = (BossBarColor)args[2].toInt(); - BossEventPacket pkt = BossEventPacket(); - pkt.mEventType = BossEventUpdateType::Add; - pkt.mName = args[0].asString().toString(); - pkt.mHealthPercent = value; - pkt.mColor = color; - player->sendNetworkPacket(pkt); - return Boolean::newBoolean(true); - } - CATCH("Fail in setBossBar!") -} - -Local PlayerClass::removeBossBar(const Arguments &args) { - if (args.size() == 0) { - try { - Player *player = get(); - if (!player) - return Local(); + AttributeInstance* healthAttribute = player->getMutableAttribute(SharedAttributes::HEALTH); - BossEventPacket pkt = BossEventPacket(); - pkt.mEventType = BossEventUpdateType::Remove; - pkt.mColor = BossBarColor::Red; - player->sendNetworkPacket(pkt); - return Boolean::newBoolean(true); + healthAttribute->setMaxValue(args[0].asNumber().toFloat()); + + return Boolean::newBoolean(true); } - CATCH("Fail in removeBossBar!") - } else { + CATCH("Fail in setMaxHealth!"); +} + +Local PlayerClass::setAbsorption(const Arguments& args) { CHECK_ARGS_COUNT(args, 1); CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Player *player = get(); - if (!player) - return Local(); - int64_t uid = args[0].asNumber().toInt64(); - BossEventPacket pkt = BossEventPacket(); - pkt.mBossID = ActorUniqueID(uid); - pkt.mEventType = BossEventUpdateType::Remove; - player->sendNetworkPacket(pkt); - return Boolean::newBoolean(true); - } - CATCH("Fail in removeBossBar!") - } -} - -Local PlayerClass::sendSimpleForm(const Arguments &args) { - CHECK_ARGS_COUNT(args, 4); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - CHECK_ARG_TYPE(args[2], ValueKind::kArray); - CHECK_ARG_TYPE(args[3], ValueKind::kArray); - CHECK_ARG_TYPE(args[4], ValueKind::kFunction); - - try { - Player *player = get(); - if (!player) - return Local(); - - // 普通格式 - auto textsArr = args[2].asArray(); - if (textsArr.size() == 0 || !textsArr.get(0).isString()) - return Local(); - auto imagesArr = args[3].asArray(); - if (imagesArr.size() != textsArr.size() || !imagesArr.get(0).isString()) - return Local(); - - ll::form::SimpleForm form(args[0].asString().toString(), - args[1].asString().toString()); - for (int i = 0; i < textsArr.size(); ++i) { - Local img = imagesArr.get(i); - if (img.isString()) { - form.appendButton(textsArr.get(i).asString().toString(), - img.asString().toString()); - } else { - form.appendButton(textsArr.get(i).asString().toString()); - } - } - form.sendTo(*player, [engine{EngineScope::currentEngine()}, - callback{script::Global(args[4].asFunction())}]( - Player &pl, int chosen) { - if ((ll::getServerStatus() != ll::ServerStatus::Running)) - return; - if (!EngineManager::isValid(engine)) - return; - - EngineScope scope(engine); - try { - callback.get().call({}, PlayerClass::newPlayer(&pl), - chosen >= 0 ? Number::newNumber(chosen) - : Local()); - } - CATCH_IN_CALLBACK("sendSimpleForm") - }); - - return Number::newNumber(1); - } - CATCH("Fail in sendSimpleForm!"); -} - -Local PlayerClass::sendModalForm(const Arguments &args) { - CHECK_ARGS_COUNT(args, 5); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - CHECK_ARG_TYPE(args[2], ValueKind::kString); - CHECK_ARG_TYPE(args[3], ValueKind::kString); - CHECK_ARG_TYPE(args[4], ValueKind::kFunction); - - try { - Player *player = get(); - if (!player) - return Local(); - - ll::form::ModalForm form( - args[0].asString().toString(), args[1].asString().toString(), - args[2].asString().toString(), args[3].asString().toString()); - form.sendTo(*player, [engine{EngineScope::currentEngine()}, - callback{script::Global(args[4].asFunction())}]( - Player &pl, bool chosen) { - if ((ll::getServerStatus() != ll::ServerStatus::Running)) - return; - if (!EngineManager::isValid(engine)) - return; - - EngineScope scope(engine); - try { - callback.get().call({}, PlayerClass::newPlayer(&pl), - chosen ? Boolean::newBoolean(chosen) - : Local()); - } - CATCH_IN_CALLBACK("sendModalForm") - }); - - return Number::newNumber(2); - } - CATCH("Fail in sendModalForm!"); -} - -Local PlayerClass::sendCustomForm(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kFunction); - - try { - Player *player = get(); - if (!player) - return Local(); - // Todo - // std::string data = ordered_json::parse(args[0].toStr()).dump(); - - // player->sendCustomFormPacket( - // data, [id{player->getOrCreateUniqueID()}, - // engine{EngineScope::currentEngine()}, - // callback{script::Global(args[1].asFunction())}](string result) - // { - // if ((ll::getServerStatus() != ll::ServerStatus::Running)) - // return; - // if (!EngineManager::isValid(engine)) - // return; - - // Player *pl = ll::service::getLevel()->getPlayer(id); - // if (!pl) - // return; - - // EngineScope scope(engine); - // try { - // callback.get().call({}, PlayerClass::newPlayer(pl), - // result != "null" ? JsonToValue(result) - // : Local()); - // } - // CATCH_IN_CALLBACK("sendCustomForm") - // }); - return Number::newNumber(3); - } catch (const ordered_json::exception &e) { - logger.error("Fail to parse Json string in sendCustomForm!"); - logger.error(ll::string_utils::tou8str(e.what())); - PrintScriptStackTrace(); - return Local(); - } - CATCH("Fail in sendCustomForm!"); -} - -Local PlayerClass::sendForm(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[1], ValueKind::kFunction); - - try { - Player *player = get(); - if (!player) - return Local(); - - ll::form::SimpleForm *form = SimpleFormClass::extract(args[0]); - if (IsInstanceOf(args[0])) { - Local callback = args[1].asFunction(); - SimpleFormClass::sendForm(SimpleFormClass::extract(args[0]), player, - callback); - } else if (IsInstanceOf(args[0])) { - Local callback = args[1].asFunction(); - CustomFormClass::sendForm(CustomFormClass::extract(args[0]), player, - callback); - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - return Boolean::newBoolean(true); - } - CATCH("Fail in sendForm!"); -} - -Local PlayerClass::sendPacket(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kObject); - - try { - Player *player = get(); - if (!player) - return Local(); - auto pkt = PacketClass::extract(args[0]); - if (!pkt) - return Boolean::newBoolean(false); - player->sendNetworkPacket(*pkt); - return Boolean::newBoolean(true); - } - CATCH("Fail in sendPacket"); - return Local(); -} - -Local PlayerClass::setExtraData(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - Player *player = get(); - if (!player) - return Local(); - - string key = args[0].toStr(); - if (key.empty()) - return Boolean::newBoolean(false); - - ENGINE_OWN_DATA()->playerDataDB[player->getRealName() + "-" + key] = - args[1]; - return Boolean::newBoolean(true); - } - CATCH("Fail in setExtraData!"); -} - -Local PlayerClass::getExtraData(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - Player *player = get(); - if (!player) - return Local(); - - string key = args[0].toStr(); - if (key.empty()) - return Local(); - - auto &db = ENGINE_OWN_DATA()->playerDataDB; - auto res = db.find(player->getRealName() + "-" + key); - if (res == db.end() || res->second.isEmpty()) - return Local(); - else - return res->second.get(); - } - CATCH("Fail in getExtraData!"); -} -Local PlayerClass::delExtraData(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - CHECK_ARG_TYPE(args[0], ValueKind::kString) + try { + Player* player = get(); + if (!player) return Local(); - try { - Player *player = get(); - if (!player) - return Local(); + AttributeInstance* absorptionAttribute = player->getMutableAttribute(SharedAttributes::ABSORPTION); - string key = args[0].toStr(); - if (key.empty()) - return Boolean::newBoolean(false); + absorptionAttribute->setCurrentValue(args[0].asNumber().toFloat()); - ENGINE_OWN_DATA()->playerDataDB.erase(player->getRealName() + "-" + key); - return Boolean::newBoolean(true); - } - CATCH("Fail in delExtraData!") + return Boolean::newBoolean(true); + } + CATCH("Fail in setAbsorptionAttribute!"); } -Local PlayerClass::hurt(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local PlayerClass::setAttackDamage(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Player *player = get(); - if (!player) { - return Boolean::newBoolean(false); - } - float damage = args[0].asNumber().toFloat(); - int type = 0; - if (args.size() == 2) { - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - type = args[1].asNumber().toInt32(); - return Boolean::newBoolean( - player->hurtByCause(damage, (ActorDamageCause)type)); - } - if (args.size() == 3) { - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - auto source = EntityClass::extract(args[2]); - type = args[1].asNumber().toInt32(); - return Boolean::newBoolean( - player->hurtByCause(damage, (ActorDamageCause)type, source)); - } - return Boolean::newBoolean(false); - } - CATCH("Fail in hurt!"); -} + try { + Player* player = get(); + if (!player) return Local(); -Local PlayerClass::heal(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Player *player = get(); - if (!player) - return Local(); + AttributeInstance* attactDamageAttribute = player->getMutableAttribute(SharedAttributes::ATTACK_DAMAGE); - player->heal(args[0].toInt()); - return Boolean::newBoolean(true); - } - CATCH("Fail in heal!"); + attactDamageAttribute->setCurrentValue(args[0].asNumber().toFloat()); + + return Boolean::newBoolean(true); + } + CATCH("Fail in setAttackDamage!"); } -Local PlayerClass::setHealth(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local PlayerClass::setMaxAttackDamage(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - AttributeInstance *healthAttribute = - player->getMutableAttribute(SharedAttributes::HEALTH); + AttributeInstance* attactDamageAttribute = player->getMutableAttribute(SharedAttributes::ATTACK_DAMAGE); - healthAttribute->setCurrentValue(args[0].asNumber().toFloat()); + attactDamageAttribute->setMaxValue(args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setHealth!"); + return Boolean::newBoolean(true); + } + CATCH("Fail in setMaxAttackDamage!"); } -Local PlayerClass::setMaxHealth(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local PlayerClass::setFollowRange(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - AttributeInstance *healthAttribute = - player->getMutableAttribute(SharedAttributes::HEALTH); + AttributeInstance* followRangeAttribute = player->getMutableAttribute(SharedAttributes::FOLLOW_RANGE); - healthAttribute->setMaxValue(args[0].asNumber().toFloat()); + followRangeAttribute->setCurrentValue(args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setMaxHealth!"); + return Boolean::newBoolean(true); + } + CATCH("Fail in setFollowRange!"); } -Local PlayerClass::setAbsorption(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local PlayerClass::setKnockbackResistance(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - AttributeInstance *absorptionAttribute = - player->getMutableAttribute(SharedAttributes::ABSORPTION); + AttributeInstance* knockbackResistanceAttribute = + player->getMutableAttribute(SharedAttributes::KNOCKBACK_RESISTANCE); - absorptionAttribute->setCurrentValue(args[0].asNumber().toFloat()); + knockbackResistanceAttribute->setCurrentValue(args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setAbsorptionAttribute!"); + return Boolean::newBoolean(true); + } + CATCH("Fail in setKnockbackResistance!"); } -Local PlayerClass::setAttackDamage(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local PlayerClass::setLuck(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - AttributeInstance *attactDamageAttribute = - player->getMutableAttribute(SharedAttributes::ATTACK_DAMAGE); + AttributeInstance* luckAttribute = player->getMutableAttribute(SharedAttributes::LUCK); - attactDamageAttribute->setCurrentValue(args[0].asNumber().toFloat()); + luckAttribute->setCurrentValue(args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setAttackDamage!"); + return Boolean::newBoolean(true); + } + CATCH("Fail in setLuck!"); } -Local PlayerClass::setMaxAttackDamage(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local PlayerClass::setMovementSpeed(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - AttributeInstance *attactDamageAttribute = - player->getMutableAttribute(SharedAttributes::ATTACK_DAMAGE); + AttributeInstance* movementSpeedAttribute = player->getMutableAttribute(SharedAttributes::MOVEMENT_SPEED); - attactDamageAttribute->setMaxValue(args[0].asNumber().toFloat()); + movementSpeedAttribute->setCurrentValue(args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setMaxAttackDamage!"); + return Boolean::newBoolean(true); + } + CATCH("Fail in setMovementSpeed!"); } -Local PlayerClass::setFollowRange(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local PlayerClass::setUnderwaterMovementSpeed(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - AttributeInstance *followRangeAttribute = - player->getMutableAttribute(SharedAttributes::FOLLOW_RANGE); + AttributeInstance* underwaterMovementSpeedAttribute = + player->getMutableAttribute(SharedAttributes::UNDERWATER_MOVEMENT_SPEED); - followRangeAttribute->setCurrentValue(args[0].asNumber().toFloat()); + underwaterMovementSpeedAttribute->setCurrentValue(args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setFollowRange!"); + return Boolean::newBoolean(true); + } + CATCH("Fail in setUnderwaterMovementSpeed!"); } -Local PlayerClass::setKnockbackResistance(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local PlayerClass::setLavaMovementSpeed(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - AttributeInstance *knockbackResistanceAttribute = - player->getMutableAttribute(SharedAttributes::KNOCKBACK_RESISTANCE); + AttributeInstance* lavaMovementSpeedAttribute = + player->getMutableAttribute(SharedAttributes::LAVA_MOVEMENT_SPEED); - knockbackResistanceAttribute->setCurrentValue(args[0].asNumber().toFloat()); + lavaMovementSpeedAttribute->setCurrentValue(args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setKnockbackResistance!"); + return Boolean::newBoolean(true); + } + CATCH("Fail in setLavaMovementSpeed!"); } -Local PlayerClass::setLuck(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local PlayerClass::setHungry(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - AttributeInstance *luckAttribute = - player->getMutableAttribute(SharedAttributes::LUCK); + AttributeInstance* healthAttribute = player->getMutableAttribute(player->HUNGER); - luckAttribute->setCurrentValue(args[0].asNumber().toFloat()); + healthAttribute->setCurrentValue(args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setLuck!"); + return Boolean::newBoolean(true); + } + CATCH("Fail in setHungry!"); } -Local PlayerClass::setMovementSpeed(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - - try { - Player *player = get(); - if (!player) - return Local(); +Local PlayerClass::setFire(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kBoolean); - AttributeInstance *movementSpeedAttribute = - player->getMutableAttribute(SharedAttributes::MOVEMENT_SPEED); + try { + Player* player = get(); + if (!player) return Local(); - movementSpeedAttribute->setCurrentValue(args[0].asNumber().toFloat()); + int time = args[0].toInt(); + bool isEffectValue = args[1].asBoolean().value(); - return Boolean::newBoolean(true); - } - CATCH("Fail in setMovementSpeed!"); + player->setOnFire(time, isEffectValue); + return Boolean::newBoolean(true); + } + CATCH("Fail in setFire!"); } -Local PlayerClass::setUnderwaterMovementSpeed(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local PlayerClass::stopFire(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); + + player->stopFire(); + return Boolean::newBoolean(true); + } + CATCH("Fail in stopFire!"); +} - try { - Player *player = get(); - if (!player) - return Local(); +// For Compatibility +Local PlayerClass::setOnFire(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - AttributeInstance *underwaterMovementSpeedAttribute = - player->getMutableAttribute( - SharedAttributes::UNDERWATER_MOVEMENT_SPEED); + try { + Player* player = get(); + if (!player) return Local(); - underwaterMovementSpeedAttribute->setCurrentValue( - args[0].asNumber().toFloat()); + int time = args[0].toInt(); - return Boolean::newBoolean(true); - } - CATCH("Fail in setUnderwaterMovementSpeed!"); + player->setOnFire(time, true); + return Boolean::newBoolean(true); + } + CATCH("Fail in setOnFire!"); } -Local PlayerClass::setLavaMovementSpeed(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - - try { - Player *player = get(); - if (!player) - return Local(); +Local PlayerClass::refreshChunks(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); - AttributeInstance *lavaMovementSpeedAttribute = - player->getMutableAttribute(SharedAttributes::LAVA_MOVEMENT_SPEED); + player->resendAllChunks(); + return Boolean::newBoolean(true); + } + CATCH("Fail in refreshChunks!"); +} - lavaMovementSpeedAttribute->setCurrentValue(args[0].asNumber().toFloat()); +Local PlayerClass::giveItem(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); - return Boolean::newBoolean(true); - } - CATCH("Fail in setLavaMovementSpeed!"); + try { + Player* player = get(); + if (!player) return Local(); + + ItemStack* item = ItemClass::extract(args[0]); + if (!item) return Local(); // Null + if (args.size() >= 2) { + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + item->set(args[1].asNumber().toInt32()); + } + bool result = player->add(*item); + if (!result) { + player->drop(*item, false); + } + player->sendInventory(true); + return Boolean::newBoolean(result); + } + CATCH("Fail in giveItem!"); } -Local PlayerClass::setHungry(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local PlayerClass::clearItem(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) { + return {}; + } + unsigned int clearCount = 1; + if (args.size() > 1) { + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + clearCount = args[1].asNumber().toInt32(); + } + int result = 0; + for (std::reference_wrapper item : player->getInventory().getSlotCopies()) { + if (item.get().getTypeName() == args[0].asString().toString()) { + if (item.get().mCount < clearCount) { + result += item.get().mCount; + } + item.get().remove(clearCount); + } + } + for (std::reference_wrapper item : player->getHandContainer().getSlotCopies()) { + if (item.get().getTypeName() == args[0].asString().toString()) { + if (item.get().mCount < clearCount) { + result += item.get().mCount; + } + item.get().remove(clearCount); + } + } + for (std::reference_wrapper item : player->getArmorContainer().getSlotCopies()) { + if (item.get().getTypeName() == args[0].asString().toString()) { + if (item.get().mCount < clearCount) { + result += item.get().mCount; + } + item.get().remove(clearCount); + } + } + return Number::newNumber(result); + } + CATCH("Fail in clearItem!"); +} - AttributeInstance *healthAttribute = - player->getMutableAttribute(player->HUNGER); +Local PlayerClass::isSprinting(const Arguments& args) { + CHECK_ARGS_COUNT(args, 0); - healthAttribute->setCurrentValue(args[0].asNumber().toFloat()); + try { + Player* player = get(); + if (!player) return Local(); - return Boolean::newBoolean(true); - } - CATCH("Fail in setHungry!"); + return Boolean::newBoolean(player->isSprinting()); + } + CATCH("Fail in isSprinting!"); } -Local PlayerClass::setFire(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kBoolean); - - try { - Player *player = get(); - if (!player) - return Local(); +Local PlayerClass::setSprinting(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kBoolean); - int time = args[0].toInt(); - bool isEffectValue = args[1].asBoolean().value(); + try { + Player* player = get(); + if (!player) return Local(); - player->setOnFire(time, isEffectValue); - return Boolean::newBoolean(true); - } - CATCH("Fail in setFire!"); + player->setSprinting(args[0].asBoolean().value()); + return Boolean::newBoolean(true); + } + CATCH("Fail in setSprinting!"); } -Local PlayerClass::stopFire(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); +Local PlayerClass::getNbt(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); - player->stopFire(); - return Boolean::newBoolean(true); - } - CATCH("Fail in stopFire!"); + CompoundTag tag = CompoundTag(); + player->save(tag); + return NbtCompoundClass::pack(&tag); + } + CATCH("Fail in getNbt!") } -// For Compatibility -Local PlayerClass::setOnFire(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); +Local PlayerClass::setNbt(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - int time = args[0].toInt(); + auto nbt = NbtCompoundClass::extract(args[0]); + if (!nbt) return Local(); // Null - player->setOnFire(time, true); - return Boolean::newBoolean(true); - } - CATCH("Fail in setOnFire!"); + DefaultDataLoadHelper helper = DefaultDataLoadHelper(); + return Boolean::newBoolean(player->load(*nbt, helper)); + } + CATCH("Fail in setNbt!") } -Local PlayerClass::refreshChunks(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); +Local PlayerClass::addTag(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + Player* player = get(); + if (!player) return Local(); - player->resendAllChunks(); - return Boolean::newBoolean(true); - } - CATCH("Fail in refreshChunks!"); + return Boolean::newBoolean(player->addTag(args[0].toStr())); + } + CATCH("Fail in addTag!"); } -Local PlayerClass::giveItem(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); +Local PlayerClass::removeTag(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); - ItemStack *item = ItemClass::extract(args[0]); - if (!item) - return Local(); // Null - if (args.size() >= 2) { - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - item->set(args[1].asNumber().toInt32()); + return Boolean::newBoolean(player->removeTag(args[0].toStr())); } - bool result = player->add(*item); - if (!result) { - player->drop(*item, false); - } - player->sendInventory(true); - return Boolean::newBoolean(result); - } - CATCH("Fail in giveItem!"); + CATCH("Fail in removeTag!"); } -Local PlayerClass::clearItem(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local PlayerClass::hasTag(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + Player* player = get(); + if (!player) return Local(); - try { - Player *player = get(); - if (!player) { - return {}; + return Boolean::newBoolean(player->hasTag(args[0].toStr())); } - unsigned int clearCount = 1; - if (args.size() > 1) { - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - clearCount = args[1].asNumber().toInt32(); + CATCH("Fail in hasTag!"); +} + +Local PlayerClass::getAllTags(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); + + Local arr = Array::newArray(); + CompoundTag tag = CompoundTag(); + player->save(tag); + tag.getList("Tags")->forEachCompoundTag([&arr](const CompoundTag& tag) { + arr.add(String::newString(tag.toString())); + }); + return arr; } - int result = 0; - for (std::reference_wrapper item : - player->getInventory().getSlotCopies()) { - if (item.get().getTypeName() == args[0].asString().toString()) { - if (item.get().mCount < clearCount) { - result += item.get().mCount; + CATCH("Fail in getAllTags!"); +} + +Local PlayerClass::getAbilities(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); + + CompoundTag tag = CompoundTag(); + player->save(tag); + try { + return Tag2Value(tag.getCompound("abilities"), true); + } catch (...) { + return Object::newObject(); } - item.get().remove(clearCount); - } } - for (std::reference_wrapper item : - player->getHandContainer().getSlotCopies()) { - if (item.get().getTypeName() == args[0].asString().toString()) { - if (item.get().mCount < clearCount) { - result += item.get().mCount; + CATCH("Fail in getAbilities!"); +} + +Local PlayerClass::getAttributes(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); + + Local res = Array::newArray(); + + CompoundTag tag = CompoundTag(); + player->save(tag); + try { + Local arr = Array::newArray(); + tag.getList("Attributes")->forEachCompoundTag([&](const CompoundTag& tag) { + arr.add(Tag2Value(const_cast(&tag), true)); + }); + return arr; + } catch (...) { + return Array::newArray(); } - item.get().remove(clearCount); - } } - for (std::reference_wrapper item : - player->getArmorContainer().getSlotCopies()) { - if (item.get().getTypeName() == args[0].asString().toString()) { - if (item.get().mCount < clearCount) { - result += item.get().mCount; + CATCH("Fail in getAttributes!"); +} + +Local PlayerClass::getEntityFromViewVector(const Arguments& args) { + + try { + Player* player = get(); + if (!player) return Local(); + float maxDistance = 5.25f; + if (args.size() > 0) { + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + maxDistance = args[0].asNumber().toFloat(); } - item.get().remove(clearCount); - } + HitResult result = player->traceRay(maxDistance); + Actor* entity = result.getEntity(); + if (entity) return EntityClass::newEntity(entity); + return Local(); } - return Number::newNumber(result); - } - CATCH("Fail in clearItem!"); + CATCH("Fail in getEntityFromViewVector!"); } -Local PlayerClass::isSprinting(const Arguments &args) { - CHECK_ARGS_COUNT(args, 0); - - try { - Player *player = get(); - if (!player) - return Local(); +Local PlayerClass::getBlockFromViewVector(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); + bool includeLiquid = false; + bool solidOnly = false; // not used + float maxDistance = 5.25f; + bool ignoreBorderBlocks = true; // not used + bool fullOnly = false; // not used + if (args.size() > 0) { + CHECK_ARG_TYPE(args[0], ValueKind::kBoolean); + includeLiquid = args[0].asBoolean().value(); + } + if (args.size() > 1) { + CHECK_ARG_TYPE(args[1], ValueKind::kBoolean); + solidOnly = args[1].asBoolean().value(); + } + if (args.size() > 2) { + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + maxDistance = args[2].asNumber().toFloat(); + } + if (args.size() > 3) { + CHECK_ARG_TYPE(args[3], ValueKind::kBoolean); + fullOnly = args[3].asBoolean().value(); + } + HitResult res = player->traceRay(maxDistance, false, true); + Block bl; + BlockPos bp; + if (includeLiquid && res.mIsHitLiquid) { + bp = res.mLiquidPos; + } else { + bp = res.mBlockPos; + } + player->getDimensionBlockSource().getBlock(bp); + if (bl.isEmpty()) return Local(); + return BlockClass::newBlock(std::move(&bl), &bp, player->getDimensionId().id); + } + CATCH("Fail in getBlockFromViewVector!"); +} - return Boolean::newBoolean(player->isSprinting()); - } - CATCH("Fail in isSprinting!"); +Local PlayerClass::isSimulatedPlayer(const Arguments& args) { + try { + Player* actor = get(); + if (!actor) return Local(); + return Boolean::newBoolean(actor->isSimulatedPlayer()); + } + CATCH("Fail in isSimulatedPlayer!"); } -Local PlayerClass::setSprinting(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kBoolean); +Local PlayerClass::quickEvalMolangScript(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + try { + Player* actor = get(); + if (!actor) return Local(); + return Number::newNumber(actor->quickEvalMolangScript(args[0].toStr())); + } + CATCH("Fail in quickEvalMolangScript!"); +} - try { - Player *player = get(); - if (!player) - return Local(); +//////////////////// For LLMoney //////////////////// - player->setSprinting(args[0].asBoolean().value()); - return Boolean::newBoolean(true); - } - CATCH("Fail in setSprinting!"); +Local PlayerClass::getMoney(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); + auto xuid = player->getXuid(); + return xuid.empty() ? Local() : Number::newNumber(EconomySystem::getMoney(xuid)); + } + CATCH("Fail in getMoney!"); } -Local PlayerClass::getNbt(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); +Local PlayerClass::reduceMoney(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CompoundTag tag = CompoundTag(); - player->save(tag); - return NbtCompoundClass::pack(&tag); - } - CATCH("Fail in getNbt!") + try { + Player* player = get(); + if (!player) return Local(); + auto xuid = player->getXuid(); + return xuid.empty() ? Local() + : Boolean::newBoolean(EconomySystem::reduceMoney(xuid, args[0].asNumber().toInt64())); + } + CATCH("Fail in reduceMoney!"); } -Local PlayerClass::setNbt(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); +Local PlayerClass::setMoney(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Player *player = get(); - if (!player) - return Local(); + try { + Player* player = get(); + if (!player) return Local(); + auto xuid = player->getXuid(); + return xuid.empty() ? Local() + : Boolean::newBoolean(EconomySystem::setMoney(xuid, args[0].asNumber().toInt64())); + } + CATCH("Fail in setMoney!"); +} - auto nbt = NbtCompoundClass::extract(args[0]); - if (!nbt) - return Local(); // Null +Local PlayerClass::addMoney(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - DefaultDataLoadHelper helper = DefaultDataLoadHelper(); - return Boolean::newBoolean(player->load(*nbt, helper)); - } - CATCH("Fail in setNbt!") + try { + Player* player = get(); + if (!player) return Local(); + auto xuid = player->getXuid(); + return xuid.empty() ? Local() + : Boolean::newBoolean(EconomySystem::addMoney(xuid, args[0].asNumber().toInt64())); + } + CATCH("Fail in addMoney!"); } -Local PlayerClass::addTag(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local PlayerClass::transMoney(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + // nocheck: args[0] maybe Player or XUID. + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + + try { + Player* player = get(); + if (!player) return Local(); + auto xuid = player->getXuid(); + string targetXuid; + string note; + if (args[0].getKind() == ValueKind::kString) targetXuid = args[0].toStr(); + else targetXuid = PlayerClass::extract(args[0])->getXuid(); + if (args.size() >= 3) { + CHECK_ARG_TYPE(args[2], ValueKind::kString); + note = args[2].toStr(); + } + return xuid.empty() + ? Local() + : Boolean::newBoolean(EconomySystem::transMoney(xuid, targetXuid, args[0].asNumber().toInt64(), note)); + } + CATCH("Fail in transMoney!"); +} - try { - Player *player = get(); - if (!player) - return Local(); +Local PlayerClass::getMoneyHistory(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - return Boolean::newBoolean(player->addTag(args[0].toStr())); - } - CATCH("Fail in addTag!"); + try { + Player* player = get(); + if (!player) return Local(); + auto xuid = player->getXuid(); + return xuid.empty() ? Local() + : objectificationMoneyHistory(EconomySystem::getMoneyHist(xuid, args[0].toInt())); + } + CATCH("Fail in getMoneyHistory!"); } -Local PlayerClass::removeTag(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +//////////////////// For Compatibility //////////////////// + +Local PlayerClass::getAllItems(const Arguments& args) { + try { + Player* player = get(); + if (!player) return Local(); - try { - Player *player = get(); - if (!player) - return Local(); + const ItemStack& hand = player->getCarriedItem(); + const ItemStack& offHand = player->getOffhandSlot(); + vector inventory = player->getInventory().getSlots(); + vector armor = player->getArmorContainer().getSlots(); + vector endChest = player->getEnderChestContainer()->getSlots(); - return Boolean::newBoolean(player->removeTag(args[0].toStr())); - } - CATCH("Fail in removeTag!"); -} + Local result = Object::newObject(); -Local PlayerClass::hasTag(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); + // hand + result.set("hand", ItemClass::newItem(const_cast(&hand))); - try { - Player *player = get(); - if (!player) - return Local(); + // offHand + result.set("offHand", ItemClass::newItem(const_cast(&offHand))); - return Boolean::newBoolean(player->hasTag(args[0].toStr())); - } - CATCH("Fail in hasTag!"); -} + // inventory + Local inventoryArr = Array::newArray(); + for (const ItemStack* item : inventory) { + inventoryArr.add(ItemClass::newItem((ItemStack*)item)); + } + result.set("inventory", inventoryArr); -Local PlayerClass::getAllTags(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); + // armor + Local armorArr = Array::newArray(); + for (const ItemStack* item : armor) { + armorArr.add(ItemClass::newItem((ItemStack*)item)); + } + result.set("armor", armorArr); - Local arr = Array::newArray(); - CompoundTag tag = CompoundTag(); - player->save(tag); - tag.getList("Tags")->forEachCompoundTag([&arr](const CompoundTag &tag) { - arr.add(String::newString(tag.toString())); - }); - return arr; - } - CATCH("Fail in getAllTags!"); -} + // endChest + Local endChestArr = Array::newArray(); + for (const ItemStack* item : endChest) { + endChestArr.add(ItemClass::newItem((ItemStack*)item)); + } + result.set("endChest", endChestArr); -Local PlayerClass::getAbilities(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); + return result; + } + CATCH("Fail in getAllItems!") +} - CompoundTag tag = CompoundTag(); - player->save(tag); +Local PlayerClass::removeItem(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); try { - return Tag2Value(tag.getCompound("abilities"), true); - } catch (...) { - return Object::newObject(); + Player* player = get(); + if (!player) return Local(); + + int inventoryId = args[0].toInt(); + int count = args[1].toInt(); + + Container& container = player->getInventory(); + if (inventoryId > container.getContainerSize()) return Boolean::newBoolean(false); + container.removeItem(inventoryId, count); + return Boolean::newBoolean(true); } - } - CATCH("Fail in getAbilities!"); + CATCH("Fail in removeItem!") } -Local PlayerClass::getAttributes(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); +Local PlayerClass::sendToast(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kString); + try { + Player* player = get(); - Local res = Array::newArray(); + if (!player) return Local(); - CompoundTag tag = CompoundTag(); - player->save(tag); - try { - Local arr = Array::newArray(); - tag.getList("Attributes") - ->forEachCompoundTag([&](const CompoundTag &tag) { - arr.add(Tag2Value(const_cast(&tag), true)); - }); - return arr; - } catch (...) { - return Array::newArray(); + ToastRequestPacket pkt = ToastRequestPacket(args[0].asString().toString(), args[1].asString().toString()); + player->sendNetworkPacket(pkt); + return Boolean::newBoolean(true); } - } - CATCH("Fail in getAttributes!"); + CATCH("Fail in sendToast!"); } -Local PlayerClass::getEntityFromViewVector(const Arguments &args) { +Local PlayerClass::distanceTo(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + + try { + FloatVec4 pos{}; + + Player* player = get(); + if (!player) return Local(); + + if (args.size() == 1) { // pos | player | entity + if (IsInstanceOf(args[0])) { + // IntPos + IntPos* posObj = IntPos::extractPos(args[0]); + if (posObj->dim < 0) return Local(); + else { + pos.x = posObj->x; + pos.y = posObj->y; + pos.z = posObj->z; + pos.dim = posObj->dim; + } + } else if (IsInstanceOf(args[0])) { + // FloatPos + FloatPos* posObj = FloatPos::extractPos(args[0]); + if (posObj->dim < 0) return Local(); + else { + pos = *posObj; + } + } else if (IsInstanceOf(args[0]) || IsInstanceOf(args[0])) { + // Player or Entity + + Actor* targetActor = EntityClass::tryExtractActor(args[0]).value(); + if (!targetActor) return Local(); + + Vec3 targetActorPos = targetActor->getPosition(); + + pos.x = targetActorPos.x; + pos.y = targetActorPos.y; + pos.z = targetActorPos.z; + pos.dim = targetActor->getDimensionId(); + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + } else if (args.size() == 4) { // x, y, z, dimId + // number pos + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + + pos.x = args[0].asNumber().toFloat(); + pos.y = args[1].asNumber().toFloat(); + pos.z = args[2].asNumber().toFloat(); + pos.dim = args[3].toInt(); + } else { + LOG_WRONG_ARGS_COUNT(); + return Local(); + } - try { - Player *player = get(); - if (!player) - return Local(); - float maxDistance = 5.25f; - if (args.size() > 0) { - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - maxDistance = args[0].asNumber().toFloat(); + if (player->getDimensionId() != pos.dim) return Number::newNumber(INT_MAX); + + return Number::newNumber(player->distanceTo(pos.getVec3())); } - HitResult result = player->traceRay(maxDistance); - Actor *entity = result.getEntity(); - if (entity) - return EntityClass::newEntity(entity); - return Local(); - } - CATCH("Fail in getEntityFromViewVector!"); -} - -Local PlayerClass::getBlockFromViewVector(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); - bool includeLiquid = false; - bool solidOnly = false; // not used - float maxDistance = 5.25f; - bool ignoreBorderBlocks = true; // not used - bool fullOnly = false; // not used - if (args.size() > 0) { - CHECK_ARG_TYPE(args[0], ValueKind::kBoolean); - includeLiquid = args[0].asBoolean().value(); - } - if (args.size() > 1) { - CHECK_ARG_TYPE(args[1], ValueKind::kBoolean); - solidOnly = args[1].asBoolean().value(); - } - if (args.size() > 2) { - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - maxDistance = args[2].asNumber().toFloat(); - } - if (args.size() > 3) { - CHECK_ARG_TYPE(args[3], ValueKind::kBoolean); - fullOnly = args[3].asBoolean().value(); - } - HitResult res = player->traceRay(maxDistance, false, true); - Block bl; - BlockPos bp; - if (includeLiquid && res.mIsHitLiquid) { - bp = res.mLiquidPos; - } else { - bp = res.mBlockPos; - } - player->getDimensionBlockSource().getBlock(bp); - if (bl.isEmpty()) - return Local(); - return BlockClass::newBlock(std::move(&bl), &bp, - player->getDimensionId().id); - } - CATCH("Fail in getBlockFromViewVector!"); -} - -Local PlayerClass::isSimulatedPlayer(const Arguments &args) { - try { - Player *actor = get(); - if (!actor) - return Local(); - return Boolean::newBoolean(actor->isSimulatedPlayer()); - } - CATCH("Fail in isSimulatedPlayer!"); -} - -Local PlayerClass::quickEvalMolangScript(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - Player *actor = get(); - if (!actor) - return Local(); - return Number::newNumber(actor->quickEvalMolangScript(args[0].toStr())); - } - CATCH("Fail in quickEvalMolangScript!"); + CATCH("Fail in distanceTo!") } -//////////////////// For LLMoney //////////////////// +Local PlayerClass::distanceToSqr(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + + try { + FloatVec4 pos; + + Player* player = get(); + if (!player) return Local(); + + if (args.size() == 1) { + if (IsInstanceOf(args[0])) { + // IntPos + IntPos* posObj = IntPos::extractPos(args[0]); + if (posObj->dim < 0) return Local(); + else { + pos.x = posObj->x; + pos.y = posObj->y; + pos.z = posObj->z; + pos.dim = posObj->dim; + } + } else if (IsInstanceOf(args[0])) { + // FloatPos + FloatPos* posObj = FloatPos::extractPos(args[0]); + if (posObj->dim < 0) return Local(); + else { + pos = *posObj; + } + } else if (IsInstanceOf(args[0]) || IsInstanceOf(args[0])) { + // Player or Entity + + Actor* targetActor = EntityClass::tryExtractActor(args[0]).value(); + if (!targetActor) return Local(); + + Vec3 targetActorPos = targetActor->getPosition(); + + pos.x = targetActorPos.x; + pos.y = targetActorPos.y; + pos.z = targetActorPos.z; + pos.dim = targetActor->getDimensionId(); + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + } else if (args.size() == 4) { + // number pos + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + + pos.x = args[0].asNumber().toFloat(); + pos.y = args[1].asNumber().toFloat(); + pos.z = args[2].asNumber().toFloat(); + pos.dim = args[3].toInt(); + } else { + LOG_WRONG_ARGS_COUNT(); + return Local(); + } -Local PlayerClass::getMoney(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); - auto xuid = player->getXuid(); - return xuid.empty() ? Local() - : Number::newNumber(EconomySystem::getMoney(xuid)); - } - CATCH("Fail in getMoney!"); -} - -Local PlayerClass::reduceMoney(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - - try { - Player *player = get(); - if (!player) - return Local(); - auto xuid = player->getXuid(); - return xuid.empty() ? Local() - : Boolean::newBoolean(EconomySystem::reduceMoney( - xuid, args[0].asNumber().toInt64())); - } - CATCH("Fail in reduceMoney!"); -} - -Local PlayerClass::setMoney(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - - try { - Player *player = get(); - if (!player) - return Local(); - auto xuid = player->getXuid(); - return xuid.empty() ? Local() - : Boolean::newBoolean(EconomySystem::setMoney( - xuid, args[0].asNumber().toInt64())); - } - CATCH("Fail in setMoney!"); -} - -Local PlayerClass::addMoney(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - - try { - Player *player = get(); - if (!player) - return Local(); - auto xuid = player->getXuid(); - return xuid.empty() ? Local() - : Boolean::newBoolean(EconomySystem::addMoney( - xuid, args[0].asNumber().toInt64())); - } - CATCH("Fail in addMoney!"); -} - -Local PlayerClass::transMoney(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - // nocheck: args[0] maybe Player or XUID. - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - - try { - Player *player = get(); - if (!player) - return Local(); - auto xuid = player->getXuid(); - string targetXuid; - string note; - if (args[0].getKind() == ValueKind::kString) - targetXuid = args[0].toStr(); - else - targetXuid = PlayerClass::extract(args[0])->getXuid(); - if (args.size() >= 3) { - CHECK_ARG_TYPE(args[2], ValueKind::kString); - note = args[2].toStr(); - } - return xuid.empty() - ? Local() - : Boolean::newBoolean(EconomySystem::transMoney( - xuid, targetXuid, args[0].asNumber().toInt64(), note)); - } - CATCH("Fail in transMoney!"); -} - -Local PlayerClass::getMoneyHistory(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - - try { - Player *player = get(); - if (!player) - return Local(); - auto xuid = player->getXuid(); - return xuid.empty() - ? Local() - : objectificationMoneyHistory( - EconomySystem::getMoneyHist(xuid, args[0].toInt())); - } - CATCH("Fail in getMoneyHistory!"); + if (player->getDimensionId() != pos.dim) return Number::newNumber(INT_MAX); + + return Number::newNumber(player->distanceToSqr(pos.getVec3())); + } + CATCH("Fail in distanceToSqr!") } -//////////////////// For Compatibility //////////////////// +Local PlayerClass::setAbility(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kBoolean); -Local PlayerClass::getAllItems(const Arguments &args) { - try { - Player *player = get(); - if (!player) - return Local(); - - const ItemStack &hand = player->getCarriedItem(); - const ItemStack &offHand = player->getOffhandSlot(); - vector inventory = player->getInventory().getSlots(); - vector armor = player->getArmorContainer().getSlots(); - vector endChest = - player->getEnderChestContainer()->getSlots(); - - Local result = Object::newObject(); - - // hand - result.set("hand", ItemClass::newItem(const_cast(&hand))); - - // offHand - result.set("offHand", - ItemClass::newItem(const_cast(&offHand))); - - // inventory - Local inventoryArr = Array::newArray(); - for (const ItemStack *item : inventory) { - inventoryArr.add(ItemClass::newItem((ItemStack *)item)); - } - result.set("inventory", inventoryArr); - - // armor - Local armorArr = Array::newArray(); - for (const ItemStack *item : armor) { - armorArr.add(ItemClass::newItem((ItemStack *)item)); - } - result.set("armor", armorArr); - - // endChest - Local endChestArr = Array::newArray(); - for (const ItemStack *item : endChest) { - endChestArr.add(ItemClass::newItem((ItemStack *)item)); - } - result.set("endChest", endChestArr); - - return result; - } - CATCH("Fail in getAllItems!") -} - -Local PlayerClass::removeItem(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - try { - Player *player = get(); - if (!player) - return Local(); - - int inventoryId = args[0].toInt(); - int count = args[1].toInt(); - - Container &container = player->getInventory(); - if (inventoryId > container.getContainerSize()) - return Boolean::newBoolean(false); - container.removeItem(inventoryId, count); - return Boolean::newBoolean(true); - } - CATCH("Fail in removeItem!") -} - -Local PlayerClass::sendToast(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kString); - try { - Player *player = get(); - - if (!player) - return Local(); - - ToastRequestPacket pkt = ToastRequestPacket(args[0].asString().toString(), - args[1].asString().toString()); - player->sendNetworkPacket(pkt); - return Boolean::newBoolean(true); - } - CATCH("Fail in sendToast!"); -} - -Local PlayerClass::distanceTo(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - - try { - FloatVec4 pos{}; - - Player *player = get(); - if (!player) - return Local(); - - if (args.size() == 1) { // pos | player | entity - if (IsInstanceOf(args[0])) { - // IntPos - IntPos *posObj = IntPos::extractPos(args[0]); - if (posObj->dim < 0) - return Local(); - else { - pos.x = posObj->x; - pos.y = posObj->y; - pos.z = posObj->z; - pos.dim = posObj->dim; - } - } else if (IsInstanceOf(args[0])) { - // FloatPos - FloatPos *posObj = FloatPos::extractPos(args[0]); - if (posObj->dim < 0) - return Local(); - else { - pos = *posObj; - } - } else if (IsInstanceOf(args[0]) || - IsInstanceOf(args[0])) { - // Player or Entity - - Actor *targetActor = EntityClass::tryExtractActor(args[0]).value(); - if (!targetActor) - return Local(); - - Vec3 targetActorPos = targetActor->getPosition(); - - pos.x = targetActorPos.x; - pos.y = targetActorPos.y; - pos.z = targetActorPos.z; - pos.dim = targetActor->getDimensionId(); - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - } else if (args.size() == 4) { // x, y, z, dimId - // number pos - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - - pos.x = args[0].asNumber().toFloat(); - pos.y = args[1].asNumber().toFloat(); - pos.z = args[2].asNumber().toFloat(); - pos.dim = args[3].toInt(); - } else { - LOG_WRONG_ARGS_COUNT(); - return Local(); - } - - if (player->getDimensionId() != pos.dim) - return Number::newNumber(INT_MAX); - - return Number::newNumber(player->distanceTo(pos.getVec3())); - } - CATCH("Fail in distanceTo!") -} - -Local PlayerClass::distanceToSqr(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - - try { - FloatVec4 pos; - - Player *player = get(); - if (!player) - return Local(); - - if (args.size() == 1) { - if (IsInstanceOf(args[0])) { - // IntPos - IntPos *posObj = IntPos::extractPos(args[0]); - if (posObj->dim < 0) - return Local(); - else { - pos.x = posObj->x; - pos.y = posObj->y; - pos.z = posObj->z; - pos.dim = posObj->dim; - } - } else if (IsInstanceOf(args[0])) { - // FloatPos - FloatPos *posObj = FloatPos::extractPos(args[0]); - if (posObj->dim < 0) - return Local(); - else { - pos = *posObj; - } - } else if (IsInstanceOf(args[0]) || - IsInstanceOf(args[0])) { - // Player or Entity - - Actor *targetActor = EntityClass::tryExtractActor(args[0]).value(); - if (!targetActor) - return Local(); - - Vec3 targetActorPos = targetActor->getPosition(); - - pos.x = targetActorPos.x; - pos.y = targetActorPos.y; - pos.z = targetActorPos.z; - pos.dim = targetActor->getDimensionId(); - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - } else if (args.size() == 4) { - // number pos - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - - pos.x = args[0].asNumber().toFloat(); - pos.y = args[1].asNumber().toFloat(); - pos.z = args[2].asNumber().toFloat(); - pos.dim = args[3].toInt(); - } else { - LOG_WRONG_ARGS_COUNT(); - return Local(); - } - - if (player->getDimensionId() != pos.dim) - return Number::newNumber(INT_MAX); - - return Number::newNumber(player->distanceToSqr(pos.getVec3())); - } - CATCH("Fail in distanceToSqr!") -} - -Local PlayerClass::setAbility(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kBoolean); - - try { - Player *player = get(); - if (!player) - return Local(); - bool value = args[1].asBoolean().value(); - AbilitiesIndex index = AbilitiesIndex(args[0].asNumber().toInt32()); - ActorUniqueID uid = player->getOrCreateUniqueID(); - auto &abilities = player->getAbilities(); - bool flying = abilities.getAbility(AbilitiesIndex::Flying).getBool(); - if (index == AbilitiesIndex::Flying && value && player->isOnGround()) { - abilities.setAbility(AbilitiesIndex::MayFly, value); - } - if (index == AbilitiesIndex::MayFly && value == false && flying) { - abilities.setAbility(AbilitiesIndex::Flying, false); - } - abilities.setAbility(index, value); - auto mayfly = abilities.getAbility(AbilitiesIndex::MayFly).getBool(); - auto noclip = abilities.getAbility(AbilitiesIndex::NoClip).getBool(); - player->setCanFly(mayfly || noclip); - if (index == AbilitiesIndex::NoClip) { - abilities.setAbility(AbilitiesIndex::Flying, value); - } - flying = abilities.getAbility(AbilitiesIndex::Flying).getBool(); - Ability &ab = - abilities.getAbility(AbilitiesLayer(1), AbilitiesIndex::Flying); - ab.setBool(0); - if (flying) - ab.setBool(1); - UpdateAbilitiesPacket pkt(uid, abilities); - UpdateAdventureSettingsPacket pkt2 = - UpdateAdventureSettingsPacket(AdventureSettings()); - abilities.setAbility(AbilitiesIndex::Flying, flying); - player->sendNetworkPacket(pkt2); - player->sendNetworkPacket(pkt); - return Boolean::newBoolean(true); - } - CATCH("Fail in setAbility!"); + try { + Player* player = get(); + if (!player) return Local(); + bool value = args[1].asBoolean().value(); + AbilitiesIndex index = AbilitiesIndex(args[0].asNumber().toInt32()); + ActorUniqueID uid = player->getOrCreateUniqueID(); + auto& abilities = player->getAbilities(); + bool flying = abilities.getAbility(AbilitiesIndex::Flying).getBool(); + if (index == AbilitiesIndex::Flying && value && player->isOnGround()) { + abilities.setAbility(AbilitiesIndex::MayFly, value); + } + if (index == AbilitiesIndex::MayFly && value == false && flying) { + abilities.setAbility(AbilitiesIndex::Flying, false); + } + abilities.setAbility(index, value); + auto mayfly = abilities.getAbility(AbilitiesIndex::MayFly).getBool(); + auto noclip = abilities.getAbility(AbilitiesIndex::NoClip).getBool(); + player->setCanFly(mayfly || noclip); + if (index == AbilitiesIndex::NoClip) { + abilities.setAbility(AbilitiesIndex::Flying, value); + } + flying = abilities.getAbility(AbilitiesIndex::Flying).getBool(); + Ability& ab = abilities.getAbility(AbilitiesLayer(1), AbilitiesIndex::Flying); + ab.setBool(0); + if (flying) ab.setBool(1); + UpdateAbilitiesPacket pkt(uid, abilities); + UpdateAdventureSettingsPacket pkt2 = UpdateAdventureSettingsPacket(AdventureSettings()); + abilities.setAbility(AbilitiesIndex::Flying, flying); + player->sendNetworkPacket(pkt2); + player->sendNetworkPacket(pkt); + return Boolean::newBoolean(true); + } + CATCH("Fail in setAbility!"); } Local PlayerClass::getBiomeId() { - try { - Player *player = get(); - if (!player) - return Local(); - Biome bio = - player->getDimensionBlockSource().getBiome(player->getFeetBlockPos()); - return Number::newNumber(bio.getId()); - } - CATCH("Fail in getBiomeId!"); + try { + Player* player = get(); + if (!player) return Local(); + Biome bio = player->getDimensionBlockSource().getBiome(player->getFeetBlockPos()); + return Number::newNumber(bio.getId()); + } + CATCH("Fail in getBiomeId!"); } Local PlayerClass::getBiomeName() { - try { - Player *player = get(); - if (!player) - return Local(); - Biome bio = - player->getDimensionBlockSource().getBiome(player->getFeetBlockPos()); - return String::newString(bio.getName()); - } - CATCH("Fail in getBiomeName!"); + try { + Player* player = get(); + if (!player) return Local(); + Biome bio = player->getDimensionBlockSource().getBiome(player->getFeetBlockPos()); + return String::newString(bio.getName()); + } + CATCH("Fail in getBiomeName!"); } Local PlayerClass::getAllEffects() { - try { - Player *player = get(); - if (!player) { - return Local(); - } - Local effectList = Array::newArray(); - for (unsigned int i = 0; i <= 30; i++) { - if (player->getEffect(i)) { - effectList.add(Number::newNumber((int)i)); - } - } - return effectList; - } - CATCH("Fail in getAllEffects!") -} - -Local PlayerClass::addEffect(const Arguments &args) { - CHECK_ARGS_COUNT(args, 4); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - CHECK_ARG_TYPE(args[3], ValueKind::kBoolean); - try { - Player *player = get(); - if (!player) { - return Boolean::newBoolean(false); - } - unsigned int id = args[0].asNumber().toInt32(); - int tick = args[1].asNumber().toInt32(); - int level = args[2].asNumber().toInt32(); - bool showParticles = args[3].asBoolean().value(); - MobEffectInstance effect = - MobEffectInstance(id, tick, level, false, showParticles, false); - player->addEffect(effect); - return Boolean::newBoolean(true); - } - CATCH("Fail in addEffect!"); -} - -Local PlayerClass::removeEffect(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - Player *player = get(); - if (!player) { - return Boolean::newBoolean(false); - } - int id = args[0].asNumber().toInt32(); - player->removeEffect(id); - return Boolean::newBoolean(true); - } - CATCH("Fail in removeEffect!"); + try { + Player* player = get(); + if (!player) { + return Local(); + } + Local effectList = Array::newArray(); + for (unsigned int i = 0; i <= 30; i++) { + if (player->getEffect(i)) { + effectList.add(Number::newNumber((int)i)); + } + } + return effectList; + } + CATCH("Fail in getAllEffects!") +} + +Local PlayerClass::addEffect(const Arguments& args) { + CHECK_ARGS_COUNT(args, 4); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + CHECK_ARG_TYPE(args[3], ValueKind::kBoolean); + try { + Player* player = get(); + if (!player) { + return Boolean::newBoolean(false); + } + unsigned int id = args[0].asNumber().toInt32(); + int tick = args[1].asNumber().toInt32(); + int level = args[2].asNumber().toInt32(); + bool showParticles = args[3].asBoolean().value(); + MobEffectInstance effect = MobEffectInstance(id, tick, level, false, showParticles, false); + player->addEffect(effect); + return Boolean::newBoolean(true); + } + CATCH("Fail in addEffect!"); +} + +Local PlayerClass::removeEffect(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + try { + Player* player = get(); + if (!player) { + return Boolean::newBoolean(false); + } + int id = args[0].asNumber().toInt32(); + player->removeEffect(id); + return Boolean::newBoolean(true); + } + CATCH("Fail in removeEffect!"); } diff --git a/src/api/PlayerAPI.h b/src/api/PlayerAPI.h index 2325459c..e747a7f0 100644 --- a/src/api/PlayerAPI.h +++ b/src/api/PlayerAPI.h @@ -9,220 +9,220 @@ class Player; class ActorUniqueID; class PlayerClass : public ScriptClass { private: - ActorUniqueID id; - bool isValid = true; + ActorUniqueID id; + bool isValid = true; public: - explicit PlayerClass(Player *p); - - void set(Player *player); - Player *get(); - SimulatedPlayer *asSimulatedPlayer(); - - static Local newPlayer(Player *p); - static Player *extract(Local v); - Local asPointer(const Arguments &args); - - Local getName(); - Local getPos(); - Local getFeetPos(); - Local getBlockPos(); - Local getLastDeathPos(); - Local getRealName(); - Local getXuid(); - Local getUuid(); - Local getPermLevel(); - Local getGameMode(); - Local getCanSleep(); - Local getCanFly(); - Local getCanBeSeenOnMap(); - Local getCanFreeze(); - Local getCanSeeDaylight(); - Local getCanShowNameTag(); - Local getCanStartSleepInBed(); - Local getCanPickupItems(); - Local getMaxHealth(); - Local getHealth(); - Local getInAir(); - Local getInWater(); - Local getInLava(); - Local getInRain(); - Local getInSnow(); - Local getInWall(); - Local getInWaterOrRain(); - Local getInWorld(); - Local getInClouds(); - Local getSpeed(); - Local getDirection(); - Local getUniqueID(); - Local getLangCode(); - Local getBiomeName(); - Local getBiomeId(); - Local isLoading(); - Local isInvisible(); - Local isInsidePortal(); - Local isHurt(); - Local isTrusting(); - Local isTouchingDamageBlock(); - Local isHungry(); - Local isOnFire(); - Local isOnGround(); - Local isOnHotBlock(); - Local isTrading(); - Local isAdventure(); - Local isGliding(); - Local isSurvival(); - Local isSpectator(); - Local isRiding(); - Local isDancing(); - Local isCreative(); - Local isFlying(); - Local isSleeping(); - Local isMoving(); - Local isSneaking(); - - Local isOP(const Arguments &args); - Local setPermLevel(const Arguments &args); - Local setGameMode(const Arguments &args); - - Local runcmd(const Arguments &args); - Local teleport(const Arguments &args); - Local kill(const Arguments &args); - Local kick(const Arguments &args); - Local tell(const Arguments &args); - Local setTitle(const Arguments &args); - Local talkAs(const Arguments &args); - Local talkTo(const Arguments &args); - Local rename(const Arguments &args); - Local transServer(const Arguments &args); - Local crash(const Arguments &args); - Local hurt(const Arguments &args); - Local heal(const Arguments &args); - Local setHealth(const Arguments &args); - Local setMaxHealth(const Arguments &args); - Local setAbsorption(const Arguments &args); - Local setAttackDamage(const Arguments &args); - Local setMaxAttackDamage(const Arguments &args); - Local setFollowRange(const Arguments &args); - Local setKnockbackResistance(const Arguments &args); - Local setLuck(const Arguments &args); - Local setMovementSpeed(const Arguments &args); - Local setUnderwaterMovementSpeed(const Arguments &args); - Local setLavaMovementSpeed(const Arguments &args); - Local setHungry(const Arguments &args); - Local setOnFire(const Arguments &args); - Local setFire(const Arguments &args); - Local stopFire(const Arguments &args); - Local refreshChunks(const Arguments &args); - Local giveItem(const Arguments &args); - Local clearItem(const Arguments &args); - Local isSprinting(const Arguments &args); - Local setSprinting(const Arguments &args); - Local sendToast(const Arguments &args); - Local distanceTo(const Arguments &args); - Local distanceToSqr(const Arguments &args); - - Local getBlockStandingOn(const Arguments &args); - Local getDevice(const Arguments &args); - Local getHand(const Arguments &args); - Local getOffHand(const Arguments &args); - Local getInventory(const Arguments &args); - Local getArmor(const Arguments &args); - Local getEnderChest(const Arguments &args); - Local getRespawnPosition(const Arguments &args); - Local setRespawnPosition(const Arguments &args); - Local refreshItems(const Arguments &args); - - Local getScore(const Arguments &args); - Local setScore(const Arguments &args); - Local addScore(const Arguments &args); - Local reduceScore(const Arguments &args); - Local deleteScore(const Arguments &args); - Local setSidebar(const Arguments &args); - Local removeSidebar(const Arguments &args); - Local setBossBar(const Arguments &args); - Local removeBossBar(const Arguments &args); - Local addLevel(const Arguments &args); - Local reduceLevel(const Arguments &args); - Local getLevel(const Arguments &arg); - Local setLevel(const Arguments &arg); - Local resetLevel(const Arguments &arg); - Local setScale(const Arguments &arg); - Local addExperience(const Arguments &args); - Local reduceExperience(const Arguments &args); - Local getCurrentExperience(const Arguments &arg); - Local setCurrentExperience(const Arguments &arg); - Local getTotalExperience(const Arguments &arg); - Local setTotalExperience(const Arguments &arg); - Local getXpNeededForNextLevel(const Arguments &arg); - - Local sendSimpleForm(const Arguments &args); - Local sendModalForm(const Arguments &args); - Local sendCustomForm(const Arguments &args); - Local sendForm(const Arguments &args); - Local sendPacket(const Arguments &args); - - Local setExtraData(const Arguments &args); - Local getExtraData(const Arguments &args); - Local delExtraData(const Arguments &args); - - Local getNbt(const Arguments &args); - Local setNbt(const Arguments &args); - Local addTag(const Arguments &args); - Local hasTag(const Arguments &args); - Local removeTag(const Arguments &args); - Local getAllTags(const Arguments &args); - Local getAbilities(const Arguments &args); - Local getAttributes(const Arguments &args); - Local getEntityFromViewVector(const Arguments &args); - Local getBlockFromViewVector(const Arguments &args); - - Local isSimulatedPlayer(const Arguments &args); - Local quickEvalMolangScript(const Arguments &args); - - Local getAllEffects(); - Local addEffect(const Arguments &args); - Local removeEffect(const Arguments &args); - - // LLMoney - - Local getMoney(const Arguments &args); - Local setMoney(const Arguments &args); - Local reduceMoney(const Arguments &args); - Local addMoney(const Arguments &args); - Local transMoney(const Arguments &args); - Local getMoneyHistory(const Arguments &args); - - // SimulatedPlayer API (API/SimulatedPlayerAPI.cpp) - - Local simulateRespawn(const Arguments &args); - Local simulateSneak(const Arguments &args); - Local simulateAttack(const Arguments &args); - Local simulateDestroy(const Arguments &args); - Local simulateDisconnect(const Arguments &args); - Local simulateInteract(const Arguments &args); - Local simulateJump(const Arguments &args); - Local simulateLocalMove(const Arguments &args); - Local simulateWorldMove(const Arguments &args); - Local simulateMoveTo(const Arguments &args); - Local simulateLookAt(const Arguments &args); - Local simulateSetBodyRotation(const Arguments &args); - Local simulateNavigateTo(const Arguments &args); - Local simulateUseItem(const Arguments &args); - Local simulateStopDestroyingBlock(const Arguments &args); - Local simulateStopInteracting(const Arguments &args); - Local simulateStopMoving(const Arguments &args); - Local simulateStopUsingItem(const Arguments &args); - Local simulateStopSneaking(const Arguments &args); - - // bool simulateSetItem(class ItemStack&, bool, int); - // bool simulateGiveItem(class ItemStack&, bool); - - // For Compatibility - Local getIP(); - Local getAllItems(const Arguments &args); - Local removeItem(const Arguments &args); - - Local setAbility(const Arguments &args); + explicit PlayerClass(Player* p); + + void set(Player* player); + Player* get(); + SimulatedPlayer* asSimulatedPlayer(); + + static Local newPlayer(Player* p); + static Player* extract(Local v); + Local asPointer(const Arguments& args); + + Local getName(); + Local getPos(); + Local getFeetPos(); + Local getBlockPos(); + Local getLastDeathPos(); + Local getRealName(); + Local getXuid(); + Local getUuid(); + Local getPermLevel(); + Local getGameMode(); + Local getCanSleep(); + Local getCanFly(); + Local getCanBeSeenOnMap(); + Local getCanFreeze(); + Local getCanSeeDaylight(); + Local getCanShowNameTag(); + Local getCanStartSleepInBed(); + Local getCanPickupItems(); + Local getMaxHealth(); + Local getHealth(); + Local getInAir(); + Local getInWater(); + Local getInLava(); + Local getInRain(); + Local getInSnow(); + Local getInWall(); + Local getInWaterOrRain(); + Local getInWorld(); + Local getInClouds(); + Local getSpeed(); + Local getDirection(); + Local getUniqueID(); + Local getLangCode(); + Local getBiomeName(); + Local getBiomeId(); + Local isLoading(); + Local isInvisible(); + Local isInsidePortal(); + Local isHurt(); + Local isTrusting(); + Local isTouchingDamageBlock(); + Local isHungry(); + Local isOnFire(); + Local isOnGround(); + Local isOnHotBlock(); + Local isTrading(); + Local isAdventure(); + Local isGliding(); + Local isSurvival(); + Local isSpectator(); + Local isRiding(); + Local isDancing(); + Local isCreative(); + Local isFlying(); + Local isSleeping(); + Local isMoving(); + Local isSneaking(); + + Local isOP(const Arguments& args); + Local setPermLevel(const Arguments& args); + Local setGameMode(const Arguments& args); + + Local runcmd(const Arguments& args); + Local teleport(const Arguments& args); + Local kill(const Arguments& args); + Local kick(const Arguments& args); + Local tell(const Arguments& args); + Local setTitle(const Arguments& args); + Local talkAs(const Arguments& args); + Local talkTo(const Arguments& args); + Local rename(const Arguments& args); + Local transServer(const Arguments& args); + Local crash(const Arguments& args); + Local hurt(const Arguments& args); + Local heal(const Arguments& args); + Local setHealth(const Arguments& args); + Local setMaxHealth(const Arguments& args); + Local setAbsorption(const Arguments& args); + Local setAttackDamage(const Arguments& args); + Local setMaxAttackDamage(const Arguments& args); + Local setFollowRange(const Arguments& args); + Local setKnockbackResistance(const Arguments& args); + Local setLuck(const Arguments& args); + Local setMovementSpeed(const Arguments& args); + Local setUnderwaterMovementSpeed(const Arguments& args); + Local setLavaMovementSpeed(const Arguments& args); + Local setHungry(const Arguments& args); + Local setOnFire(const Arguments& args); + Local setFire(const Arguments& args); + Local stopFire(const Arguments& args); + Local refreshChunks(const Arguments& args); + Local giveItem(const Arguments& args); + Local clearItem(const Arguments& args); + Local isSprinting(const Arguments& args); + Local setSprinting(const Arguments& args); + Local sendToast(const Arguments& args); + Local distanceTo(const Arguments& args); + Local distanceToSqr(const Arguments& args); + + Local getBlockStandingOn(const Arguments& args); + Local getDevice(const Arguments& args); + Local getHand(const Arguments& args); + Local getOffHand(const Arguments& args); + Local getInventory(const Arguments& args); + Local getArmor(const Arguments& args); + Local getEnderChest(const Arguments& args); + Local getRespawnPosition(const Arguments& args); + Local setRespawnPosition(const Arguments& args); + Local refreshItems(const Arguments& args); + + Local getScore(const Arguments& args); + Local setScore(const Arguments& args); + Local addScore(const Arguments& args); + Local reduceScore(const Arguments& args); + Local deleteScore(const Arguments& args); + Local setSidebar(const Arguments& args); + Local removeSidebar(const Arguments& args); + Local setBossBar(const Arguments& args); + Local removeBossBar(const Arguments& args); + Local addLevel(const Arguments& args); + Local reduceLevel(const Arguments& args); + Local getLevel(const Arguments& arg); + Local setLevel(const Arguments& arg); + Local resetLevel(const Arguments& arg); + Local setScale(const Arguments& arg); + Local addExperience(const Arguments& args); + Local reduceExperience(const Arguments& args); + Local getCurrentExperience(const Arguments& arg); + Local setCurrentExperience(const Arguments& arg); + Local getTotalExperience(const Arguments& arg); + Local setTotalExperience(const Arguments& arg); + Local getXpNeededForNextLevel(const Arguments& arg); + + Local sendSimpleForm(const Arguments& args); + Local sendModalForm(const Arguments& args); + Local sendCustomForm(const Arguments& args); + Local sendForm(const Arguments& args); + Local sendPacket(const Arguments& args); + + Local setExtraData(const Arguments& args); + Local getExtraData(const Arguments& args); + Local delExtraData(const Arguments& args); + + Local getNbt(const Arguments& args); + Local setNbt(const Arguments& args); + Local addTag(const Arguments& args); + Local hasTag(const Arguments& args); + Local removeTag(const Arguments& args); + Local getAllTags(const Arguments& args); + Local getAbilities(const Arguments& args); + Local getAttributes(const Arguments& args); + Local getEntityFromViewVector(const Arguments& args); + Local getBlockFromViewVector(const Arguments& args); + + Local isSimulatedPlayer(const Arguments& args); + Local quickEvalMolangScript(const Arguments& args); + + Local getAllEffects(); + Local addEffect(const Arguments& args); + Local removeEffect(const Arguments& args); + + // LLMoney + + Local getMoney(const Arguments& args); + Local setMoney(const Arguments& args); + Local reduceMoney(const Arguments& args); + Local addMoney(const Arguments& args); + Local transMoney(const Arguments& args); + Local getMoneyHistory(const Arguments& args); + + // SimulatedPlayer API (API/SimulatedPlayerAPI.cpp) + + Local simulateRespawn(const Arguments& args); + Local simulateSneak(const Arguments& args); + Local simulateAttack(const Arguments& args); + Local simulateDestroy(const Arguments& args); + Local simulateDisconnect(const Arguments& args); + Local simulateInteract(const Arguments& args); + Local simulateJump(const Arguments& args); + Local simulateLocalMove(const Arguments& args); + Local simulateWorldMove(const Arguments& args); + Local simulateMoveTo(const Arguments& args); + Local simulateLookAt(const Arguments& args); + Local simulateSetBodyRotation(const Arguments& args); + Local simulateNavigateTo(const Arguments& args); + Local simulateUseItem(const Arguments& args); + Local simulateStopDestroyingBlock(const Arguments& args); + Local simulateStopInteracting(const Arguments& args); + Local simulateStopMoving(const Arguments& args); + Local simulateStopUsingItem(const Arguments& args); + Local simulateStopSneaking(const Arguments& args); + + // bool simulateSetItem(class ItemStack&, bool, int); + // bool simulateGiveItem(class ItemStack&, bool); + + // For Compatibility + Local getIP(); + Local getAllItems(const Arguments& args); + Local removeItem(const Arguments& args); + + Local setAbility(const Arguments& args); }; extern ClassDefine PlayerClassBuilder; \ No newline at end of file diff --git a/src/api/ScoreboardAPI.cpp b/src/api/ScoreboardAPI.cpp index ed37acc3..01065610 100644 --- a/src/api/ScoreboardAPI.cpp +++ b/src/api/ScoreboardAPI.cpp @@ -28,378 +28,343 @@ ClassDefine ObjectiveClassBuilder = //////////////////// Classes //////////////////// -Local ObjectiveClass::newObjective(Objective *obj) { - auto newp = new ObjectiveClass(obj); - return newp->getScriptObject(); +Local ObjectiveClass::newObjective(Objective* obj) { + auto newp = new ObjectiveClass(obj); + return newp->getScriptObject(); } -void ObjectiveClass::set(Objective *obj) { - if (obj) { - objname = obj->getName(); - isValid = true; - } +void ObjectiveClass::set(Objective* obj) { + if (obj) { + objname = obj->getName(); + isValid = true; + } } -Objective *ObjectiveClass::get() { - if (isValid) - return ll::service::getLevel()->getScoreboard().getObjective(objname); - return nullptr; +Objective* ObjectiveClass::get() { + if (isValid) return ll::service::getLevel()->getScoreboard().getObjective(objname); + return nullptr; } Local ObjectiveClass::getName() { - try { - return String::newString(objname); - } - CATCH("Fail in getName!") + try { + return String::newString(objname); + } + CATCH("Fail in getName!") } Local ObjectiveClass::getDisplayName() { - try { - Objective *obj = get(); - if (!obj) - return Local(); - return String::newString(obj->getDisplayName()); - } - CATCH("Fail in getDisplayName!") + try { + Objective* obj = get(); + if (!obj) return Local(); + return String::newString(obj->getDisplayName()); + } + CATCH("Fail in getDisplayName!") } -Local ObjectiveClass::setDisplay(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - CHECK_ARG_TYPE(args[0], ValueKind::kString) - if (args.size() == 2) - CHECK_ARG_TYPE(args[1], ValueKind::kNumber) - - try { - Objective *obj = get(); - if (!obj) - return Local(); - - std::string slot = args[0].toStr(); - int sort = 0; - if (args.size() == 2) - sort = args[1].toInt(); - return Boolean::newBoolean( - ll::service::getLevel()->getScoreboard().setDisplayObjective( - slot, *obj, (ObjectiveSortOrder)sort)); - } - CATCH("Fail in setDisplay"); +Local ObjectiveClass::setDisplay(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + CHECK_ARG_TYPE(args[0], ValueKind::kString) + if (args.size() == 2) CHECK_ARG_TYPE(args[1], ValueKind::kNumber) + + try { + Objective* obj = get(); + if (!obj) return Local(); + + std::string slot = args[0].toStr(); + int sort = 0; + if (args.size() == 2) sort = args[1].toInt(); + return Boolean::newBoolean( + ll::service::getLevel()->getScoreboard().setDisplayObjective(slot, *obj, (ObjectiveSortOrder)sort) + ); + } + CATCH("Fail in setDisplay"); } -Local ObjectiveClass::setScore(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2) - CHECK_ARG_TYPE(args[1], ValueKind::kNumber) - - try { - int score = args[1].toInt(); +Local ObjectiveClass::setScore(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2) + CHECK_ARG_TYPE(args[1], ValueKind::kNumber) - if (args[0].isString()) { - std::string name = args[0].toStr(); - Scoreboard &scoreboard = ll::service::getLevel()->getScoreboard(); - Objective *obj = scoreboard.getObjective(objname); - if (!obj) { - return Boolean::newBoolean(false); - } - const ScoreboardId &id = scoreboard.getScoreboardId(name); - if (!id.isValid()) { - scoreboard.createScoreboardId(name); - } - bool isSuccess = false; - scoreboard.modifyPlayerScore(isSuccess, id, *obj, score, - PlayerScoreSetFunction::Set); - if (isSuccess) - return Number::newNumber(score); - } else if (IsInstanceOf(args[0])) { - auto player = PlayerClass::extract(args[0]); - Scoreboard &scoreboard = ll::service::getLevel()->getScoreboard(); - Objective *obj = scoreboard.getObjective(objname); - if (!obj) { - return Boolean::newBoolean(false); - } - const ScoreboardId &id = - scoreboard.getScoreboardId(player->getOrCreateUniqueID()); - if (!id.isValid()) { - scoreboard.createScoreboardId(*player); - } - bool isSuccess = false; - scoreboard.modifyPlayerScore(isSuccess, id, *obj, - args[1].asNumber().toInt32(), - PlayerScoreSetFunction::Set); - if (isSuccess) - return Number::newNumber(score); - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); + try { + int score = args[1].toInt(); + + if (args[0].isString()) { + std::string name = args[0].toStr(); + Scoreboard& scoreboard = ll::service::getLevel()->getScoreboard(); + Objective* obj = scoreboard.getObjective(objname); + if (!obj) { + return Boolean::newBoolean(false); + } + const ScoreboardId& id = scoreboard.getScoreboardId(name); + if (!id.isValid()) { + scoreboard.createScoreboardId(name); + } + bool isSuccess = false; + scoreboard.modifyPlayerScore(isSuccess, id, *obj, score, PlayerScoreSetFunction::Set); + if (isSuccess) return Number::newNumber(score); + } else if (IsInstanceOf(args[0])) { + auto player = PlayerClass::extract(args[0]); + Scoreboard& scoreboard = ll::service::getLevel()->getScoreboard(); + Objective* obj = scoreboard.getObjective(objname); + if (!obj) { + return Boolean::newBoolean(false); + } + const ScoreboardId& id = scoreboard.getScoreboardId(player->getOrCreateUniqueID()); + if (!id.isValid()) { + scoreboard.createScoreboardId(*player); + } + bool isSuccess = false; + scoreboard + .modifyPlayerScore(isSuccess, id, *obj, args[1].asNumber().toInt32(), PlayerScoreSetFunction::Set); + if (isSuccess) return Number::newNumber(score); + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } } - } - CATCH("Fail in setScore"); + CATCH("Fail in setScore"); } -Local ObjectiveClass::addScore(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2) - CHECK_ARG_TYPE(args[1], ValueKind::kNumber) - - try { - int score = args[1].toInt(); +Local ObjectiveClass::addScore(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2) + CHECK_ARG_TYPE(args[1], ValueKind::kNumber) - if (args[0].isString()) { - std::string name = args[0].toStr(); - Scoreboard &scoreboard = ll::service::getLevel()->getScoreboard(); - Objective *obj = scoreboard.getObjective(objname); - if (!obj) { - return Boolean::newBoolean(false); - } - const ScoreboardId &id = scoreboard.getScoreboardId(name); - if (!id.isValid()) { - scoreboard.createScoreboardId(name); - } - bool isSuccess = false; - scoreboard.modifyPlayerScore(isSuccess, id, *obj, - args[1].asNumber().toInt32(), - PlayerScoreSetFunction::Add); - if (isSuccess) - return Number::newNumber(score); - } else if (IsInstanceOf(args[0])) { - auto player = PlayerClass::extract(args[0]); - Scoreboard &scoreboard = ll::service::getLevel()->getScoreboard(); - Objective *obj = scoreboard.getObjective(objname); - if (!obj) { - return Boolean::newBoolean(false); - } - const ScoreboardId &id = - scoreboard.getScoreboardId(player->getOrCreateUniqueID()); - if (!id.isValid()) { - scoreboard.createScoreboardId(*player); - } - bool isSuccess = false; - scoreboard.modifyPlayerScore(isSuccess, id, *obj, - args[1].asNumber().toInt32(), - PlayerScoreSetFunction::Add); - if (isSuccess) - return Number::newNumber(score); - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); + try { + int score = args[1].toInt(); + + if (args[0].isString()) { + std::string name = args[0].toStr(); + Scoreboard& scoreboard = ll::service::getLevel()->getScoreboard(); + Objective* obj = scoreboard.getObjective(objname); + if (!obj) { + return Boolean::newBoolean(false); + } + const ScoreboardId& id = scoreboard.getScoreboardId(name); + if (!id.isValid()) { + scoreboard.createScoreboardId(name); + } + bool isSuccess = false; + scoreboard + .modifyPlayerScore(isSuccess, id, *obj, args[1].asNumber().toInt32(), PlayerScoreSetFunction::Add); + if (isSuccess) return Number::newNumber(score); + } else if (IsInstanceOf(args[0])) { + auto player = PlayerClass::extract(args[0]); + Scoreboard& scoreboard = ll::service::getLevel()->getScoreboard(); + Objective* obj = scoreboard.getObjective(objname); + if (!obj) { + return Boolean::newBoolean(false); + } + const ScoreboardId& id = scoreboard.getScoreboardId(player->getOrCreateUniqueID()); + if (!id.isValid()) { + scoreboard.createScoreboardId(*player); + } + bool isSuccess = false; + scoreboard + .modifyPlayerScore(isSuccess, id, *obj, args[1].asNumber().toInt32(), PlayerScoreSetFunction::Add); + if (isSuccess) return Number::newNumber(score); + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } } - } - CATCH("Fail in addScore"); + CATCH("Fail in addScore"); } -Local ObjectiveClass::reduceScore(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2) - CHECK_ARG_TYPE(args[1], ValueKind::kNumber) - - try { - int score = args[1].toInt(); +Local ObjectiveClass::reduceScore(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2) + CHECK_ARG_TYPE(args[1], ValueKind::kNumber) - if (args[0].isString()) { - std::string name = args[0].toStr(); - Scoreboard &scoreboard = ll::service::getLevel()->getScoreboard(); - Objective *obj = scoreboard.getObjective(objname); - if (!obj) { - return Boolean::newBoolean(false); - } - const ScoreboardId &id = scoreboard.getScoreboardId(name); - if (!id.isValid()) { - scoreboard.createScoreboardId(name); - } - bool isSuccess = false; - scoreboard.modifyPlayerScore(isSuccess, id, *obj, - args[1].asNumber().toInt32(), - PlayerScoreSetFunction::Subtract); - if (isSuccess) - return Number::newNumber(score); - } else if (IsInstanceOf(args[0])) { - auto player = PlayerClass::extract(args[0]); - Scoreboard &scoreboard = ll::service::getLevel()->getScoreboard(); - Objective *obj = scoreboard.getObjective(objname); - if (!obj) { - return Boolean::newBoolean(false); - } - const ScoreboardId &id = - scoreboard.getScoreboardId(player->getOrCreateUniqueID()); - if (!id.isValid()) { - scoreboard.createScoreboardId(*player); - } - bool isSuccess = false; - scoreboard.modifyPlayerScore(isSuccess, id, *obj, - args[1].asNumber().toInt32(), - PlayerScoreSetFunction::Subtract); - if (isSuccess) - return Number::newNumber(score); - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); + try { + int score = args[1].toInt(); + + if (args[0].isString()) { + std::string name = args[0].toStr(); + Scoreboard& scoreboard = ll::service::getLevel()->getScoreboard(); + Objective* obj = scoreboard.getObjective(objname); + if (!obj) { + return Boolean::newBoolean(false); + } + const ScoreboardId& id = scoreboard.getScoreboardId(name); + if (!id.isValid()) { + scoreboard.createScoreboardId(name); + } + bool isSuccess = false; + scoreboard + .modifyPlayerScore(isSuccess, id, *obj, args[1].asNumber().toInt32(), PlayerScoreSetFunction::Subtract); + if (isSuccess) return Number::newNumber(score); + } else if (IsInstanceOf(args[0])) { + auto player = PlayerClass::extract(args[0]); + Scoreboard& scoreboard = ll::service::getLevel()->getScoreboard(); + Objective* obj = scoreboard.getObjective(objname); + if (!obj) { + return Boolean::newBoolean(false); + } + const ScoreboardId& id = scoreboard.getScoreboardId(player->getOrCreateUniqueID()); + if (!id.isValid()) { + scoreboard.createScoreboardId(*player); + } + bool isSuccess = false; + scoreboard + .modifyPlayerScore(isSuccess, id, *obj, args[1].asNumber().toInt32(), PlayerScoreSetFunction::Subtract); + if (isSuccess) return Number::newNumber(score); + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } } - } - CATCH("Fail in removeScore"); + CATCH("Fail in removeScore"); } -Local ObjectiveClass::deleteScore(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - - try { - if (args[0].isString()) { - Scoreboard &scoreboard = ll::service::getLevel()->getScoreboard(); - Objective *obj = scoreboard.getObjective(objname); - if (!obj) { - return Boolean::newBoolean(false); - } - const ScoreboardId &id = - scoreboard.getScoreboardId(args[0].asString().toString()); - if (!id.isValid()) { - return Boolean::newBoolean(true); - } - return Boolean::newBoolean( - scoreboard.getScoreboardIdentityRef(id)->removeFromObjective( - scoreboard, *obj)); - } else if (IsInstanceOf(args[0])) { - Player *player = PlayerClass::extract(args[0]); - Scoreboard &scoreboard = ll::service::getLevel()->getScoreboard(); - Objective *obj = scoreboard.getObjective(objname); - if (!obj) { - return Boolean::newBoolean(false); - } - const ScoreboardId &id = - scoreboard.getScoreboardId(player->getOrCreateUniqueID()); - if (!id.isValid()) { - return Boolean::newBoolean(true); - } - return Boolean::newBoolean( - scoreboard.getScoreboardIdentityRef(id)->removeFromObjective( - scoreboard, *obj)); - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); +Local ObjectiveClass::deleteScore(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + + try { + if (args[0].isString()) { + Scoreboard& scoreboard = ll::service::getLevel()->getScoreboard(); + Objective* obj = scoreboard.getObjective(objname); + if (!obj) { + return Boolean::newBoolean(false); + } + const ScoreboardId& id = scoreboard.getScoreboardId(args[0].asString().toString()); + if (!id.isValid()) { + return Boolean::newBoolean(true); + } + return Boolean::newBoolean(scoreboard.getScoreboardIdentityRef(id)->removeFromObjective(scoreboard, *obj)); + } else if (IsInstanceOf(args[0])) { + Player* player = PlayerClass::extract(args[0]); + Scoreboard& scoreboard = ll::service::getLevel()->getScoreboard(); + Objective* obj = scoreboard.getObjective(objname); + if (!obj) { + return Boolean::newBoolean(false); + } + const ScoreboardId& id = scoreboard.getScoreboardId(player->getOrCreateUniqueID()); + if (!id.isValid()) { + return Boolean::newBoolean(true); + } + return Boolean::newBoolean(scoreboard.getScoreboardIdentityRef(id)->removeFromObjective(scoreboard, *obj)); + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } } - } - CATCH("Fail in deleteScore"); + CATCH("Fail in deleteScore"); } -Local ObjectiveClass::getScore(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - - try { - if (args[0].isString()) { - Scoreboard &board = ll::service::getLevel()->getScoreboard(); - Objective *objective = board.getObjective(objname); - ScoreboardId sid = board.getScoreboardId(PlayerScoreboardId( - std::atoll(args[0].asString().toString().c_str()))); - if (!objective || !sid.isValid() || !objective->hasScore(sid)) { - return {}; - } - return Number::newNumber(objective->getPlayerScore(sid).mScore); - } else if (IsInstanceOf(args[0])) { - Scoreboard &board = ll::service::getLevel()->getScoreboard(); - Objective *objective = board.getObjective(objname); - ScoreboardId sid = board.getScoreboardId(*PlayerClass::extract(args[0])); - if (!objective || !sid.isValid() || !objective->hasScore(sid)) { - return {}; - } - return Number::newNumber(objective->getPlayerScore(sid).mScore); - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); +Local ObjectiveClass::getScore(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + + try { + if (args[0].isString()) { + Scoreboard& board = ll::service::getLevel()->getScoreboard(); + Objective* objective = board.getObjective(objname); + ScoreboardId sid = + board.getScoreboardId(PlayerScoreboardId(std::atoll(args[0].asString().toString().c_str()))); + if (!objective || !sid.isValid() || !objective->hasScore(sid)) { + return {}; + } + return Number::newNumber(objective->getPlayerScore(sid).mScore); + } else if (IsInstanceOf(args[0])) { + Scoreboard& board = ll::service::getLevel()->getScoreboard(); + Objective* objective = board.getObjective(objname); + ScoreboardId sid = board.getScoreboardId(*PlayerClass::extract(args[0])); + if (!objective || !sid.isValid() || !objective->hasScore(sid)) { + return {}; + } + return Number::newNumber(objective->getPlayerScore(sid).mScore); + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } } - } - CATCH("Fail in getScore"); + CATCH("Fail in getScore"); } //////////////////// APIs //////////////////// -Local McClass::getDisplayObjective(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local McClass::getDisplayObjective(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - string slot = args[0].toStr(); - auto res = - ll::service::getLevel()->getScoreboard().getDisplayObjective(slot); + try { + string slot = args[0].toStr(); + auto res = ll::service::getLevel()->getScoreboard().getDisplayObjective(slot); - if (!res) - return Local(); - return ObjectiveClass::newObjective((Objective *)res); - } - CATCH("Fail in GetDisplayObjective"); + if (!res) return Local(); + return ObjectiveClass::newObjective((Objective*)res); + } + CATCH("Fail in GetDisplayObjective"); } -Local McClass::clearDisplayObjective(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local McClass::clearDisplayObjective(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - string slot = args[0].toStr(); - auto res = - ll::service::getLevel()->getScoreboard().clearDisplayObjective(slot); + try { + string slot = args[0].toStr(); + auto res = ll::service::getLevel()->getScoreboard().clearDisplayObjective(slot); - if (!res) - return Local(); - return ObjectiveClass::newObjective(res); - } - CATCH("Fail in ClearDisplayObjective"); + if (!res) return Local(); + return ObjectiveClass::newObjective(res); + } + CATCH("Fail in ClearDisplayObjective"); } -Local McClass::getScoreObjective(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); +Local McClass::getScoreObjective(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); - try { - string name = args[0].toStr(); - auto res = ll::service::getLevel()->getScoreboard().getObjective(name); + try { + string name = args[0].toStr(); + auto res = ll::service::getLevel()->getScoreboard().getObjective(name); - if (!res) - return Local(); - return ObjectiveClass::newObjective(res); - } - CATCH("Fail in GetScoreObjective"); + if (!res) return Local(); + return ObjectiveClass::newObjective(res); + } + CATCH("Fail in GetScoreObjective"); } -Local McClass::newScoreObjective(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - CHECK_ARG_TYPE(args[0], ValueKind::kString) - if (args.size() >= 2) - CHECK_ARG_TYPE(args[1], ValueKind::kString) - - try { - std::string name = args[0].toStr(); - std::string display = name; - if (args.size() >= 2) - display = args[1].toStr(); - Scoreboard &scoreboard = ll::service::getLevel()->getScoreboard(); - std::string criteria = "dummy"; - Objective *obj = scoreboard.addObjective( - name, display, - *const_cast(scoreboard.getCriteria(criteria))); - return obj ? ObjectiveClass::newObjective(obj) : Local(); - } - CATCH("Fail in NewScoreObjective!") +Local McClass::newScoreObjective(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + CHECK_ARG_TYPE(args[0], ValueKind::kString) + if (args.size() >= 2) CHECK_ARG_TYPE(args[1], ValueKind::kString) + + try { + std::string name = args[0].toStr(); + std::string display = name; + if (args.size() >= 2) display = args[1].toStr(); + Scoreboard& scoreboard = ll::service::getLevel()->getScoreboard(); + std::string criteria = "dummy"; + Objective* obj = + scoreboard.addObjective(name, display, *const_cast(scoreboard.getCriteria(criteria))); + return obj ? ObjectiveClass::newObjective(obj) : Local(); + } + CATCH("Fail in NewScoreObjective!") } -Local McClass::removeScoreObjective(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - CHECK_ARG_TYPE(args[0], ValueKind::kString) - - try { - string name = args[0].toStr(); - auto obj = ll::service::getLevel()->getScoreboard().getObjective(name); - if (obj) { - ll::service::getLevel()->getScoreboard().removeObjective(obj); - return Boolean::newBoolean(true); +Local McClass::removeScoreObjective(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + CHECK_ARG_TYPE(args[0], ValueKind::kString) + + try { + string name = args[0].toStr(); + auto obj = ll::service::getLevel()->getScoreboard().getObjective(name); + if (obj) { + ll::service::getLevel()->getScoreboard().removeObjective(obj); + return Boolean::newBoolean(true); + } + return Boolean::newBoolean(false); } - return Boolean::newBoolean(false); - } - CATCH("Fail in RemoveScoreObjective!") + CATCH("Fail in RemoveScoreObjective!") } -Local McClass::getAllScoreObjectives(const Arguments &args) { - try { - Local res = Array::newArray(); +Local McClass::getAllScoreObjectives(const Arguments& args) { + try { + Local res = Array::newArray(); - auto objs = ll::service::getLevel()->getScoreboard().getObjectives(); - for (auto &obj : objs) { - if (obj) - res.add(ObjectiveClass::newObjective((Objective *)obj)); + auto objs = ll::service::getLevel()->getScoreboard().getObjectives(); + for (auto& obj : objs) { + if (obj) res.add(ObjectiveClass::newObjective((Objective*)obj)); + } + return res; } - return res; - } - CATCH("Fail in GetAllScoreObjectives!") + CATCH("Fail in GetAllScoreObjectives!") } \ No newline at end of file diff --git a/src/api/ScoreboardAPI.h b/src/api/ScoreboardAPI.h index ced7061b..e7d62841 100644 --- a/src/api/ScoreboardAPI.h +++ b/src/api/ScoreboardAPI.h @@ -6,24 +6,21 @@ class Objective; class ObjectiveClass : public ScriptClass { std::string objname; - bool isValid = false; + bool isValid = false; public: - explicit ObjectiveClass(Objective* obj) - : ScriptClass(ScriptClass::ConstructFromCpp{}) { - set(obj); - } + explicit ObjectiveClass(Objective* obj) : ScriptClass(ScriptClass::ConstructFromCpp{}) { set(obj); } - void set(Objective* obj); - Objective* get(); + void set(Objective* obj); + Objective* get(); static Local newObjective(Objective* obj); - Local getName(); - Local getDisplayName(); - Local setDisplay(const Arguments& args); - Local setScore(const Arguments& args); - Local addScore(const Arguments& args); - Local reduceScore(const Arguments& args); - Local deleteScore(const Arguments& args); - Local getScore(const Arguments& args); + Local getName(); + Local getDisplayName(); + Local setDisplay(const Arguments& args); + Local setScore(const Arguments& args); + Local addScore(const Arguments& args); + Local reduceScore(const Arguments& args); + Local deleteScore(const Arguments& args); + Local getScore(const Arguments& args); }; extern ClassDefine ObjectiveClassBuilder; \ No newline at end of file diff --git a/src/api/ScriptAPI.cpp b/src/api/ScriptAPI.cpp index ff109b7e..ae272447 100644 --- a/src/api/ScriptAPI.cpp +++ b/src/api/ScriptAPI.cpp @@ -15,159 +15,149 @@ //////////////////// APIs //////////////////// -Local Log(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - - try { - std::ostringstream sout; - for (int i = 0; i < args.size(); ++i) - PrintValue(sout, args[i]); - sout << std::endl; - ENGINE_OWN_DATA()->logger.info(sout.str()); - return Boolean::newBoolean(true); - } - CATCH("Fail in Log!"); +Local Log(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + + try { + std::ostringstream sout; + for (int i = 0; i < args.size(); ++i) PrintValue(sout, args[i]); + sout << std::endl; + ENGINE_OWN_DATA()->logger.info(sout.str()); + return Boolean::newBoolean(true); + } + CATCH("Fail in Log!"); } // #include -Local ColorLog(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - - try { - std::string prefix = ""; - switch (H(args[0].asString().toString())) { - case H("dk_blue"): - prefix = "\x1b[34m"; - break; - case H("dk_green"): - prefix = "\x1b[32m"; - break; - case H("bt_blue"): - prefix = "\x1b[36m"; - break; - case H("dk_red"): - prefix = "\x1b[31m"; - break; - case H("purple"): - prefix = "\x1b[35m"; - break; - case H("dk_yellow"): - prefix = "\x1b[33m"; - break; - case H("grey"): - prefix = "\x1b[37m"; - break; - case H("sky_blue"): - prefix = "\x1b[94m"; - break; - case H("blue"): - prefix = "\x1b[94m"; - break; - case H("green"): - prefix = "\x1b[92m"; - break; - case H("cyan"): - prefix = "\x1b[36m"; - break; - case H("red"): - prefix = "\x1b[91m"; - break; - case H("pink"): - prefix = "\x1b[95m"; - break; - case H("yellow"): - prefix = "\x1b[93m"; - break; - case H("white"): - prefix = "\x1b[97m"; - break; - default: - LOG_ERROR_WITH_SCRIPT_INFO("Invalid color!"); - break; +Local ColorLog(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + + try { + std::string prefix = ""; + switch (H(args[0].asString().toString())) { + case H("dk_blue"): + prefix = "\x1b[34m"; + break; + case H("dk_green"): + prefix = "\x1b[32m"; + break; + case H("bt_blue"): + prefix = "\x1b[36m"; + break; + case H("dk_red"): + prefix = "\x1b[31m"; + break; + case H("purple"): + prefix = "\x1b[35m"; + break; + case H("dk_yellow"): + prefix = "\x1b[33m"; + break; + case H("grey"): + prefix = "\x1b[37m"; + break; + case H("sky_blue"): + prefix = "\x1b[94m"; + break; + case H("blue"): + prefix = "\x1b[94m"; + break; + case H("green"): + prefix = "\x1b[92m"; + break; + case H("cyan"): + prefix = "\x1b[36m"; + break; + case H("red"): + prefix = "\x1b[91m"; + break; + case H("pink"): + prefix = "\x1b[95m"; + break; + case H("yellow"): + prefix = "\x1b[93m"; + break; + case H("white"): + prefix = "\x1b[97m"; + break; + default: + LOG_ERROR_WITH_SCRIPT_INFO("Invalid color!"); + break; + } + std::ostringstream sout; + sout << prefix; + for (int i = 1; i < args.size(); ++i) PrintValue(sout, args[i]); + sout << "\x1b[0m" << std::endl; + ENGINE_OWN_DATA()->logger.info(sout.str()); + return Boolean::newBoolean(true); } - std::ostringstream sout; - sout << prefix; - for (int i = 1; i < args.size(); ++i) - PrintValue(sout, args[i]); - sout << "\x1b[0m" << std::endl; - ENGINE_OWN_DATA()->logger.info(sout.str()); - return Boolean::newBoolean(true); - } - CATCH("Fail in Log!"); + CATCH("Fail in Log!"); } -Local FastLog(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); +Local FastLog(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); - try { - std::ostringstream sout; - for (int i = 0; i < args.size(); ++i) - PrintValue(sout, args[i]); + try { + std::ostringstream sout; + for (int i = 0; i < args.size(); ++i) PrintValue(sout, args[i]); - pool.enqueue( - [str{sout.str()}, pluginName{ENGINE_OWN_DATA()->pluginName}]() { - ll::Logger fastLogger(pluginName); - fastLogger.info(str); + pool.enqueue([str{sout.str()}, pluginName{ENGINE_OWN_DATA()->pluginName}]() { + ll::Logger fastLogger(pluginName); + fastLogger.info(str); }); - return Boolean::newBoolean(true); - } - CATCH("Fail in FastLog!"); + return Boolean::newBoolean(true); + } + CATCH("Fail in FastLog!"); } //////////////////// APIs //////////////////// -Local SetTimeout(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2) - CHECK_ARG_TYPE(args[1], ValueKind::kNumber) - try { - bool isFunc = args[0].getKind() == ValueKind::kFunction; - if (!isFunc && args[0].getKind() != ValueKind::kString) { - LOG_WRONG_ARG_TYPE(); - return Local(); +Local SetTimeout(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2) + CHECK_ARG_TYPE(args[1], ValueKind::kNumber) + try { + bool isFunc = args[0].getKind() == ValueKind::kFunction; + if (!isFunc && args[0].getKind() != ValueKind::kString) { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + + int timeout = args[1].toInt(); + if (timeout <= 0) timeout = 1; + + if (isFunc) return Number::newNumber(NewTimeout(args[0].asFunction(), {}, timeout)); + else return Number::newNumber(NewTimeout(args[0].asString(), timeout)); } - - int timeout = args[1].toInt(); - if (timeout <= 0) - timeout = 1; - - if (isFunc) - return Number::newNumber(NewTimeout(args[0].asFunction(), {}, timeout)); - else - return Number::newNumber(NewTimeout(args[0].asString(), timeout)); - } - CATCH("Fail in SetTimeout!") + CATCH("Fail in SetTimeout!") } -Local SetInterval(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2) - CHECK_ARG_TYPE(args[1], ValueKind::kNumber) +Local SetInterval(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2) + CHECK_ARG_TYPE(args[1], ValueKind::kNumber) - try { - bool isFunc = args[0].getKind() == ValueKind::kFunction; - if (!isFunc && args[0].getKind() != ValueKind::kString) { - LOG_WRONG_ARG_TYPE(); - return Local(); - } + try { + bool isFunc = args[0].getKind() == ValueKind::kFunction; + if (!isFunc && args[0].getKind() != ValueKind::kString) { + LOG_WRONG_ARG_TYPE(); + return Local(); + } - int timeout = args[1].toInt(); - if (timeout <= 0) - timeout = 1; + int timeout = args[1].toInt(); + if (timeout <= 0) timeout = 1; - if (isFunc) - return Number::newNumber(NewInterval(args[0].asFunction(), {}, timeout)); - else - return Number::newNumber(NewInterval(args[0].asString(), timeout)); - } - CATCH("Fail in SetInterval!") + if (isFunc) return Number::newNumber(NewInterval(args[0].asFunction(), {}, timeout)); + else return Number::newNumber(NewInterval(args[0].asString(), timeout)); + } + CATCH("Fail in SetInterval!") } // ClearInterval -Local ClearInterval(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - CHECK_ARG_TYPE(args[0], ValueKind::kNumber) - - try { - return Boolean::newBoolean(ClearTimeTask(args[0].toInt())); - } - CATCH("Fail in ClearInterval!") +Local ClearInterval(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + CHECK_ARG_TYPE(args[0], ValueKind::kNumber) + + try { + return Boolean::newBoolean(ClearTimeTask(args[0].toInt())); + } + CATCH("Fail in ClearInterval!") } diff --git a/src/api/ServerAPI.cpp b/src/api/ServerAPI.cpp index aed24a90..ec64fad9 100644 --- a/src/api/ServerAPI.cpp +++ b/src/api/ServerAPI.cpp @@ -7,124 +7,110 @@ #include "mc/network/packet/SetTimePacket.h" #include -Local McClass::setMotd(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - CHECK_ARG_TYPE(args[0], ValueKind::kString) - - try { - return Boolean::newBoolean( - ll::setServerMotd(args[0].asString().toString())); - } - CATCH("Fail in SetServerMotd!") +Local McClass::setMotd(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + CHECK_ARG_TYPE(args[0], ValueKind::kString) + + try { + return Boolean::newBoolean(ll::setServerMotd(args[0].asString().toString())); + } + CATCH("Fail in SetServerMotd!") } -Local McClass::crashBDS(const Arguments &args) //===========??? +Local McClass::crashBDS(const Arguments& args) //===========??? { #ifdef LL_DEBUG - RecordOperation(ENGINE_OWN_DATA()->pluginName, "Crash Server", - "Execute mc.crash() to crash server."); - throw; - return Boolean::newBoolean(true); + RecordOperation(ENGINE_OWN_DATA()->pluginName, "Crash Server", "Execute mc.crash() to crash server."); + throw; + return Boolean::newBoolean(true); #endif - return Boolean::newBoolean(false); + return Boolean::newBoolean(false); } -Local McClass::setMaxNumPlayers(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - CHECK_ARG_TYPE(args[0], ValueKind::kNumber) - - try { - int back = ll::service::getServerNetworkHandler()->setMaxNumPlayers( - args[0].asNumber().toInt32()); - ll::service::getServerNetworkHandler()->updateServerAnnouncement(); - return Boolean::newBoolean(back == 0 ? true : false); - } - CATCH("Fail in setMaxPlayers!") +Local McClass::setMaxNumPlayers(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + CHECK_ARG_TYPE(args[0], ValueKind::kNumber) + + try { + int back = ll::service::getServerNetworkHandler()->setMaxNumPlayers(args[0].asNumber().toInt32()); + ll::service::getServerNetworkHandler()->updateServerAnnouncement(); + return Boolean::newBoolean(back == 0 ? true : false); + } + CATCH("Fail in setMaxPlayers!") } -Local McClass::getTime(const Arguments &args) { - int option = 0; // option: 0: daytime, 1: gametime, 2: day +Local McClass::getTime(const Arguments& args) { + int option = 0; // option: 0: daytime, 1: gametime, 2: day - if (args.size() > 0) { - CHECK_ARG_TYPE(args[0], ValueKind::kNumber) - option = args[0].asNumber().toInt32(); - } - - switch (option) { - case 0: - return Number::newNumber(ll::service::getLevel()->getTime() % 24000); - break; - case 1: - return Number::newNumber( - (int)*(size_t *)&ll::service::getLevel()->getCurrentTick()); - break; - case 2: - return Number::newNumber(ll::service::getLevel()->getTime() / 24000); - break; - default: - throw script::Exception("The range of this argument is between 0 and 2"); - } + if (args.size() > 0) { + CHECK_ARG_TYPE(args[0], ValueKind::kNumber) + option = args[0].asNumber().toInt32(); + } + + switch (option) { + case 0: + return Number::newNumber(ll::service::getLevel()->getTime() % 24000); + break; + case 1: + return Number::newNumber((int)*(size_t*)&ll::service::getLevel()->getCurrentTick()); + break; + case 2: + return Number::newNumber(ll::service::getLevel()->getTime() / 24000); + break; + default: + throw script::Exception("The range of this argument is between 0 and 2"); + } } -Local McClass::setTime(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - CHECK_ARG_TYPE(args[0], ValueKind::kNumber) +Local McClass::setTime(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + CHECK_ARG_TYPE(args[0], ValueKind::kNumber) - try { - int currentTime = ll::service::getLevel()->getTime(); - int targetTime = args[0].asNumber().toInt32(); // Tick + try { + int currentTime = ll::service::getLevel()->getTime(); + int targetTime = args[0].asNumber().toInt32(); // Tick - int newTime = currentTime; - int currentTimeOfDay = currentTime % 24000; + int newTime = currentTime; + int currentTimeOfDay = currentTime % 24000; - if (targetTime > currentTime % 24000) - newTime = currentTime + targetTime - currentTimeOfDay; - else if (targetTime < currentTimeOfDay) - newTime = currentTime + targetTime + 24000 - currentTimeOfDay; + if (targetTime > currentTime % 24000) newTime = currentTime + targetTime - currentTimeOfDay; + else if (targetTime < currentTimeOfDay) newTime = currentTime + targetTime + 24000 - currentTimeOfDay; - ll::service::getLevel()->setTime(newTime); - SetTimePacket(newTime).sendToClients(); - } - CATCH("Fail in setTime!") + ll::service::getLevel()->setTime(newTime); + SetTimePacket(newTime).sendToClients(); + } + CATCH("Fail in setTime!") - return Boolean::newBoolean(true); + return Boolean::newBoolean(true); } -Local McClass::getWeather( - const Arguments &args) { // weather: 0: Clear, 1: Rain, 2: Thunder - if (ll::service::getLevel()->getLevelData().isLightning()) - return Number::newNumber(2); - else if (ll::service::getLevel()->getLevelData().isRaining()) - return Number::newNumber(1); +Local McClass::getWeather(const Arguments& args) { // weather: 0: Clear, 1: Rain, 2: Thunder + if (ll::service::getLevel()->getLevelData().isLightning()) return Number::newNumber(2); + else if (ll::service::getLevel()->getLevelData().isRaining()) return Number::newNumber(1); - return Number::newNumber(0); + return Number::newNumber(0); } -Local McClass::setWeather(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1) - CHECK_ARG_TYPE(args[0], ValueKind::kNumber) +Local McClass::setWeather(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1) + CHECK_ARG_TYPE(args[0], ValueKind::kNumber) + + int duration = 0; + int weather = args[0].asNumber().toInt32(); // weather: 0: Clear, 1: Rain, 2: Thunder - int duration = 0; - int weather = - args[0].asNumber().toInt32(); // weather: 0: Clear, 1: Rain, 2: Thunder + try { + if (args.size() > 1) { + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + duration = args[1].asNumber().toInt32(); + } else { + duration = 20 * (ll::random_utils::rand(600) + 300); + } - try { - if (args.size() > 1) { - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - duration = args[1].asNumber().toInt32(); - } else { - duration = 20 * (ll::random_utils::rand(600) + 300); + if (weather == 1) ll::service::getLevel()->updateWeather(1.0, duration, 0.0, duration); + else if (weather == 2) ll::service::getLevel()->updateWeather(1065353216.0, duration, 1065353216.0, duration); + else ll::service::getLevel()->updateWeather(0.0, duration, 0.0, duration); } + CATCH("Fail in setWeather!") - if (weather == 1) - ll::service::getLevel()->updateWeather(1.0, duration, 0.0, duration); - else if (weather == 2) - ll::service::getLevel()->updateWeather(1065353216.0, duration, - 1065353216.0, duration); - else - ll::service::getLevel()->updateWeather(0.0, duration, 0.0, duration); - } - CATCH("Fail in setWeather!") - - return Boolean::newBoolean(true); + return Boolean::newBoolean(true); } diff --git a/src/api/SimulatedPlayerAPI.cpp b/src/api/SimulatedPlayerAPI.cpp index af1d4c80..03940f6a 100644 --- a/src/api/SimulatedPlayerAPI.cpp +++ b/src/api/SimulatedPlayerAPI.cpp @@ -26,555 +26,505 @@ #include #include -Local McClass::spawnSimulatedPlayer(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - - try { - std::string name = args[0].toStr(); - if (args.size() == 1) { - if (auto sp = SimulatedPlayer::create(name)) - return PlayerClass::newPlayer(sp); - else - return Local(); - } - auto dimid = 0; - Vec3 bpos; - if (IsInstanceOf(args[1])) { - auto pos = IntPos::extractPos(args[1]); - bpos = pos->getBlockPos().bottomCenter(); - dimid = pos->getDimensionId(); - } else if (IsInstanceOf(args[1])) { - auto pos = FloatPos::extractPos(args[1]); - bpos = pos->getVec3(); - dimid = pos->getDimensionId(); - } else { - CHECK_ARGS_COUNT(args, 4); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - if (args.size() > 4) { - CHECK_ARG_TYPE(args[4], ValueKind::kNumber); - dimid = args[4].toInt(); - } - bpos = BlockPos(args[1].toInt(), args[2].toInt(), args[3].toInt()) - .bottomCenter(); +Local McClass::spawnSimulatedPlayer(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + + try { + std::string name = args[0].toStr(); + if (args.size() == 1) { + if (auto sp = SimulatedPlayer::create(name)) return PlayerClass::newPlayer(sp); + else return Local(); + } + auto dimid = 0; + Vec3 bpos; + if (IsInstanceOf(args[1])) { + auto pos = IntPos::extractPos(args[1]); + bpos = pos->getBlockPos().bottomCenter(); + dimid = pos->getDimensionId(); + } else if (IsInstanceOf(args[1])) { + auto pos = FloatPos::extractPos(args[1]); + bpos = pos->getVec3(); + dimid = pos->getDimensionId(); + } else { + CHECK_ARGS_COUNT(args, 4); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + if (args.size() > 4) { + CHECK_ARG_TYPE(args[4], ValueKind::kNumber); + dimid = args[4].toInt(); + } + bpos = BlockPos(args[1].toInt(), args[2].toInt(), args[3].toInt()).bottomCenter(); + } + if (auto sp = SimulatedPlayer::create(name, bpos, dimid)) return PlayerClass::newPlayer(sp); + else return Local(); } - if (auto sp = SimulatedPlayer::create(name, bpos, dimid)) - return PlayerClass::newPlayer(sp); - else - return Local(); - } - CATCH("Fail in " __FUNCTION__ "!") + CATCH("Fail in " __FUNCTION__ "!") } -SimulatedPlayer *PlayerClass::asSimulatedPlayer() { - if (get()->isSimulatedPlayer()) { - return static_cast(get()); - } - return nullptr; +SimulatedPlayer* PlayerClass::asSimulatedPlayer() { + if (get()->isSimulatedPlayer()) { + return static_cast(get()); + } + return nullptr; } -Local PlayerClass::simulateSneak(const Arguments &args) { - try { - auto sp = asSimulatedPlayer(); - if (!sp) - return Local(); +Local PlayerClass::simulateSneak(const Arguments& args) { + try { + auto sp = asSimulatedPlayer(); + if (!sp) return Local(); - return Boolean::newBoolean(sp->simulateSneaking()); - } - CATCH("Fail in " __FUNCTION__ "!") + return Boolean::newBoolean(sp->simulateSneaking()); + } + CATCH("Fail in " __FUNCTION__ "!") } // bool simulateAttack(class Actor*); // bool simulateAttack(); -Local PlayerClass::simulateAttack(const Arguments &args) { - try { - auto sp = asSimulatedPlayer(); - if (!sp) - return Local(); +Local PlayerClass::simulateAttack(const Arguments& args) { + try { + auto sp = asSimulatedPlayer(); + if (!sp) return Local(); - if (args.size() == 0) - return Boolean::newBoolean(sp->simulateAttack()); + if (args.size() == 0) return Boolean::newBoolean(sp->simulateAttack()); - if (auto actor = EntityClass::tryExtractActor(args[0])) { - if (!*actor) + if (auto actor = EntityClass::tryExtractActor(args[0])) { + if (!*actor) return Local(); + return Boolean::newBoolean(sp->simulateAttack(*actor)); + } + + LOG_WRONG_ARG_TYPE(); return Local(); - return Boolean::newBoolean(sp->simulateAttack(*actor)); } - - LOG_WRONG_ARG_TYPE(); - return Local(); - } - CATCH("Fail in " __FUNCTION__ "!") + CATCH("Fail in " __FUNCTION__ "!") }; // bool simulateDestroy(); // LIAPI // bool simulateDestroyBlock(class BlockPos const&, enum ScriptFacing); -Local PlayerClass::simulateDestroy(const Arguments &args) { - try { - auto sp = asSimulatedPlayer(); - if (!sp) - return Local(); - - if (args.size() == 0) - return Boolean::newBoolean(sp->simulateDestroyLookAt()); - - int dimid = sp->getDimensionId(); - BlockPos bpos; - size_t index = 0; - ScriptModuleMinecraft::ScriptFacing face = - (ScriptModuleMinecraft::ScriptFacing)0; - if (IsInstanceOf(args[0])) { - auto pos = IntPos::extractPos(args[index]); - if (dimid != pos->getDimensionId()) - return Local(); - bpos = pos->getBlockPos(); - index = 1; - } else if (IsInstanceOf(args[0])) { - auto pos = FloatPos::extractPos(args[index]); - if (dimid != pos->getDimensionId()) - return Local(); - bpos = pos->getVec3(); - index = 1; - } else if (IsInstanceOf(args[0])) { - auto block = - EngineScope::currentEngine()->getNativeInstance(args[0]); - auto pos = IntPos::extractPos(block->getPos()); - if (dimid != pos->getDimensionId()) - return Local(); - bpos = pos->getBlockPos(); - index = 1; - } +Local PlayerClass::simulateDestroy(const Arguments& args) { + try { + auto sp = asSimulatedPlayer(); + if (!sp) return Local(); + + if (args.size() == 0) return Boolean::newBoolean(sp->simulateDestroyLookAt()); + + int dimid = sp->getDimensionId(); + BlockPos bpos; + size_t index = 0; + ScriptModuleMinecraft::ScriptFacing face = (ScriptModuleMinecraft::ScriptFacing)0; + if (IsInstanceOf(args[0])) { + auto pos = IntPos::extractPos(args[index]); + if (dimid != pos->getDimensionId()) return Local(); + bpos = pos->getBlockPos(); + index = 1; + } else if (IsInstanceOf(args[0])) { + auto pos = FloatPos::extractPos(args[index]); + if (dimid != pos->getDimensionId()) return Local(); + bpos = pos->getVec3(); + index = 1; + } else if (IsInstanceOf(args[0])) { + auto block = EngineScope::currentEngine()->getNativeInstance(args[0]); + auto pos = IntPos::extractPos(block->getPos()); + if (dimid != pos->getDimensionId()) return Local(); + bpos = pos->getBlockPos(); + index = 1; + } #ifdef ENABLE_NUMBERS_AS_POS - else if (args[0].isNumber()) { - CHECK_ARGS_COUNT(args, 4); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - bpos = {args[0].toInt(), args[1].toInt(), args[2].toInt()}; - index = 3; - } + else if (args[0].isNumber()) { + CHECK_ARGS_COUNT(args, 4); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + bpos = {args[0].toInt(), args[1].toInt(), args[2].toInt()}; + index = 3; + } #endif // ENABLE_NUMBERS_AS_POS - else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - if (args.size() > index) { - CHECK_ARG_TYPE(args[index], ValueKind::kNumber); - face = (ScriptModuleMinecraft::ScriptFacing)args[index].toInt(); + else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + if (args.size() > index) { + CHECK_ARG_TYPE(args[index], ValueKind::kNumber); + face = (ScriptModuleMinecraft::ScriptFacing)args[index].toInt(); + } + // TODO + return Boolean::newBoolean(sp->simulateDestroyBlock(bpos, face)); } - // TODO - return Boolean::newBoolean(sp->simulateDestroyBlock(bpos, face)); - } - CATCH("Fail in " __FUNCTION__ "!") + CATCH("Fail in " __FUNCTION__ "!") }; // void simulateDisconnect(); -Local PlayerClass::simulateDisconnect(const Arguments &args) { - try { - auto sp = asSimulatedPlayer(); - if (!sp) - return Local(); - sp->simulateDisconnect(); - return Boolean::newBoolean(true); - } - CATCH("Fail in " __FUNCTION__ "!") +Local PlayerClass::simulateDisconnect(const Arguments& args) { + try { + auto sp = asSimulatedPlayer(); + if (!sp) return Local(); + sp->simulateDisconnect(); + return Boolean::newBoolean(true); + } + CATCH("Fail in " __FUNCTION__ "!") }; // bool simulateInteract(class Actor&); // bool simulateInteract(class BlockPos const&, enum ScriptFacing); // bool simulateInteract(); -Local PlayerClass::simulateInteract(const Arguments &args) { - try { - auto sp = asSimulatedPlayer(); - if (!sp) - return Local(); - if (args.size() == 0) - return Boolean::newBoolean(sp->simulateInteract()); - - if (auto actor = EntityClass::tryExtractActor(args[0])) { - if (!*actor) - return Local(); - return Boolean::newBoolean(sp->simulateInteract(**actor)); - } +Local PlayerClass::simulateInteract(const Arguments& args) { + try { + auto sp = asSimulatedPlayer(); + if (!sp) return Local(); + if (args.size() == 0) return Boolean::newBoolean(sp->simulateInteract()); + + if (auto actor = EntityClass::tryExtractActor(args[0])) { + if (!*actor) return Local(); + return Boolean::newBoolean(sp->simulateInteract(**actor)); + } - int dimid = sp->getDimensionId(); - BlockPos bpos; - size_t index = 0; - ScriptModuleMinecraft::ScriptFacing face = - (ScriptModuleMinecraft::ScriptFacing)0; - if (IsInstanceOf(args[0])) { - auto pos = IntPos::extractPos(args[index]); - if (dimid != pos->getDimensionId()) - return Local(); - bpos = pos->getBlockPos(); - index = 1; - } else if (IsInstanceOf(args[0])) { - auto pos = FloatPos::extractPos(args[index]); - if (dimid != pos->getDimensionId()) - return Local(); - bpos = pos->getVec3(); - index = 1; - } else if (IsInstanceOf(args[0])) { - auto block = - EngineScope::currentEngine()->getNativeInstance(args[0]); - auto pos = IntPos::extractPos(block->getPos()); - if (dimid != pos->getDimensionId()) - return Local(); - bpos = pos->getBlockPos(); - index = 1; - } + int dimid = sp->getDimensionId(); + BlockPos bpos; + size_t index = 0; + ScriptModuleMinecraft::ScriptFacing face = (ScriptModuleMinecraft::ScriptFacing)0; + if (IsInstanceOf(args[0])) { + auto pos = IntPos::extractPos(args[index]); + if (dimid != pos->getDimensionId()) return Local(); + bpos = pos->getBlockPos(); + index = 1; + } else if (IsInstanceOf(args[0])) { + auto pos = FloatPos::extractPos(args[index]); + if (dimid != pos->getDimensionId()) return Local(); + bpos = pos->getVec3(); + index = 1; + } else if (IsInstanceOf(args[0])) { + auto block = EngineScope::currentEngine()->getNativeInstance(args[0]); + auto pos = IntPos::extractPos(block->getPos()); + if (dimid != pos->getDimensionId()) return Local(); + bpos = pos->getBlockPos(); + index = 1; + } #ifdef ENABLE_NUMBERS_AS_POS - else if (args[0].isNumber()) { - CHECK_ARGS_COUNT(args, 4); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - bpos = {args[0].toInt(), args[1].toInt(), args[2].toInt()}; - index = 3; - } + else if (args[0].isNumber()) { + CHECK_ARGS_COUNT(args, 4); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + bpos = {args[0].toInt(), args[1].toInt(), args[2].toInt()}; + index = 3; + } #endif // ENABLE_NUMBERS_AS_POS - else { - LOG_WRONG_ARG_TYPE(); - return Local(); + else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + // TODO + return Boolean::newBoolean(sp->simulateInteract(bpos, face)); } - // TODO - return Boolean::newBoolean(sp->simulateInteract(bpos, face)); - } - CATCH("Fail in " __FUNCTION__ "!") + CATCH("Fail in " __FUNCTION__ "!") }; // bool simulateJump(); -Local PlayerClass::simulateJump(const Arguments &args) { - try { - auto sp = asSimulatedPlayer(); - if (!sp) - return Local(); - return Boolean::newBoolean(sp->simulateJump()); - } - CATCH("Fail in " __FUNCTION__ "!") +Local PlayerClass::simulateJump(const Arguments& args) { + try { + auto sp = asSimulatedPlayer(); + if (!sp) return Local(); + return Boolean::newBoolean(sp->simulateJump()); + } + CATCH("Fail in " __FUNCTION__ "!") }; // bool simulateRespawn(); -Local PlayerClass::simulateRespawn(const Arguments &args) { - try { - auto sp = asSimulatedPlayer(); - if (!sp) - return Local(); - if (sp->simulateRespawn()) { - get()->teleport(sp->getSpawnPosition().bottomCenter(), - sp->getSpawnDimension()); - return Boolean::newBoolean(true); - } else { - return Boolean::newBoolean(false); +Local PlayerClass::simulateRespawn(const Arguments& args) { + try { + auto sp = asSimulatedPlayer(); + if (!sp) return Local(); + if (sp->simulateRespawn()) { + get()->teleport(sp->getSpawnPosition().bottomCenter(), sp->getSpawnDimension()); + return Boolean::newBoolean(true); + } else { + return Boolean::newBoolean(false); + } } - } - CATCH("Fail in " __FUNCTION__ "!") + CATCH("Fail in " __FUNCTION__ "!") }; // void simulateLocalMove(class Vec3 const&, float); -Local PlayerClass::simulateLocalMove(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - try { - auto sp = asSimulatedPlayer(); - if (!sp) - return Local(); - Vec3 target; - float speed = 1.0f; - size_t index = 0; - if (IsInstanceOf(args[0])) { - auto pos = IntPos::extractPos(args[0]); - target = pos->getBlockPos(); - index += 1; - } else if (IsInstanceOf(args[0])) { - auto pos = FloatPos::extractPos(args[0]); - target = pos->getVec3(); - index += 1; - } +Local PlayerClass::simulateLocalMove(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + try { + auto sp = asSimulatedPlayer(); + if (!sp) return Local(); + Vec3 target; + float speed = 1.0f; + size_t index = 0; + if (IsInstanceOf(args[0])) { + auto pos = IntPos::extractPos(args[0]); + target = pos->getBlockPos(); + index += 1; + } else if (IsInstanceOf(args[0])) { + auto pos = FloatPos::extractPos(args[0]); + target = pos->getVec3(); + index += 1; + } #ifdef ENABLE_NUMBERS_AS_POS - else if (args[0].isNumber()) { - CHECK_ARGS_COUNT(args, 3); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - Vec3 pos = - Vec3(args[0].asNumber().toFloat(), args[1].asNumber().toFloat(), - args[2].asNumber().toFloat()); - index += 3; - } + else if (args[0].isNumber()) { + CHECK_ARGS_COUNT(args, 3); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + Vec3 pos = Vec3(args[0].asNumber().toFloat(), args[1].asNumber().toFloat(), args[2].asNumber().toFloat()); + index += 3; + } #endif // ENABLE_NUMBERS_AS_POS - else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } + else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } - if (args.size() > index) { - CHECK_ARG_TYPE(args[index], ValueKind::kNumber); - speed = args[index].asNumber().toFloat(); - } + if (args.size() > index) { + CHECK_ARG_TYPE(args[index], ValueKind::kNumber); + speed = args[index].asNumber().toFloat(); + } - sp->simulateLocalMove(target, speed); - return Boolean::newBoolean(true); - } - CATCH("Fail in " __FUNCTION__ "!") + sp->simulateLocalMove(target, speed); + return Boolean::newBoolean(true); + } + CATCH("Fail in " __FUNCTION__ "!") } // void simulateWorldMove(class Vec3 const&, float); -Local PlayerClass::simulateWorldMove(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - try { - auto sp = asSimulatedPlayer(); - if (!sp) - return Local(); - Vec3 target; - float speed = 1.0f; - size_t index = 0; - if (IsInstanceOf(args[0])) { - auto pos = IntPos::extractPos(args[0]); - target = pos->getBlockPos(); - index += 1; - } else if (IsInstanceOf(args[0])) { - auto pos = FloatPos::extractPos(args[0]); - target = pos->getVec3(); - index += 1; - } +Local PlayerClass::simulateWorldMove(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + try { + auto sp = asSimulatedPlayer(); + if (!sp) return Local(); + Vec3 target; + float speed = 1.0f; + size_t index = 0; + if (IsInstanceOf(args[0])) { + auto pos = IntPos::extractPos(args[0]); + target = pos->getBlockPos(); + index += 1; + } else if (IsInstanceOf(args[0])) { + auto pos = FloatPos::extractPos(args[0]); + target = pos->getVec3(); + index += 1; + } #ifdef ENABLE_NUMBERS_AS_POS - else if (args[0].isNumber()) { - CHECK_ARGS_COUNT(args, 3); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - Vec3 pos = - Vec3(args[0].asNumber().toFloat(), args[1].asNumber().toFloat(), - args[2].asNumber().toFloat()); - index += 3; - } + else if (args[0].isNumber()) { + CHECK_ARGS_COUNT(args, 3); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + Vec3 pos = Vec3(args[0].asNumber().toFloat(), args[1].asNumber().toFloat(), args[2].asNumber().toFloat()); + index += 3; + } #endif // ENABLE_NUMBERS_AS_POS - else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } + else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } - if (args.size() > index) { - CHECK_ARG_TYPE(args[index], ValueKind::kNumber); - speed = args[index].asNumber().toFloat(); - } + if (args.size() > index) { + CHECK_ARG_TYPE(args[index], ValueKind::kNumber); + speed = args[index].asNumber().toFloat(); + } - sp->simulateWorldMove(target, speed); - return Boolean::newBoolean(true); - } - CATCH("Fail in " __FUNCTION__ "!") + sp->simulateWorldMove(target, speed); + return Boolean::newBoolean(true); + } + CATCH("Fail in " __FUNCTION__ "!") }; // void simulateMoveToLocation(class Vec3 const&, float); -Local PlayerClass::simulateMoveTo(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - try { - auto sp = asSimulatedPlayer(); - if (!sp) - return Local(); - Vec3 target; - float speed = 1.0f; - size_t index = 0; - if (IsInstanceOf(args[0])) { - auto pos = IntPos::extractPos(args[0]); - target = pos->getBlockPos(); - index += 1; - } else if (IsInstanceOf(args[0])) { - auto pos = FloatPos::extractPos(args[0]); - target = pos->getVec3(); - index += 1; - } +Local PlayerClass::simulateMoveTo(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + try { + auto sp = asSimulatedPlayer(); + if (!sp) return Local(); + Vec3 target; + float speed = 1.0f; + size_t index = 0; + if (IsInstanceOf(args[0])) { + auto pos = IntPos::extractPos(args[0]); + target = pos->getBlockPos(); + index += 1; + } else if (IsInstanceOf(args[0])) { + auto pos = FloatPos::extractPos(args[0]); + target = pos->getVec3(); + index += 1; + } #ifdef ENABLE_NUMBERS_AS_POS - else if (args[0].isNumber()) { - CHECK_ARGS_COUNT(args, 3); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - Vec3 pos = - Vec3(args[0].asNumber().toFloat(), args[1].asNumber().toFloat(), - args[2].asNumber().toFloat()); - index += 3; - } + else if (args[0].isNumber()) { + CHECK_ARGS_COUNT(args, 3); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + Vec3 pos = Vec3(args[0].asNumber().toFloat(), args[1].asNumber().toFloat(), args[2].asNumber().toFloat()); + index += 3; + } #endif // ENABLE_NUMBERS_AS_POS - else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } + else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } - if (args.size() > index) { - CHECK_ARG_TYPE(args[index], ValueKind::kNumber); - speed = args[index].asNumber().toFloat(); - } + if (args.size() > index) { + CHECK_ARG_TYPE(args[index], ValueKind::kNumber); + speed = args[index].asNumber().toFloat(); + } - sp->simulateMoveToLocation(target, speed); - return Boolean::newBoolean(true); - } - CATCH("Fail in " __FUNCTION__ "!") + sp->simulateMoveToLocation(target, speed); + return Boolean::newBoolean(true); + } + CATCH("Fail in " __FUNCTION__ "!") }; // void simulateLookAt(class Actor&); // void simulateLookAt(class BlockPos const&); // void simulateLookAt(class Vec3 const&); -Local PlayerClass::simulateLookAt(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - try { - auto sp = asSimulatedPlayer(); - if (!sp) - return Local(); - Vec3 target; - int dimid = sp->getDimensionId(); - if (IsInstanceOf(args[0])) { - auto pos = IntPos::extractPos(args[0]); - auto did = pos->getDimensionId(); - if (dimid == did || did < 0 || did > 2) { - sp->simulateLookAt(pos->getBlockPos()); - return Boolean::newBoolean(true); - } - logger.debug("Can't simulate look at other dimension!"); - return Boolean::newBoolean(false); - } else if (IsInstanceOf(args[0])) { - auto pos = FloatPos::extractPos(args[0]); - auto did = pos->getDimensionId(); - if (dimid == did || did < 0 || did > 2) { - sp->simulateLookAt(pos->getVec3()); - return Boolean::newBoolean(true); - } - logger.debug("Can't simulate look at other dimension!"); - return Boolean::newBoolean(false); - } else if (IsInstanceOf(args[0])) { - auto block = - EngineScope::currentEngine()->getNativeInstance(args[0]); - auto pos = IntPos::extractPos(block->getPos()); - auto did = pos->getDimensionId(); - if (dimid == did || did < 0 || did > 2) { - sp->simulateLookAt(pos->getBlockPos()); - return Boolean::newBoolean(true); - } - logger.debug("Can't simulate look at other dimension!"); - return Boolean::newBoolean(false); - } else if (auto actor = EntityClass::tryExtractActor(args[0])) { - if (!*actor) +Local PlayerClass::simulateLookAt(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + try { + auto sp = asSimulatedPlayer(); + if (!sp) return Local(); + Vec3 target; + int dimid = sp->getDimensionId(); + if (IsInstanceOf(args[0])) { + auto pos = IntPos::extractPos(args[0]); + auto did = pos->getDimensionId(); + if (dimid == did || did < 0 || did > 2) { + sp->simulateLookAt(pos->getBlockPos()); + return Boolean::newBoolean(true); + } + logger.debug("Can't simulate look at other dimension!"); + return Boolean::newBoolean(false); + } else if (IsInstanceOf(args[0])) { + auto pos = FloatPos::extractPos(args[0]); + auto did = pos->getDimensionId(); + if (dimid == did || did < 0 || did > 2) { + sp->simulateLookAt(pos->getVec3()); + return Boolean::newBoolean(true); + } + logger.debug("Can't simulate look at other dimension!"); + return Boolean::newBoolean(false); + } else if (IsInstanceOf(args[0])) { + auto block = EngineScope::currentEngine()->getNativeInstance(args[0]); + auto pos = IntPos::extractPos(block->getPos()); + auto did = pos->getDimensionId(); + if (dimid == did || did < 0 || did > 2) { + sp->simulateLookAt(pos->getBlockPos()); + return Boolean::newBoolean(true); + } + logger.debug("Can't simulate look at other dimension!"); + return Boolean::newBoolean(false); + } else if (auto actor = EntityClass::tryExtractActor(args[0])) { + if (!*actor) return Local(); + sp->simulateLookAt(**actor); + return Boolean::newBoolean(true); + } + LOG_WRONG_ARG_TYPE(); return Local(); - sp->simulateLookAt(**actor); - return Boolean::newBoolean(true); } - LOG_WRONG_ARG_TYPE(); - return Local(); - } - CATCH("Fail in " __FUNCTION__ "!") + CATCH("Fail in " __FUNCTION__ "!") }; // void simulateSetBodyRotation(float); -Local PlayerClass::simulateSetBodyRotation(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - try { - auto sp = asSimulatedPlayer(); - if (!sp) - return Local(); - sp->simulateSetBodyRotation(args[0].asNumber().toFloat()); - return Boolean::newBoolean(true); - } - CATCH("Fail in " __FUNCTION__ "!") +Local PlayerClass::simulateSetBodyRotation(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + try { + auto sp = asSimulatedPlayer(); + if (!sp) return Local(); + sp->simulateSetBodyRotation(args[0].asNumber().toFloat()); + return Boolean::newBoolean(true); + } + CATCH("Fail in " __FUNCTION__ "!") } // void simulateWorldMove(class Vec3 const&, float); // void simulateMoveToLocation(class Vec3 const&, float); -inline Local NavigateResultToObject( - ScriptModuleMinecraft::ScriptNavigationResult const &res) { - auto obj = Object::newObject(); - obj.set(String::newString("isFullPath"), - Boolean::newBoolean(res.mIsFullPath)); - auto path = Array::newArray(); - for (auto &pos : res.mPath) { - path.add( - Array::newArray({Number::newNumber(pos.x), Number::newNumber(pos.y), - Number::newNumber(pos.z)})); - } - obj.set(String::newString("path"), path); - return obj; +inline Local NavigateResultToObject(ScriptModuleMinecraft::ScriptNavigationResult const& res) { + auto obj = Object::newObject(); + obj.set(String::newString("isFullPath"), Boolean::newBoolean(res.mIsFullPath)); + auto path = Array::newArray(); + for (auto& pos : res.mPath) { + path.add(Array::newArray({Number::newNumber(pos.x), Number::newNumber(pos.y), Number::newNumber(pos.z)})); + } + obj.set(String::newString("path"), path); + return obj; } // struct ScriptNavigationResult simulateNavigateToEntity(class Actor&, float); // struct ScriptNavigationResult simulateNavigateToLocation(class Vec3 const&, // float); void simulateNavigateToLocations(std::vector&&, float); -Local PlayerClass::simulateNavigateTo(const Arguments &args) { - CHECK_ARGS_COUNT(args, 1); - - try { - - auto sp = asSimulatedPlayer(); - if (!sp) - return Local(); - float speed = 1.f; - if (args.size() > 1) { - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - speed = args[1].asNumber().toFloat(); - } - if (args[0].isArray()) { - auto arr = args[0].asArray(); - std::vector path; - for (size_t index = 0; index < arr.size(); ++index) { - if (IsInstanceOf(arr.get(index))) - path.emplace_back( - IntPos::extractPos(arr.get(index))->getBlockPos().center()); - else if (IsInstanceOf(arr.get(index))) - path.emplace_back(FloatPos::extractPos(arr.get(index))->getVec3()); - else if (arr.get(index).isArray()) { - auto posArr = arr.get(index).asArray(); - if (posArr.size() != 3 || !posArr.get(0).isNumber()) { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - path.emplace_back(posArr.get(0).asNumber().toFloat(), - posArr.get(1).asNumber().toFloat(), - posArr.get(2).asNumber().toFloat()); - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - } - sp->simulateNavigateToLocations(std::move(path), speed); - return Boolean::newBoolean(true); - } else if (auto actor = EntityClass::tryExtractActor(args[0])) { - if (!*actor) - return Local(); - auto res = sp->simulateNavigateToEntity(**actor, speed); - return NavigateResultToObject(res); - } else if (IsInstanceOf(args[0]) || - IsInstanceOf(args[0])) { - Vec3 pos = IsInstanceOf(args[0]) - ? IntPos::extractPos(args[0])->getBlockPos().bottomCenter() - : FloatPos::extractPos(args[0])->getVec3(); - auto res = sp->simulateNavigateToLocation(pos, speed); - return NavigateResultToObject(res); - } +Local PlayerClass::simulateNavigateTo(const Arguments& args) { + CHECK_ARGS_COUNT(args, 1); + + try { + + auto sp = asSimulatedPlayer(); + if (!sp) return Local(); + float speed = 1.f; + if (args.size() > 1) { + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + speed = args[1].asNumber().toFloat(); + } + if (args[0].isArray()) { + auto arr = args[0].asArray(); + std::vector path; + for (size_t index = 0; index < arr.size(); ++index) { + if (IsInstanceOf(arr.get(index))) + path.emplace_back(IntPos::extractPos(arr.get(index))->getBlockPos().center()); + else if (IsInstanceOf(arr.get(index))) + path.emplace_back(FloatPos::extractPos(arr.get(index))->getVec3()); + else if (arr.get(index).isArray()) { + auto posArr = arr.get(index).asArray(); + if (posArr.size() != 3 || !posArr.get(0).isNumber()) { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + path.emplace_back( + posArr.get(0).asNumber().toFloat(), + posArr.get(1).asNumber().toFloat(), + posArr.get(2).asNumber().toFloat() + ); + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + } + sp->simulateNavigateToLocations(std::move(path), speed); + return Boolean::newBoolean(true); + } else if (auto actor = EntityClass::tryExtractActor(args[0])) { + if (!*actor) return Local(); + auto res = sp->simulateNavigateToEntity(**actor, speed); + return NavigateResultToObject(res); + } else if (IsInstanceOf(args[0]) || IsInstanceOf(args[0])) { + Vec3 pos = IsInstanceOf(args[0]) ? IntPos::extractPos(args[0])->getBlockPos().bottomCenter() + : FloatPos::extractPos(args[0])->getVec3(); + auto res = sp->simulateNavigateToLocation(pos, speed); + return NavigateResultToObject(res); + } #ifdef ENABLE_NUMBERS_AS_POS - else if (args[0].isNumber()) { - CHECK_ARGS_COUNT(args, 3); - CHECK_ARG_TYPE(args[0], ValueKind::kNumber); - CHECK_ARG_TYPE(args[1], ValueKind::kNumber); - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - if (args.size() > 3) { - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - speed = args[3].asNumber().toFloat(); - } - Vec3 pos = - Vec3(args[0].asNumber().toFloat(), args[1].asNumber().toFloat(), - args[2].asNumber().toFloat()); - auto res = sp->simulateNavigateToLocation(pos, speed); - return NavigateResultToObject(res); - } + else if (args[0].isNumber()) { + CHECK_ARGS_COUNT(args, 3); + CHECK_ARG_TYPE(args[0], ValueKind::kNumber); + CHECK_ARG_TYPE(args[1], ValueKind::kNumber); + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + if (args.size() > 3) { + CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + speed = args[3].asNumber().toFloat(); + } + Vec3 pos = Vec3(args[0].asNumber().toFloat(), args[1].asNumber().toFloat(), args[2].asNumber().toFloat()); + auto res = sp->simulateNavigateToLocation(pos, speed); + return NavigateResultToObject(res); + } #endif // ENABLE_NUMBERS_AS_POS - else { - LOG_WRONG_ARG_TYPE(); - return Local(); + else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } } - } - CATCH("Fail in " __FUNCTION__ "!") + CATCH("Fail in " __FUNCTION__ "!") }; // bool simulateSetItem(class ItemStack&, bool, int); @@ -585,121 +535,103 @@ Local PlayerClass::simulateNavigateTo(const Arguments &args) { // bool simulateUseItemInSlotOnBlock(int, class BlockPos const&, enum // ScriptFacing, class Vec3 const&); bool simulateUseItemOnBlock(class // ItemStack&, class BlockPos const&, enum ScriptFacing, class Vec3 const&); -Local PlayerClass::simulateUseItem(const Arguments &args) { - try { - auto sp = asSimulatedPlayer(); - if (!sp) - return Local(); - - if (args.size() == 0) - return Boolean::newBoolean(sp->simulateUseItem()); - - int slot = -1; - ItemStack *item = nullptr; - if (args[0].isNumber()) - slot = args[0].toInt(); - else if (IsInstanceOf(args[0])) - item = ItemClass::extract(args[0]); - else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - if (args.size() == 1) { - if (item) - return Boolean::newBoolean(sp->simulateUseItem(*item)); - else - return Boolean::newBoolean(sp->simulateUseItemInSlot(slot)); - } +Local PlayerClass::simulateUseItem(const Arguments& args) { + try { + auto sp = asSimulatedPlayer(); + if (!sp) return Local(); + + if (args.size() == 0) return Boolean::newBoolean(sp->simulateUseItem()); + + int slot = -1; + ItemStack* item = nullptr; + if (args[0].isNumber()) slot = args[0].toInt(); + else if (IsInstanceOf(args[0])) item = ItemClass::extract(args[0]); + else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + if (args.size() == 1) { + if (item) return Boolean::newBoolean(sp->simulateUseItem(*item)); + else return Boolean::newBoolean(sp->simulateUseItemInSlot(slot)); + } - BlockPos bpos; - ScriptModuleMinecraft::ScriptFacing face = - (ScriptModuleMinecraft::ScriptFacing)0; - Vec3 relativePos = {0.5, 0.5, 0.5}; - if (IsInstanceOf(args[1])) - bpos = IntPos::extractPos(args[1])->getBlockPos(); - else if (IsInstanceOf(args[1])) - bpos = FloatPos::extractPos(args[1])->getVec3(); - else { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - if (args.size() > 2) { - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - face = (ScriptModuleMinecraft::ScriptFacing)args[2].toInt(); - if (args.size() > 3) { - if (IsInstanceOf(args[3])) { - relativePos = FloatPos::extractPos(args[3])->getVec3(); - } else { - LOG_WRONG_ARG_TYPE(); - return Local(); + BlockPos bpos; + ScriptModuleMinecraft::ScriptFacing face = (ScriptModuleMinecraft::ScriptFacing)0; + Vec3 relativePos = {0.5, 0.5, 0.5}; + if (IsInstanceOf(args[1])) bpos = IntPos::extractPos(args[1])->getBlockPos(); + else if (IsInstanceOf(args[1])) bpos = FloatPos::extractPos(args[1])->getVec3(); + else { + LOG_WRONG_ARG_TYPE(); + return Local(); } - } + if (args.size() > 2) { + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + face = (ScriptModuleMinecraft::ScriptFacing)args[2].toInt(); + if (args.size() > 3) { + if (IsInstanceOf(args[3])) { + relativePos = FloatPos::extractPos(args[3])->getVec3(); + } else { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + } + } + if (item) return Boolean::newBoolean(sp->simulateUseItemOnBlock(*item, bpos, face, relativePos)); + else return Boolean::newBoolean(sp->simulateUseItemInSlotOnBlock(slot, bpos, face, relativePos)); } - if (item) - return Boolean::newBoolean( - sp->simulateUseItemOnBlock(*item, bpos, face, relativePos)); - else - return Boolean::newBoolean( - sp->simulateUseItemInSlotOnBlock(slot, bpos, face, relativePos)); - } - CATCH("Fail in " __FUNCTION__ "!") + CATCH("Fail in " __FUNCTION__ "!") }; // void simulateStopDestroyingBlock(); // void simulateStopInteracting(); // void simulateStopMoving(); // void simulateStopUsingItem(); -Local PlayerClass::simulateStopDestroyingBlock(const Arguments &args) { - try { - auto sp = asSimulatedPlayer(); - if (!sp) - return Local(); - sp->simulateStopDestroyingBlock(); - return Boolean::newBoolean(true); - } - CATCH("Fail in " __FUNCTION__ "!") +Local PlayerClass::simulateStopDestroyingBlock(const Arguments& args) { + try { + auto sp = asSimulatedPlayer(); + if (!sp) return Local(); + sp->simulateStopDestroyingBlock(); + return Boolean::newBoolean(true); + } + CATCH("Fail in " __FUNCTION__ "!") }; -Local PlayerClass::simulateStopInteracting(const Arguments &args) { - try { - auto sp = asSimulatedPlayer(); - if (!sp) - return Local(); - sp->simulateStopInteracting(); - return Boolean::newBoolean(true); - } - CATCH("Fail in " __FUNCTION__ "!") +Local PlayerClass::simulateStopInteracting(const Arguments& args) { + try { + auto sp = asSimulatedPlayer(); + if (!sp) return Local(); + sp->simulateStopInteracting(); + return Boolean::newBoolean(true); + } + CATCH("Fail in " __FUNCTION__ "!") }; -Local PlayerClass::simulateStopMoving(const Arguments &args) { - try { - auto sp = asSimulatedPlayer(); - if (!sp) - return Local(); - sp->simulateStopMoving(); - return Boolean::newBoolean(true); - } - CATCH("Fail in " __FUNCTION__ "!") +Local PlayerClass::simulateStopMoving(const Arguments& args) { + try { + auto sp = asSimulatedPlayer(); + if (!sp) return Local(); + sp->simulateStopMoving(); + return Boolean::newBoolean(true); + } + CATCH("Fail in " __FUNCTION__ "!") }; -Local PlayerClass::simulateStopUsingItem(const Arguments &args) { - try { - auto sp = asSimulatedPlayer(); - if (!sp) - return Local(); - sp->simulateStopUsingItem(); - return Boolean::newBoolean(true); - } - CATCH("Fail in " __FUNCTION__ "!") +Local PlayerClass::simulateStopUsingItem(const Arguments& args) { + try { + auto sp = asSimulatedPlayer(); + if (!sp) return Local(); + sp->simulateStopUsingItem(); + return Boolean::newBoolean(true); + } + CATCH("Fail in " __FUNCTION__ "!") }; -Local PlayerClass::simulateStopSneaking(const Arguments &args) { - try { - auto sp = asSimulatedPlayer(); - if (!sp) - return Local(); +Local PlayerClass::simulateStopSneaking(const Arguments& args) { + try { + auto sp = asSimulatedPlayer(); + if (!sp) return Local(); - return Boolean::newBoolean(sp->simulateStopSneaking()); - } - CATCH("Fail in " __FUNCTION__ "!") + return Boolean::newBoolean(sp->simulateStopSneaking()); + } + CATCH("Fail in " __FUNCTION__ "!") } diff --git a/src/api/StructureAPI.cpp b/src/api/StructureAPI.cpp index 9339cee8..fee911d7 100644 --- a/src/api/StructureAPI.cpp +++ b/src/api/StructureAPI.cpp @@ -10,88 +10,89 @@ #include "mc/world/level/levelgen/structure/BoundingBox.h" #include "mc/world/level/levelgen/structure/StructureTemplate.h" -Local McClass::getStructure(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - if (!IsInstanceOf(args[0])) { - LOG_WRONG_ARG_TYPE(); - return Local(); - } +Local McClass::getStructure(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + if (!IsInstanceOf(args[0])) { + LOG_WRONG_ARG_TYPE(); + return Local(); + } - if (!IsInstanceOf(args[1])) { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - auto argsSize = args.size(); - bool ignoreBlocks = false; - bool ignoreEntities = false; - if (argsSize > 2) { - CHECK_ARG_TYPE(args[2], ValueKind::kBoolean); - ignoreBlocks = args[2].asBoolean().value(); - } - if (argsSize > 3) { - CHECK_ARG_TYPE(args[3], ValueKind::kBoolean); - ignoreEntities = args[3].asBoolean().value(); - } - try { - IntPos *pos1 = IntPos::extractPos(args[0]); - IntPos *pos2 = IntPos::extractPos(args[1]); - if (pos1->getDimensionId() != pos2->getDimensionId()) { - LOG_ERROR_WITH_SCRIPT_INFO("Pos should in the same dimension!"); - return Local(); + if (!IsInstanceOf(args[1])) { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + auto argsSize = args.size(); + bool ignoreBlocks = false; + bool ignoreEntities = false; + if (argsSize > 2) { + CHECK_ARG_TYPE(args[2], ValueKind::kBoolean); + ignoreBlocks = args[2].asBoolean().value(); } + if (argsSize > 3) { + CHECK_ARG_TYPE(args[3], ValueKind::kBoolean); + ignoreEntities = args[3].asBoolean().value(); + } + try { + IntPos* pos1 = IntPos::extractPos(args[0]); + IntPos* pos2 = IntPos::extractPos(args[1]); + if (pos1->getDimensionId() != pos2->getDimensionId()) { + LOG_ERROR_WITH_SCRIPT_INFO("Pos should in the same dimension!"); + return Local(); + } - auto structure = StructureTemplate::create( - "", - ll::service::getLevel() - ->getDimension(pos1->getDimensionId()) - ->getBlockSourceFromMainChunkSource(), - BoundingBox(pos1->getBlockPos(), pos2->getBlockPos()), ignoreBlocks, - ignoreEntities); + auto structure = StructureTemplate::create( + "", + ll::service::getLevel()->getDimension(pos1->getDimensionId())->getBlockSourceFromMainChunkSource(), + BoundingBox(pos1->getBlockPos(), pos2->getBlockPos()), + ignoreBlocks, + ignoreEntities + ); - return NbtCompoundClass::pack(std::move(structure->save())); - } - CATCH("Fail in getStructure!"); + return NbtCompoundClass::pack(std::move(structure->save())); + } + CATCH("Fail in getStructure!"); } -Local McClass::setStructure(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - auto nbt = NbtCompoundClass::extract(args[0]); - if (!nbt) { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - if (!IsInstanceOf(args[1])) { - LOG_WRONG_ARG_TYPE(); - return Local(); - } - auto argsSize = args.size(); - Mirror mirror = Mirror::None; - Rotation rotation = Rotation::None; - if (argsSize > 2) { - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - auto rawMirror = args[2].asNumber().toInt32(); - if (rawMirror > 3 || rawMirror < 0) { - return Local(); +Local McClass::setStructure(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + auto nbt = NbtCompoundClass::extract(args[0]); + if (!nbt) { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + if (!IsInstanceOf(args[1])) { + LOG_WRONG_ARG_TYPE(); + return Local(); + } + auto argsSize = args.size(); + Mirror mirror = Mirror::None; + Rotation rotation = Rotation::None; + if (argsSize > 2) { + CHECK_ARG_TYPE(args[2], ValueKind::kNumber); + auto rawMirror = args[2].asNumber().toInt32(); + if (rawMirror > 3 || rawMirror < 0) { + return Local(); + } + mirror = static_cast(rawMirror); + } + if (argsSize > 3) { + CHECK_ARG_TYPE(args[3], ValueKind::kNumber); + auto rawRotation = args[3].asNumber().toInt32(); + if (rawRotation > 4 || rawRotation < 0) { + return Local(); + } + rotation = static_cast(rawRotation); } - mirror = static_cast(rawMirror); - } - if (argsSize > 3) { - CHECK_ARG_TYPE(args[3], ValueKind::kNumber); - auto rawRotation = args[3].asNumber().toInt32(); - if (rawRotation > 4 || rawRotation < 0) { - return Local(); + try { + IntPos* pos = IntPos::extractPos(args[1]); + auto structure = StructureTemplate::create("", *nbt); + structure->placeInWorld( + ll::service::getLevel()->getDimension(pos->getDimensionId())->getBlockSourceFromMainChunkSource(), + pos->getBlockPos() + BlockPos(0, 1, 0), + mirror, + rotation + ); + return Boolean::newBoolean(true); } - rotation = static_cast(rawRotation); - } - try { - IntPos *pos = IntPos::extractPos(args[1]); - auto structure = StructureTemplate::create("", *nbt); - structure->placeInWorld(ll::service::getLevel() - ->getDimension(pos->getDimensionId()) - ->getBlockSourceFromMainChunkSource(), - pos->getBlockPos() + BlockPos(0, 1, 0), mirror, - rotation); - return Boolean::newBoolean(true); - } - CATCH("Fail in setStructure!"); + CATCH("Fail in setStructure!"); } \ No newline at end of file diff --git a/src/api/SystemAPI.cpp b/src/api/SystemAPI.cpp index bd8aeb1c..29445c6d 100644 --- a/src/api/SystemAPI.cpp +++ b/src/api/SystemAPI.cpp @@ -17,197 +17,177 @@ using namespace std::filesystem; //////////////////// Classes //////////////////// -ClassDefine SystemClassBuilder = - defineClass("system") - .function("getTimeStr", &SystemClass::getTimeStr) - .function("getTimeObj", &SystemClass::getTimeObj) - .function("randomGuid", &SystemClass::randomGuid) - .function("cmd", &SystemClass::cmd) - .function("newProcess", &SystemClass::newProcess) - .build(); +ClassDefine SystemClassBuilder = defineClass("system") + .function("getTimeStr", &SystemClass::getTimeStr) + .function("getTimeObj", &SystemClass::getTimeObj) + .function("randomGuid", &SystemClass::randomGuid) + .function("cmd", &SystemClass::cmd) + .function("newProcess", &SystemClass::newProcess) + .build(); // From LiteLoaderBDSv2 llapi/utils/WinHelper.cpp -bool NewProcess(const std::string &process, - std::function callback = nullptr, - int timeLimit = -1) { - SECURITY_ATTRIBUTES sa; - HANDLE hRead, hWrite; - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.lpSecurityDescriptor = nullptr; - sa.bInheritHandle = TRUE; - - if (!CreatePipe(&hRead, &hWrite, &sa, 0)) - return false; - STARTUPINFOW si = {0}; - PROCESS_INFORMATION pi; - - si.cb = sizeof(STARTUPINFO); - GetStartupInfoW(&si); - si.hStdOutput = si.hStdError = hWrite; - si.dwFlags = STARTF_USESTDHANDLES; - - auto wCmd = str2cwstr(process); - if (!CreateProcessW(nullptr, wCmd, nullptr, nullptr, TRUE, 0, nullptr, - nullptr, &si, &pi)) { - delete[] wCmd; - return false; - } - CloseHandle(hWrite); - CloseHandle(pi.hThread); - - std::thread([hRead{hRead}, hProcess{pi.hProcess}, - callback{std::move(callback)}, timeLimit{timeLimit}, - wCmd{wCmd}]() { +bool NewProcess( + const std::string& process, + std::function callback = nullptr, + int timeLimit = -1 +) { + SECURITY_ATTRIBUTES sa; + HANDLE hRead, hWrite; + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = nullptr; + sa.bInheritHandle = TRUE; + + if (!CreatePipe(&hRead, &hWrite, &sa, 0)) return false; + STARTUPINFOW si = {0}; + PROCESS_INFORMATION pi; + + si.cb = sizeof(STARTUPINFO); + GetStartupInfoW(&si); + si.hStdOutput = si.hStdError = hWrite; + si.dwFlags = STARTF_USESTDHANDLES; + + auto wCmd = str2cwstr(process); + if (!CreateProcessW(nullptr, wCmd, nullptr, nullptr, TRUE, 0, nullptr, nullptr, &si, &pi)) { + delete[] wCmd; + return false; + } + CloseHandle(hWrite); + CloseHandle(pi.hThread); + + std::thread([hRead{hRead}, hProcess{pi.hProcess}, callback{std::move(callback)}, timeLimit{timeLimit}, wCmd{wCmd}]( + ) { #ifndef LSE_DEBUG - _set_se_translator(ll::error_utils::translateSEHtoCE); + _set_se_translator(ll::error_utils::translateSEHtoCE); #endif - if (timeLimit == -1) - WaitForSingleObject(hProcess, INFINITE); - else { - WaitForSingleObject(hProcess, timeLimit); - TerminateProcess(hProcess, -1); - } - char buffer[4096]; - string strOutput; - DWORD bytesRead, exitCode; - - delete[] wCmd; - GetExitCodeProcess(hProcess, &exitCode); - while (true) { - ZeroMemory(buffer, 4096); - if (!ReadFile(hRead, buffer, 4096, &bytesRead, nullptr)) - break; - strOutput.append(buffer, bytesRead); - } - CloseHandle(hRead); - CloseHandle(hProcess); + if (timeLimit == -1) WaitForSingleObject(hProcess, INFINITE); + else { + WaitForSingleObject(hProcess, timeLimit); + TerminateProcess(hProcess, -1); + } + char buffer[4096]; + string strOutput; + DWORD bytesRead, exitCode; + + delete[] wCmd; + GetExitCodeProcess(hProcess, &exitCode); + while (true) { + ZeroMemory(buffer, 4096); + if (!ReadFile(hRead, buffer, 4096, &bytesRead, nullptr)) break; + strOutput.append(buffer, bytesRead); + } + CloseHandle(hRead); + CloseHandle(hProcess); + + try { + if (callback) callback((int)exitCode, strOutput); + } catch (const ll::error_utils::seh_exception& e) { + logger.error("SEH Uncaught Exception Detected!\n{}", ll::string_utils::tou8str(e.what())); + logger.error("In NewProcess callback"); + // PrintCurrentStackTraceback(); + ll::error_utils::printCurrentException(logger); + } catch (...) { + logger.error("NewProcess Callback Failed!"); + logger.error("Uncaught Exception Detected!"); + // PrintCurrentStackTraceback(); + ll::error_utils::printCurrentException(logger); + } + }).detach(); + + return true; +} + +Local SystemClass::cmd(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kFunction); + if (args.size() >= 3) CHECK_ARG_TYPE(args[2], ValueKind::kNumber); try { - if (callback) - callback((int)exitCode, strOutput); - } catch (const ll::error_utils::seh_exception &e) { - logger.error("SEH Uncaught Exception Detected!\n{}", - ll::string_utils::tou8str(e.what())); - logger.error("In NewProcess callback"); - // PrintCurrentStackTraceback(); - ll::error_utils::printCurrentException(logger); - } catch (...) { - logger.error("NewProcess Callback Failed!"); - logger.error("Uncaught Exception Detected!"); - // PrintCurrentStackTraceback(); - ll::error_utils::printCurrentException(logger); + string cmd = args[0].toStr(); + RecordOperation(ENGINE_OWN_DATA()->pluginName, "ExecuteSystemCommand", cmd); + + script::Global callbackFunc{args[1].asFunction()}; + + return Boolean::newBoolean(NewProcess( + "cmd /c" + cmd, + [callback{std::move(callbackFunc)}, engine{EngineScope::currentEngine()}](int exitCode, string output) { + ll::schedule::DelayTask( + ll::chrono::ticks(1), + [engine, callback = std::move(callback), exitCode, output = std::move(output)]() { + if ((ll::getServerStatus() != ll::ServerStatus::Running)) return; + if (!EngineManager::isValid(engine)) return; + + EngineScope scope(engine); + try { + NewTimeout(callback.get(), {Number::newNumber(exitCode), String::newString(output)}, 1); + } + CATCH_IN_CALLBACK("SystemCmd") + } + ); + }, + args.size() >= 3 ? args[2].toInt() : -1 + )); } - }).detach(); - - return true; + CATCH("Fail in SystemCmd"); } -Local SystemClass::cmd(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kFunction); - if (args.size() >= 3) - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - - try { - string cmd = args[0].toStr(); - RecordOperation(ENGINE_OWN_DATA()->pluginName, "ExecuteSystemCommand", cmd); - - script::Global callbackFunc{args[1].asFunction()}; - - return Boolean::newBoolean(NewProcess( - "cmd /c" + cmd, - [callback{std::move(callbackFunc)}, - engine{EngineScope::currentEngine()}](int exitCode, string output) { - ll::schedule::DelayTask( - ll::chrono::ticks(1), [engine, callback = std::move(callback), - exitCode, output = std::move(output)]() { - if ((ll::getServerStatus() != ll::ServerStatus::Running)) - return; - if (!EngineManager::isValid(engine)) - return; - - EngineScope scope(engine); - try { - NewTimeout( - callback.get(), - {Number::newNumber(exitCode), String::newString(output)}, - 1); - } - CATCH_IN_CALLBACK("SystemCmd") - }); - }, - args.size() >= 3 ? args[2].toInt() : -1)); - } - CATCH("Fail in SystemCmd"); -} +Local SystemClass::newProcess(const Arguments& args) { + CHECK_ARGS_COUNT(args, 2); + CHECK_ARG_TYPE(args[0], ValueKind::kString); + CHECK_ARG_TYPE(args[1], ValueKind::kFunction); + if (args.size() >= 3) CHECK_ARG_TYPE(args[2], ValueKind::kNumber); -Local SystemClass::newProcess(const Arguments &args) { - CHECK_ARGS_COUNT(args, 2); - CHECK_ARG_TYPE(args[0], ValueKind::kString); - CHECK_ARG_TYPE(args[1], ValueKind::kFunction); - if (args.size() >= 3) - CHECK_ARG_TYPE(args[2], ValueKind::kNumber); - - try { - string process = args[0].toStr(); - RecordOperation(ENGINE_OWN_DATA()->pluginName, "CreateNewProcess", process); - - script::Global callbackFunc{args[1].asFunction()}; - - return Boolean::newBoolean(NewProcess( - process, - [callback{std::move(callbackFunc)}, - engine{EngineScope::currentEngine()}](int exitCode, string output) { - ll::schedule::DelayTask( - ll::chrono::ticks(1), - [engine, callback = std::move(callback), exitCode, - output = std::move(output)]() { - if ((ll::getServerStatus() != ll::ServerStatus::Running)) - return; - if (!EngineManager::isValid(engine)) - return; - - EngineScope scope(engine); - try { - NewTimeout( - callback.get(), - {Number::newNumber(exitCode), String::newString(output)}, - 1); - } - CATCH_IN_CALLBACK("newProcess") - }) - .call(); - }, - args.size() >= 3 ? args[2].toInt() : -1)); - } - CATCH("Fail in newProcess"); + try { + string process = args[0].toStr(); + RecordOperation(ENGINE_OWN_DATA()->pluginName, "CreateNewProcess", process); + + script::Global callbackFunc{args[1].asFunction()}; + + return Boolean::newBoolean(NewProcess( + process, + [callback{std::move(callbackFunc)}, engine{EngineScope::currentEngine()}](int exitCode, string output) { + ll::schedule::DelayTask( + ll::chrono::ticks(1), + [engine, callback = std::move(callback), exitCode, output = std::move(output)]() { + if ((ll::getServerStatus() != ll::ServerStatus::Running)) return; + if (!EngineManager::isValid(engine)) return; + + EngineScope scope(engine); + try { + NewTimeout(callback.get(), {Number::newNumber(exitCode), String::newString(output)}, 1); + } + CATCH_IN_CALLBACK("newProcess") + } + ).call(); + }, + args.size() >= 3 ? args[2].toInt() : -1 + )); + } + CATCH("Fail in newProcess"); } -Local SystemClass::getTimeStr(const Arguments &args) { - try { - return String::newString(Raw_GetDateTimeStr()); - } - CATCH("Fail in GetTimeStr!") +Local SystemClass::getTimeStr(const Arguments& args) { + try { + return String::newString(Raw_GetDateTimeStr()); + } + CATCH("Fail in GetTimeStr!") } -Local SystemClass::getTimeObj(const Arguments &args) { - try { - SYSTEMTIME st; - GetLocalTime(&st); - Local res = Object::newObject(); - res.set("Y", Number::newNumber((int)st.wYear)); - res.set("M", Number::newNumber((int)st.wMonth)); - res.set("D", Number::newNumber((int)st.wDay)); - res.set("h", Number::newNumber((int)st.wHour)); - res.set("m", Number::newNumber((int)st.wMinute)); - res.set("s", Number::newNumber((int)st.wSecond)); - res.set("ms", Number::newNumber((int)st.wMilliseconds)); - return res; - } - CATCH("Fail in GetTimeNow!") +Local SystemClass::getTimeObj(const Arguments& args) { + try { + SYSTEMTIME st; + GetLocalTime(&st); + Local res = Object::newObject(); + res.set("Y", Number::newNumber((int)st.wYear)); + res.set("M", Number::newNumber((int)st.wMonth)); + res.set("D", Number::newNumber((int)st.wDay)); + res.set("h", Number::newNumber((int)st.wHour)); + res.set("m", Number::newNumber((int)st.wMinute)); + res.set("s", Number::newNumber((int)st.wSecond)); + res.set("ms", Number::newNumber((int)st.wMilliseconds)); + return res; + } + CATCH("Fail in GetTimeNow!") } -Local SystemClass::randomGuid(const Arguments &args) { - return String::newString(Raw_RandomGuid()); -} +Local SystemClass::randomGuid(const Arguments& args) { return String::newString(Raw_RandomGuid()); } diff --git a/src/engine/EngineManager.cpp b/src/engine/EngineManager.cpp index 7d3d2664..1ae2d09c 100644 --- a/src/engine/EngineManager.cpp +++ b/src/engine/EngineManager.cpp @@ -12,93 +12,82 @@ using namespace script; ///////////////////////////////// API ///////////////////////////////// -bool EngineManager::unRegisterEngine(ScriptEngine *toDelete) { - std::unique_lock lock(globalShareData->engineListLock); - for (auto engine = globalShareData->globalEngineList.begin(); - engine != globalShareData->globalEngineList.end(); ++engine) - if (*engine == toDelete) { - globalShareData->globalEngineList.erase(engine); - return true; - } - return false; +bool EngineManager::unRegisterEngine(ScriptEngine* toDelete) { + std::unique_lock lock(globalShareData->engineListLock); + for (auto engine = globalShareData->globalEngineList.begin(); engine != globalShareData->globalEngineList.end(); + ++engine) + if (*engine == toDelete) { + globalShareData->globalEngineList.erase(engine); + return true; + } + return false; } -bool EngineManager::registerEngine(ScriptEngine *engine) { - std::unique_lock lock(globalShareData->engineListLock); - globalShareData->globalEngineList.push_back(engine); - return true; +bool EngineManager::registerEngine(ScriptEngine* engine) { + std::unique_lock lock(globalShareData->engineListLock); + globalShareData->globalEngineList.push_back(engine); + return true; } -ScriptEngine *EngineManager::newEngine(string pluginName, bool isHotLoad) { - ScriptEngine *engine = nullptr; +ScriptEngine* EngineManager::newEngine(string pluginName, bool isHotLoad) { + ScriptEngine* engine = nullptr; #if defined(LLSE_BACKEND_NODEJS) - engine = NodeJsHelper::newEngine(); + engine = NodeJsHelper::newEngine(); #elif !defined(SCRIPTX_BACKEND_WEBASSEMBLY) - engine = new ScriptEngineImpl(); + engine = new ScriptEngineImpl(); #else - engine = ScriptEngineImpl::instance(); + engine = ScriptEngineImpl::instance(); #endif - engine->setData(std::make_shared()); - registerEngine(engine); - if (!pluginName.empty()) { - ENGINE_GET_DATA(engine)->pluginName = pluginName; - } - return engine; + engine->setData(std::make_shared()); + registerEngine(engine); + if (!pluginName.empty()) { + ENGINE_GET_DATA(engine)->pluginName = pluginName; + } + return engine; } -bool EngineManager::isValid(ScriptEngine *engine, bool onlyCheckLocal) { - std::shared_lock lock(globalShareData->engineListLock); - for (auto i = globalShareData->globalEngineList.begin(); - i != globalShareData->globalEngineList.end(); ++i) - if (*i == engine) { - if (engine->isDestroying()) - return false; - if (onlyCheckLocal && getEngineType(engine) != LLSE_BACKEND_TYPE) - return false; - else - return true; - } - return false; +bool EngineManager::isValid(ScriptEngine* engine, bool onlyCheckLocal) { + std::shared_lock lock(globalShareData->engineListLock); + for (auto i = globalShareData->globalEngineList.begin(); i != globalShareData->globalEngineList.end(); ++i) + if (*i == engine) { + if (engine->isDestroying()) return false; + if (onlyCheckLocal && getEngineType(engine) != LLSE_BACKEND_TYPE) return false; + else return true; + } + return false; } -std::vector EngineManager::getLocalEngines() { - std::vector res; - std::shared_lock lock(globalShareData->engineListLock); - for (auto &engine : globalShareData->globalEngineList) { - if (getEngineType(engine) == LLSE_BACKEND_TYPE) - res.push_back(engine); - } - return res; +std::vector EngineManager::getLocalEngines() { + std::vector res; + std::shared_lock lock(globalShareData->engineListLock); + for (auto& engine : globalShareData->globalEngineList) { + if (getEngineType(engine) == LLSE_BACKEND_TYPE) res.push_back(engine); + } + return res; } -std::vector EngineManager::getGlobalEngines() { - std::vector res; - std::shared_lock lock(globalShareData->engineListLock); - for (auto &engine : globalShareData->globalEngineList) { - res.push_back(engine); - } - return res; +std::vector EngineManager::getGlobalEngines() { + std::vector res; + std::shared_lock lock(globalShareData->engineListLock); + for (auto& engine : globalShareData->globalEngineList) { + res.push_back(engine); + } + return res; } -ScriptEngine *EngineManager::getEngine(std::string name, bool onlyLocalEngine) { - std::shared_lock lock(globalShareData->engineListLock); - for (auto &engine : globalShareData->globalEngineList) { - if (onlyLocalEngine && getEngineType(engine) != LLSE_BACKEND_TYPE) - continue; - auto ownerData = ENGINE_GET_DATA(engine); - auto filename = ll::string_utils::u8str2str( - std::filesystem::path( - ll::string_utils::str2wstr(ownerData->pluginFileOrDirPath)) - .filename() - .u8string()); - if (ownerData->pluginName == name || filename == name) - return engine; - } - return nullptr; +ScriptEngine* EngineManager::getEngine(std::string name, bool onlyLocalEngine) { + std::shared_lock lock(globalShareData->engineListLock); + for (auto& engine : globalShareData->globalEngineList) { + if (onlyLocalEngine && getEngineType(engine) != LLSE_BACKEND_TYPE) continue; + auto ownerData = ENGINE_GET_DATA(engine); + auto filename = ll::string_utils::u8str2str( + std::filesystem::path(ll::string_utils::str2wstr(ownerData->pluginFileOrDirPath)).filename().u8string() + ); + if (ownerData->pluginName == name || filename == name) return engine; + } + return nullptr; } -std::string EngineManager::getEngineType(ScriptEngine *engine) { - return ENGINE_GET_DATA(engine)->engineType; -} \ No newline at end of file +std::string EngineManager::getEngineType(ScriptEngine* engine) { return ENGINE_GET_DATA(engine)->engineType; } \ No newline at end of file diff --git a/src/engine/EngineManager.h b/src/engine/EngineManager.h index be24f2a4..fb62a755 100644 --- a/src/engine/EngineManager.h +++ b/src/engine/EngineManager.h @@ -1,23 +1,20 @@ #pragma once -#include "main/PluginManager.h" #include "ScriptX/ScriptX.h" +#include "main/PluginManager.h" #include #include #include class EngineManager { public: - static script::ScriptEngine *newEngine(std::string pluginName = "", - bool isHotLoad = false); - static bool registerEngine(script::ScriptEngine *engine); - static bool unRegisterEngine(script::ScriptEngine *engine); - static bool isValid(script::ScriptEngine *engine, - bool onlyCheckLocal = false); + static script::ScriptEngine* newEngine(std::string pluginName = "", bool isHotLoad = false); + static bool registerEngine(script::ScriptEngine* engine); + static bool unRegisterEngine(script::ScriptEngine* engine); + static bool isValid(script::ScriptEngine* engine, bool onlyCheckLocal = false); - static std::vector getLocalEngines(); - static std::vector getGlobalEngines(); - static script::ScriptEngine *getEngine(std::string name, - bool onlyLocalEngine = false); + static std::vector getLocalEngines(); + static std::vector getGlobalEngines(); + static script::ScriptEngine* getEngine(std::string name, bool onlyLocalEngine = false); - static std::string getEngineType(script::ScriptEngine *engine); + static std::string getEngineType(script::ScriptEngine* engine); }; diff --git a/src/engine/EngineOwnData.h b/src/engine/EngineOwnData.h index 72a15958..1b2a77ac 100644 --- a/src/engine/EngineOwnData.h +++ b/src/engine/EngineOwnData.h @@ -15,14 +15,14 @@ #include "utils/UsingScriptX.inc" struct FormCallbackData { - script::ScriptEngine *engine; - script::Global func; + script::ScriptEngine* engine; + script::Global func; }; struct RemoteCallData { - std::string nameSpace; - std::string funcName; - script::Global callback; + std::string nameSpace; + std::string funcName; + script::Global callback; }; /* @@ -37,73 +37,68 @@ struct SimpleCallbackData class Player; struct EngineOwnData { - // 基础信息 - std::string pluginName = ""; - std::string pluginFileOrDirPath = ""; - std::string engineType = LLSE_BACKEND_TYPE; - - // 表单回调 - std::map formCallbacks; - - // RemoteCall Exported Functions: unordered_map - std::unordered_map exportFuncs; - - /* - uint64_t simpleCallbackIndex = 0; - std::unordered_map simpleCallbacks; - - inline uint64_t addSimpleCallback(script::Local func, - std::vector> values) - { - auto index = ++simpleCallbackIndex; - std::vector> globalValues; - for (auto& value : values) - globalValues.emplace_back(value); - SimpleCallbackData data{EngineScope::currentEngine(), - script::Global(func), std::move(globalValues)}; - simpleCallbacks.emplace(index, std::move(data)); - return index; - } - inline bool removeSimpleCallback(uint64_t index) - { - return simpleCallbacks.erase(index); - } - */ - - // I18nAPI - ll::i18n::I18N *i18n = nullptr; - - // LoggerAPI - ll::Logger logger = ll::Logger(""); - int maxLogLevel = 4; - - // 玩家绑定数据 - std::unordered_map> playerDataDB; - - // Dynamic Call vm for NativeFFI - DCCallVM *dynamicCallVM; - - // Unload Callbacks, use for close database... - int index = 0; - std::unordered_map> unloadCallbacks; - inline int addUnloadCallback(std::function &&cb) { - unloadCallbacks[++index] = cb; - return index; - } - inline bool removeUnloadCallback(int index) { - return unloadCallbacks.erase(index); - } - - // Init - EngineOwnData() { - dynamicCallVM = dcNewCallVM(4096); - dcMode(dynamicCallVM, DC_CALL_C_DEFAULT); - } + // 基础信息 + std::string pluginName = ""; + std::string pluginFileOrDirPath = ""; + std::string engineType = LLSE_BACKEND_TYPE; + + // 表单回调 + std::map formCallbacks; + + // RemoteCall Exported Functions: unordered_map + std::unordered_map exportFuncs; + + /* + uint64_t simpleCallbackIndex = 0; + std::unordered_map simpleCallbacks; + + inline uint64_t addSimpleCallback(script::Local func, + std::vector> values) + { + auto index = ++simpleCallbackIndex; + std::vector> globalValues; + for (auto& value : values) + globalValues.emplace_back(value); + SimpleCallbackData data{EngineScope::currentEngine(), + script::Global(func), std::move(globalValues)}; + simpleCallbacks.emplace(index, std::move(data)); + return index; + } + inline bool removeSimpleCallback(uint64_t index) + { + return simpleCallbacks.erase(index); + } + */ + + // I18nAPI + ll::i18n::I18N* i18n = nullptr; + + // LoggerAPI + ll::Logger logger = ll::Logger(""); + int maxLogLevel = 4; + + // 玩家绑定数据 + std::unordered_map> playerDataDB; + + // Dynamic Call vm for NativeFFI + DCCallVM* dynamicCallVM; + + // Unload Callbacks, use for close database... + int index = 0; + std::unordered_map> unloadCallbacks; + inline int addUnloadCallback(std::function&& cb) { + unloadCallbacks[++index] = cb; + return index; + } + inline bool removeUnloadCallback(int index) { return unloadCallbacks.erase(index); } + + // Init + EngineOwnData() { + dynamicCallVM = dcNewCallVM(4096); + dcMode(dynamicCallVM, DC_CALL_C_DEFAULT); + } }; // 引擎附加数据 -#define ENGINE_GET_DATA(e) \ - (std::static_pointer_cast((e)->getData())) -#define ENGINE_OWN_DATA() \ - (std::static_pointer_cast( \ - EngineScope::currentEngine()->getData())) +#define ENGINE_GET_DATA(e) (std::static_pointer_cast((e)->getData())) +#define ENGINE_OWN_DATA() (std::static_pointer_cast(EngineScope::currentEngine()->getData())) diff --git a/src/engine/GlobalShareData.cpp b/src/engine/GlobalShareData.cpp index fb22c89e..74754f69 100644 --- a/src/engine/GlobalShareData.cpp +++ b/src/engine/GlobalShareData.cpp @@ -10,33 +10,37 @@ #include // 全局共享数据 -GlobalDataType *globalShareData; +GlobalDataType* globalShareData; void InitGlobalShareData() { - HANDLE hGlobalData = CreateFileMapping( - INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(GlobalDataType), - (LLSE_GLOBAL_DATA_NAME + std::to_wstring(GetCurrentProcessId())).c_str()); - if (hGlobalData == NULL) { - logger.error(tr("init.fileMapping.fail")); - localShareData->isFirstInstance = true; - return; - } + HANDLE hGlobalData = CreateFileMapping( + INVALID_HANDLE_VALUE, + NULL, + PAGE_READWRITE, + 0, + sizeof(GlobalDataType), + (LLSE_GLOBAL_DATA_NAME + std::to_wstring(GetCurrentProcessId())).c_str() + ); + if (hGlobalData == NULL) { + logger.error(tr("init.fileMapping.fail")); + localShareData->isFirstInstance = true; + return; + } - LPVOID address = - MapViewOfFile(hGlobalData, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); - if (address == NULL) { - logger.error(tr("init.mapFile.fail")); - localShareData->isFirstInstance = true; - return; - } + LPVOID address = MapViewOfFile(hGlobalData, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); + if (address == NULL) { + logger.error(tr("init.mapFile.fail")); + localShareData->isFirstInstance = true; + return; + } - if (GetLastError() != ERROR_ALREADY_EXISTS) { - // First Time - localShareData->isFirstInstance = true; - globalShareData = new (address) GlobalDataType; - } else { - // Existing - localShareData->isFirstInstance = false; - globalShareData = (GlobalDataType *)address; - } + if (GetLastError() != ERROR_ALREADY_EXISTS) { + // First Time + localShareData->isFirstInstance = true; + globalShareData = new (address) GlobalDataType; + } else { + // Existing + localShareData->isFirstInstance = false; + globalShareData = (GlobalDataType*)address; + } } \ No newline at end of file diff --git a/src/engine/GlobalShareData.h b/src/engine/GlobalShareData.h index ec094a10..0e373be3 100644 --- a/src/engine/GlobalShareData.h +++ b/src/engine/GlobalShareData.h @@ -11,44 +11,44 @@ // 导出函数表 struct ExportedFuncData { - std::string fromEngineType; - ScriptEngine *engine; - script::Global func; - std::function)> callback; + std::string fromEngineType; + ScriptEngine* engine; + script::Global func; + std::function)> callback; }; // 消息系统处理函数信息 struct MessageHandlers { - script::utils::Message::MessageProc *handler; - script::utils::Message::MessageProc *cleaner; + script::utils::Message::MessageProc* handler; + script::utils::Message::MessageProc* cleaner; }; // 全局共享数据 struct GlobalDataType { - // 引擎管理器表 - std::shared_mutex engineListLock; - std::list globalEngineList; + // 引擎管理器表 + std::shared_mutex engineListLock; + std::list globalEngineList; - // 注册过的命令 - std::unordered_map playerRegisteredCmd; - std::unordered_map consoleRegisteredCmd; + // 注册过的命令 + std::unordered_map playerRegisteredCmd; + std::unordered_map consoleRegisteredCmd; - // 导出函数表 - std::unordered_map exportedFuncs; + // 导出函数表 + std::unordered_map exportedFuncs; - // 模块消息系统 - int messageSystemNextId = 0; - std::map messageSystemHandlers; - std::map messageThreads; + // 模块消息系统 + int messageSystemNextId = 0; + std::map messageSystemHandlers; + std::map messageThreads; - // OperationCount - std::map operationCountData; + // OperationCount + std::map operationCountData; }; //////////////////// Externs //////////////////// // 全局共享数据 -extern GlobalDataType *globalShareData; +extern GlobalDataType* globalShareData; //////////////////// APIs //////////////////// diff --git a/src/engine/LocalShareData.cpp b/src/engine/LocalShareData.cpp index 2c2b2df0..d9939fb3 100644 --- a/src/engine/LocalShareData.cpp +++ b/src/engine/LocalShareData.cpp @@ -4,7 +4,7 @@ #include // DLL本地共享数据 -LocalDataType *localShareData; +LocalDataType* localShareData; // 命令延迟注册队列 std::vector toRegCmdQueue; @@ -15,6 +15,6 @@ ThreadPool pool(LLSE_POOL_THREAD_COUNT); std::mutex messageLoopLock; void InitLocalShareData() { - srand(clock()); - localShareData = new LocalDataType; + srand(clock()); + localShareData = new LocalDataType; } \ No newline at end of file diff --git a/src/engine/LocalShareData.h b/src/engine/LocalShareData.h index c8269d46..54a8d20f 100644 --- a/src/engine/LocalShareData.h +++ b/src/engine/LocalShareData.h @@ -10,47 +10,45 @@ // 命令回调信息结构体 struct CmdCallbackData { - ScriptEngine *fromEngine; - int perm; - script::Global func; + ScriptEngine* fromEngine; + int perm; + script::Global func; }; // 命令延迟注册队列 struct RegCmdQueue { - std::string cmd; - std::string describe; - int level; + std::string cmd; + std::string describe; + int level; }; // 命令回调map排序 - struct CmdCallbackMapCmp { - bool operator()(std::string const &a, std::string const &b) const { - if (a.size() != b.size()) - return a.size() > b.size(); - else - return a > b; - } +struct CmdCallbackMapCmp { + bool operator()(std::string const& a, std::string const& b) const { + if (a.size() != b.size()) return a.size() > b.size(); + else return a > b; + } }; // DLL本地共享数据 struct LocalDataType { - // 是否是第一个ScriptEngine实例 - bool isFirstInstance = true; + // 是否是第一个ScriptEngine实例 + bool isFirstInstance = true; - // 玩家命令回调 - std::map playerCmdCallbacks; + // 玩家命令回调 + std::map playerCmdCallbacks; - // 控制台命令回调 - std::map consoleCmdCallbacks; + // 控制台命令回调 + std::map consoleCmdCallbacks; - // 真指令回调 - std::map commandCallbacks; + // 真指令回调 + std::map commandCallbacks; }; //////////////////// Externs //////////////////// // DLL本地共享数据 -extern LocalDataType *localShareData; +extern LocalDataType* localShareData; // 命令延迟注册队列 extern std::vector toRegCmdQueue; diff --git a/src/engine/MessageSystem.cpp b/src/engine/MessageSystem.cpp index 549158f4..3faaed56 100644 --- a/src/engine/MessageSystem.cpp +++ b/src/engine/MessageSystem.cpp @@ -16,361 +16,324 @@ using namespace script; -#define GET_MESSAGE_TYPE(ENGINE) (ModuleMessage::MessageType) ENGINE.data0 -#define GET_MESSAGE_HEADER(ENGINE) (ModuleMessage::MessageHeader *)ENGINE.ptr0 -#define GET_MESSAGE_DATA_PTR(ENGINE) (std::string *)ENGINE.ptr1 -#define MESSAGE_TYPE data0 -#define MESSAGE_HEADER ptr0 -#define MESSAGE_DATA_PTR ptr1 +#define GET_MESSAGE_TYPE(ENGINE) (ModuleMessage::MessageType) ENGINE.data0 +#define GET_MESSAGE_HEADER(ENGINE) (ModuleMessage::MessageHeader*)ENGINE.ptr0 +#define GET_MESSAGE_DATA_PTR(ENGINE) (std::string*)ENGINE.ptr1 +#define MESSAGE_TYPE data0 +#define MESSAGE_HEADER ptr0 +#define MESSAGE_DATA_PTR ptr1 //////////////////// 消息处理注册 //////////////////// #include "engine/RemoteCall.h" #include "engine/TimeTaskSystem.h" -void ModuleMessage::handle( - utils::Message &engineMsg) // Warning: Execute in another thread +void ModuleMessage::handle(utils::Message& engineMsg) // Warning: Execute in another thread { - ModuleMessage msg; - msg.type = GET_MESSAGE_TYPE(engineMsg); - msg.header = GET_MESSAGE_HEADER(engineMsg); - msg.data = GET_MESSAGE_DATA_PTR(engineMsg); - - switch (msg.getType()) { - case ModuleMessage::MessageType::RemoteSyncCallRequest: - RemoteSyncCallRequest(msg); - break; - case ModuleMessage::MessageType::RemoteSyncCallReturn: - RemoteSyncCallReturn(msg); - break; - /*case ModuleMessage::MessageType::RemoteLoadRequest: - RemoteLoadRequest(msg); - break; - case ModuleMessage::MessageType::RemoteLoadReturn: - RemoteLoadReturn(msg); - break;*/ - default: - break; - } + ModuleMessage msg; + msg.type = GET_MESSAGE_TYPE(engineMsg); + msg.header = GET_MESSAGE_HEADER(engineMsg); + msg.data = GET_MESSAGE_DATA_PTR(engineMsg); + + switch (msg.getType()) { + case ModuleMessage::MessageType::RemoteSyncCallRequest: + RemoteSyncCallRequest(msg); + break; + case ModuleMessage::MessageType::RemoteSyncCallReturn: + RemoteSyncCallReturn(msg); + break; + /*case ModuleMessage::MessageType::RemoteLoadRequest: + RemoteLoadRequest(msg); + break; + case ModuleMessage::MessageType::RemoteLoadReturn: + RemoteLoadReturn(msg); + break;*/ + default: + break; + } } -void ModuleMessage::cleanup(utils::Message &engineMsg) { - delete GET_MESSAGE_HEADER(engineMsg); - delete GET_MESSAGE_DATA_PTR(engineMsg); +void ModuleMessage::cleanup(utils::Message& engineMsg) { + delete GET_MESSAGE_HEADER(engineMsg); + delete GET_MESSAGE_DATA_PTR(engineMsg); } /////////////////////////// Helper /////////////////////////// -utils::Message PackEngineMessage(string toModuleType, - ModuleMessage::MessageType type, string data, - int *messageId = nullptr) { - auto &callbacks = globalShareData->messageSystemHandlers[toModuleType]; - - utils::Message engineMsg(callbacks.handler, callbacks.cleaner); - engineMsg.MESSAGE_TYPE = (int64_t)type; - engineMsg.MESSAGE_HEADER = new ModuleMessage::MessageHeader(); - engineMsg.MESSAGE_DATA_PTR = new string(data); - if (messageId) - *messageId = (GET_MESSAGE_HEADER(engineMsg))->id; - return engineMsg; +utils::Message +PackEngineMessage(string toModuleType, ModuleMessage::MessageType type, string data, int* messageId = nullptr) { + auto& callbacks = globalShareData->messageSystemHandlers[toModuleType]; + + utils::Message engineMsg(callbacks.handler, callbacks.cleaner); + engineMsg.MESSAGE_TYPE = (int64_t)type; + engineMsg.MESSAGE_HEADER = new ModuleMessage::MessageHeader(); + engineMsg.MESSAGE_DATA_PTR = new string(data); + if (messageId) *messageId = (GET_MESSAGE_HEADER(engineMsg))->id; + return engineMsg; } -utils::Message PackEngineMessage(string toModuleType, int messageId, - ModuleMessage::MessageType type, string data) { - auto &callbacks = globalShareData->messageSystemHandlers[toModuleType]; +utils::Message PackEngineMessage(string toModuleType, int messageId, ModuleMessage::MessageType type, string data) { + auto& callbacks = globalShareData->messageSystemHandlers[toModuleType]; - utils::Message engineMsg(callbacks.handler, callbacks.cleaner); - engineMsg.MESSAGE_TYPE = (int64_t)type; - engineMsg.MESSAGE_HEADER = new ModuleMessage::MessageHeader(); - (GET_MESSAGE_HEADER(engineMsg))->id = messageId; - engineMsg.MESSAGE_DATA_PTR = new string(data); - return engineMsg; + utils::Message engineMsg(callbacks.handler, callbacks.cleaner); + engineMsg.MESSAGE_TYPE = (int64_t)type; + engineMsg.MESSAGE_HEADER = new ModuleMessage::MessageHeader(); + (GET_MESSAGE_HEADER(engineMsg))->id = messageId; + engineMsg.MESSAGE_DATA_PTR = new string(data); + return engineMsg; } /////////////////////////// Module Message /////////////////////////// -int ModuleMessage::getNextMessageId() { - return InterlockedIncrement((LONG *)&(globalShareData->messageSystemNextId)); +int ModuleMessage::getNextMessageId() { return InterlockedIncrement((LONG*)&(globalShareData->messageSystemNextId)); } + +ModuleMessageResult ModuleMessage::broadcastLocal(MessageType type, string data, int64_t delay) { + std::vector engineList; + int msgId = -1; + + auto engines = EngineManager::getLocalEngines(); + for (auto& engine : engines) { + try { + engine->messageQueue()->postMessage( + PackEngineMessage(LLSE_MODULE_TYPE, type, data, &msgId), + std::chrono::milliseconds(delay) + ); + engineList.push_back(engine); + } catch (const Exception& e) { + EngineScope scope(engine); + logger.error("Fail to post message to plugin {}", ENGINE_GET_DATA(engine)->pluginName); + PrintException(e); + } catch (...) { + EngineScope scope(engine); + logger.error("Fail to post message to plugin {}", ENGINE_GET_DATA(engine)->pluginName); + } + } + return ModuleMessageResult(msgId, engineList); } -ModuleMessageResult ModuleMessage::broadcastLocal(MessageType type, string data, - int64_t delay) { - std::vector engineList; - int msgId = -1; - - auto engines = EngineManager::getLocalEngines(); - for (auto &engine : engines) { - try { - engine->messageQueue()->postMessage( - PackEngineMessage(LLSE_MODULE_TYPE, type, data, &msgId), - std::chrono::milliseconds(delay)); - engineList.push_back(engine); - } catch (const Exception &e) { - EngineScope scope(engine); - logger.error("Fail to post message to plugin {}", - ENGINE_GET_DATA(engine)->pluginName); - PrintException(e); - } catch (...) { - EngineScope scope(engine); - logger.error("Fail to post message to plugin {}", - ENGINE_GET_DATA(engine)->pluginName); +ModuleMessageResult ModuleMessage::broadcastGlobal(MessageType type, string data, int64_t delay) { + std::vector engineList; + int msgId = -1; + + auto engines = EngineManager::getGlobalEngines(); + for (auto& engine : engines) { + try { + engine->messageQueue()->postMessage( + PackEngineMessage(EngineManager::getEngineType(engine), type, data, &msgId), + std::chrono::milliseconds(delay) + ); + engineList.push_back(engine); + } catch (const Exception& e) { + EngineScope scope(engine); + logger.error("Fail to post message to plugin {}", ENGINE_GET_DATA(engine)->pluginName); + PrintException(e); + } catch (...) { + EngineScope scope(engine); + logger.error("Fail to post message to plugin {}", ENGINE_GET_DATA(engine)->pluginName); + } } - } - return ModuleMessageResult(msgId, engineList); + return ModuleMessageResult(msgId, engineList); } -ModuleMessageResult ModuleMessage::broadcastGlobal(MessageType type, - string data, int64_t delay) { - std::vector engineList; - int msgId = -1; - - auto engines = EngineManager::getGlobalEngines(); - for (auto &engine : engines) { - try { - engine->messageQueue()->postMessage( - PackEngineMessage(EngineManager::getEngineType(engine), type, data, - &msgId), - std::chrono::milliseconds(delay)); - engineList.push_back(engine); - } catch (const Exception &e) { - EngineScope scope(engine); - logger.error("Fail to post message to plugin {}", - ENGINE_GET_DATA(engine)->pluginName); - PrintException(e); - } catch (...) { - EngineScope scope(engine); - logger.error("Fail to post message to plugin {}", - ENGINE_GET_DATA(engine)->pluginName); +ModuleMessageResult ModuleMessage::broadcastTo(std::string toModuleType, MessageType type, string data, int64_t delay) { + std::vector engineList; + int msgId = -1; + + auto engines = EngineManager::getGlobalEngines(); + for (auto& engine : engines) { + if (EngineManager::getEngineType(engine) == toModuleType) { + try { + engine->messageQueue()->postMessage( + PackEngineMessage(toModuleType, type, data, &msgId), + std::chrono::milliseconds(delay) + ); + engineList.push_back(engine); + } catch (const Exception& e) { + EngineScope scope(engine); + logger.error("Fail to post message to plugin {}", ENGINE_GET_DATA(engine)->pluginName); + PrintException(e); + } catch (...) { + EngineScope scope(engine); + logger.error("Fail to post message to plugin {}", ENGINE_GET_DATA(engine)->pluginName); + } + } } - } - return ModuleMessageResult(msgId, engineList); + return ModuleMessageResult(msgId, engineList); } -ModuleMessageResult ModuleMessage::broadcastTo(std::string toModuleType, - MessageType type, string data, - int64_t delay) { - std::vector engineList; - int msgId = -1; +ModuleMessageResult ModuleMessage::sendTo(ScriptEngine* engine, MessageType type, std::string data, int64_t delay) { + int msgId = -1; + string toModuleType = LLSE_MODULE_TYPE; - auto engines = EngineManager::getGlobalEngines(); - for (auto &engine : engines) { - if (EngineManager::getEngineType(engine) == toModuleType) { - try { + try { engine->messageQueue()->postMessage( - PackEngineMessage(toModuleType, type, data, &msgId), - std::chrono::milliseconds(delay)); - engineList.push_back(engine); - } catch (const Exception &e) { + PackEngineMessage(EngineManager::getEngineType(engine), type, data, &msgId), + std::chrono::milliseconds(delay) + ); + return ModuleMessageResult(msgId, {engine}); + } catch (const Exception& e) { EngineScope scope(engine); - logger.error("Fail to post message to plugin {}", - ENGINE_GET_DATA(engine)->pluginName); + logger.error("Fail to post message to plugin {}", ENGINE_GET_DATA(engine)->pluginName); PrintException(e); - } catch (...) { + } catch (...) { EngineScope scope(engine); - logger.error("Fail to post message to plugin {}", - ENGINE_GET_DATA(engine)->pluginName); - } + logger.error("Fail to post message to plugin {}", ENGINE_GET_DATA(engine)->pluginName); } - } - return ModuleMessageResult(msgId, engineList); + return ModuleMessageResult(msgId, {}); } -ModuleMessageResult ModuleMessage::sendTo(ScriptEngine *engine, - MessageType type, std::string data, - int64_t delay) { - int msgId = -1; - string toModuleType = LLSE_MODULE_TYPE; - - try { - engine->messageQueue()->postMessage( - PackEngineMessage(EngineManager::getEngineType(engine), type, data, - &msgId), - std::chrono::milliseconds(delay)); - return ModuleMessageResult(msgId, {engine}); - } catch (const Exception &e) { - EngineScope scope(engine); - logger.error("Fail to post message to plugin {}", - ENGINE_GET_DATA(engine)->pluginName); - PrintException(e); - } catch (...) { - EngineScope scope(engine); - logger.error("Fail to post message to plugin {}", - ENGINE_GET_DATA(engine)->pluginName); - } - return ModuleMessageResult(msgId, {}); +ModuleMessageResult +ModuleMessage::sendToRandom(std::string toModuleType, MessageType type, std::string data, int64_t delay) { + int msgId = -1; + + auto engines = EngineManager::getGlobalEngines(); + for (auto& engine : engines) { + if (EngineManager::getEngineType(engine) == toModuleType) { + try { + engine->messageQueue()->postMessage( + PackEngineMessage(toModuleType, type, data, &msgId), + std::chrono::milliseconds(delay) + ); + return ModuleMessageResult(msgId, {engine}); + } catch (const Exception& e) { + EngineScope scope(engine); + logger.error("Fail to post message to plugin {}", ENGINE_GET_DATA(engine)->pluginName); + PrintException(e); + } catch (...) { + EngineScope scope(engine); + logger.error("Fail to post message to plugin {}", ENGINE_GET_DATA(engine)->pluginName); + } + } + } + return ModuleMessageResult(msgId, {}); } -ModuleMessageResult ModuleMessage::sendToRandom(std::string toModuleType, - MessageType type, - std::string data, - int64_t delay) { - int msgId = -1; +bool ModuleMessage::sendResult(MessageType type, std::string data, int64_t delay) { + int msgId = header->id; + ScriptEngine* engine = header->fromEngine; - auto engines = EngineManager::getGlobalEngines(); - for (auto &engine : engines) { - if (EngineManager::getEngineType(engine) == toModuleType) { - try { + try { engine->messageQueue()->postMessage( - PackEngineMessage(toModuleType, type, data, &msgId), - std::chrono::milliseconds(delay)); - return ModuleMessageResult(msgId, {engine}); - } catch (const Exception &e) { + PackEngineMessage(header->fromEngineModuleType, msgId, type, data), + std::chrono::milliseconds(delay) + ); + return true; + } catch (const Exception& e) { EngineScope scope(engine); - logger.error("Fail to post message to plugin {}", - ENGINE_GET_DATA(engine)->pluginName); + logger.error("Fail to post message to plugin {}", ENGINE_GET_DATA(engine)->pluginName); PrintException(e); - } catch (...) { - EngineScope scope(engine); - logger.error("Fail to post message to plugin {}", - ENGINE_GET_DATA(engine)->pluginName); - } + } catch (...) { + logger.error("Fail to post message to plugin {}", ENGINE_GET_DATA(engine)->pluginName); } - } - return ModuleMessageResult(msgId, {}); -} - -bool ModuleMessage::sendResult(MessageType type, std::string data, - int64_t delay) { - int msgId = header->id; - ScriptEngine *engine = header->fromEngine; - - try { - engine->messageQueue()->postMessage( - PackEngineMessage(header->fromEngineModuleType, msgId, type, data), - std::chrono::milliseconds(delay)); - return true; - } catch (const Exception &e) { - EngineScope scope(engine); - logger.error("Fail to post message to plugin {}", - ENGINE_GET_DATA(engine)->pluginName); - PrintException(e); - } catch (...) { - logger.error("Fail to post message to plugin {}", - ENGINE_GET_DATA(engine)->pluginName); - } - return false; + return false; } /////////////////////////// Module Message Result /////////////////////////// -ModuleMessageResult::ModuleMessageResult(int messageId, - std::vector engineList) - : msgId(messageId), engineList(engineList), - resultCount(OperationCount::create(std::to_string(messageId))) {} +ModuleMessageResult::ModuleMessageResult(int messageId, std::vector engineList) +: msgId(messageId), + engineList(engineList), + resultCount(OperationCount::create(std::to_string(messageId))) {} ModuleMessageResult::operator bool() { return getSentCount() > 0; } ModuleMessageResult::~ModuleMessageResult() { resultCount.remove(); } -bool ModuleMessageResult::waitForAllResults(int maxWaitTime) { - return waitForResultCount(getSentCount(), maxWaitTime); -} +bool ModuleMessageResult::waitForAllResults(int maxWaitTime) { return waitForResultCount(getSentCount(), maxWaitTime); } -bool ModuleMessageResult::waitForOneResult(int maxWaitTime) { - return waitForResultCount(1, maxWaitTime); -} +bool ModuleMessageResult::waitForOneResult(int maxWaitTime) { return waitForResultCount(1, maxWaitTime); } bool ModuleMessageResult::waitForResultCount(int targetCount, int maxWaitTime) { - bool res = false; - auto fromTime = GetCurrentTimeStampMS(); - - while (maxWaitTime < 0 ? true - : GetCurrentTimeStampMS() - fromTime <= maxWaitTime) { - Sleep(LLSE_MESSAGE_SYSTEM_WAIT_CHECK_INTERVAL); - if (resultCount.hasReachCount(targetCount)) { - res = true; - break; + bool res = false; + auto fromTime = GetCurrentTimeStampMS(); + + while (maxWaitTime < 0 ? true : GetCurrentTimeStampMS() - fromTime <= maxWaitTime) { + Sleep(LLSE_MESSAGE_SYSTEM_WAIT_CHECK_INTERVAL); + if (resultCount.hasReachCount(targetCount)) { + res = true; + break; + } + MessageSystemLoopOnce(); } - MessageSystemLoopOnce(); - } - return res; + return res; } bool ModuleMessageResult::cancel() { - int id = msgId; - for (auto &engine : engineList) { - EngineScope scope(engine); - engine->messageQueue()->removeMessageIf([id](utils::Message &message) { - return (GET_MESSAGE_HEADER(message))->id == id - ? utils::MessageQueue::RemoveMessagePredReturnType:: - kRemoveAndContinue - : utils::MessageQueue::RemoveMessagePredReturnType:: - kDontRemove; - }); - } - return true; + int id = msgId; + for (auto& engine : engineList) { + EngineScope scope(engine); + engine->messageQueue()->removeMessageIf([id](utils::Message& message) { + return (GET_MESSAGE_HEADER(message))->id == id + ? utils::MessageQueue::RemoveMessagePredReturnType::kRemoveAndContinue + : utils::MessageQueue::RemoveMessagePredReturnType::kDontRemove; + }); + } + return true; } ///////////////////////////// Funcs ///////////////////////////// void MessageSystemLoopOnce() { - // if (!messageLoopLock.try_lock()) - // return; - std::list tmpList; - { - std::unique_lock lock(globalShareData->engineListLock); - // low efficiency - tmpList = globalShareData->globalEngineList; - } - for (auto engine : tmpList) { - if (EngineManager::isValid(engine) && - EngineManager::getEngineType(engine) == LLSE_BACKEND_TYPE) { - try { - if (EngineScope::currentEngine() == engine) - engine->messageQueue()->loopQueue( - script::utils::MessageQueue::LoopType::kLoopOnce); - else { - EngineScope enter(engine); - engine->messageQueue()->loopQueue( - script::utils::MessageQueue::LoopType::kLoopOnce); + // if (!messageLoopLock.try_lock()) + // return; + std::list tmpList; + { + std::unique_lock lock(globalShareData->engineListLock); + // low efficiency + tmpList = globalShareData->globalEngineList; + } + for (auto engine : tmpList) { + if (EngineManager::isValid(engine) && EngineManager::getEngineType(engine) == LLSE_BACKEND_TYPE) { + try { + if (EngineScope::currentEngine() == engine) + engine->messageQueue()->loopQueue(script::utils::MessageQueue::LoopType::kLoopOnce); + else { + EngineScope enter(engine); + engine->messageQueue()->loopQueue(script::utils::MessageQueue::LoopType::kLoopOnce); + } + } catch (const Exception& e) { + EngineScope scope(engine); + logger.error("Error occurred in Engine Message Loop!"); + logger.error("Uncaught Script Exception Detected!"); + PrintException(e); + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); + } catch (...) { + logger.error("Error occurred in Engine Message Loop!"); + logger.error("Uncaught Exception Detected!"); + } } - } catch (const Exception &e) { - EngineScope scope(engine); - logger.error("Error occurred in Engine Message Loop!"); - logger.error("Uncaught Script Exception Detected!"); - PrintException(e); - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); - } catch (...) { - logger.error("Error occurred in Engine Message Loop!"); - logger.error("Uncaught Exception Detected!"); - } } - } - // messageLoopLock.unlock(); - // logger.debug("Engine-{} Message Loop.", LLSE_MODULE_TYPE); + // messageLoopLock.unlock(); + // logger.debug("Engine-{} Message Loop.", LLSE_MODULE_TYPE); } void InitMessageSystem() { - globalShareData->messageSystemHandlers[LLSE_MODULE_TYPE] = { - ModuleMessage::handle, ModuleMessage::cleanup}; - - ll::event::EventBus::getInstance() - .emplaceListener( - [](ll::event::ServerStoppingEvent &ev) { EndMessageSystemLoop(); }); - - // dangerous? - std::thread([]() { - globalShareData->messageThreads[LLSE_BACKEND_TYPE] = GetCurrentThread(); - while (true) { - MessageSystemLoopOnce(); - if (ll::getServerStatus() != ll::ServerStatus::Stopping) - return; - SleepEx(5, true); - if (ll::getServerStatus() != ll::ServerStatus::Stopping) - return; - } - }).detach(); + globalShareData->messageSystemHandlers[LLSE_MODULE_TYPE] = {ModuleMessage::handle, ModuleMessage::cleanup}; + + ll::event::EventBus::getInstance().emplaceListener( + [](ll::event::ServerStoppingEvent& ev) { EndMessageSystemLoop(); } + ); + + // dangerous? + std::thread([]() { + globalShareData->messageThreads[LLSE_BACKEND_TYPE] = GetCurrentThread(); + while (true) { + MessageSystemLoopOnce(); + if (ll::getServerStatus() != ll::ServerStatus::Stopping) return; + SleepEx(5, true); + if (ll::getServerStatus() != ll::ServerStatus::Stopping) return; + } + }).detach(); } // Helper void APCEmptyHelper(ULONG_PTR) { ; } bool EndMessageSystemLoop() { - auto res = globalShareData->messageThreads.find(LLSE_BACKEND_TYPE); - if (res == globalShareData->messageThreads.end()) - return false; + auto res = globalShareData->messageThreads.find(LLSE_BACKEND_TYPE); + if (res == globalShareData->messageThreads.end()) return false; - QueueUserAPC(APCEmptyHelper, res->second, 0); - globalShareData->messageThreads.erase(LLSE_BACKEND_TYPE); - Sleep(1); - return true; + QueueUserAPC(APCEmptyHelper, res->second, 0); + globalShareData->messageThreads.erase(LLSE_BACKEND_TYPE); + Sleep(1); + return true; } diff --git a/src/engine/MessageSystem.h b/src/engine/MessageSystem.h index 4a957a32..fc3cabe9 100644 --- a/src/engine/MessageSystem.h +++ b/src/engine/MessageSystem.h @@ -1,8 +1,8 @@ #pragma once #include "api/APIHelp.h" #include "engine/OperationCount.h" -#include #include +#include #include #include #include @@ -13,77 +13,72 @@ using std::string; class ModuleMessageResult { private: - int msgId; - OperationCount resultCount; - std::vector engineList; + int msgId; + OperationCount resultCount; + std::vector engineList; - friend class ModuleMessage; - ModuleMessageResult(int messageId, std::vector engineList); + friend class ModuleMessage; + ModuleMessageResult(int messageId, std::vector engineList); public: - ModuleMessageResult() : resultCount("") {} - ~ModuleMessageResult(); - operator bool(); + ModuleMessageResult() : resultCount("") {} + ~ModuleMessageResult(); + operator bool(); - int getSentCount() { return engineList.size(); } - int getMsgId() { return msgId; } + int getSentCount() { return engineList.size(); } + int getMsgId() { return msgId; } - bool waitForAllResults(int maxWaitTime = -1); - bool waitForOneResult(int maxWaitTime = -1); - bool waitForResultCount(int targetCount, int maxWaitTime = -1); - bool cancel(); + bool waitForAllResults(int maxWaitTime = -1); + bool waitForOneResult(int maxWaitTime = -1); + bool waitForResultCount(int targetCount, int maxWaitTime = -1); + bool cancel(); }; class ModuleMessage { private: - static int getNextMessageId(); + static int getNextMessageId(); public: - enum class MessageType : UINT { - MODULE_MESSAGE_REQUEST, - RequireBroadcast, - RemoteSyncCallRequest, - // RemoteLoadRequest, - MODULE_MESSAGE_RETURN, - RemoteSyncCallReturn, - // RemoteLoadReturn, - }; - struct MessageHeader { - MessageHeader() { - id = getNextMessageId(); - fromEngine = EngineScope::currentEngine(); - fromEngineModuleType = LLSE_MODULE_TYPE; - } - int id; - ScriptEngine *fromEngine; - string fromEngineModuleType; - }; + enum class MessageType : UINT { + MODULE_MESSAGE_REQUEST, + RequireBroadcast, + RemoteSyncCallRequest, + // RemoteLoadRequest, + MODULE_MESSAGE_RETURN, + RemoteSyncCallReturn, + // RemoteLoadReturn, + }; + struct MessageHeader { + MessageHeader() { + id = getNextMessageId(); + fromEngine = EngineScope::currentEngine(); + fromEngineModuleType = LLSE_MODULE_TYPE; + } + int id; + ScriptEngine* fromEngine; + string fromEngineModuleType; + }; - MessageType type; - MessageHeader *header; - std::string *data; + MessageType type; + MessageHeader* header; + std::string* data; - unsigned getId() { return header->id; } - MessageType getType() { return type; } - std::string getData() { return *data; } + unsigned getId() { return header->id; } + MessageType getType() { return type; } + std::string getData() { return *data; } - static ModuleMessageResult broadcastLocal(MessageType type, std::string data, - int64_t delay = 0); - static ModuleMessageResult broadcastGlobal(MessageType type, std::string data, - int64_t delay = 0); - static ModuleMessageResult broadcastTo(std::string toModuleType, - MessageType type, std::string data, - int64_t delay = 0); - static ModuleMessageResult sendTo(ScriptEngine *engine, MessageType type, - std::string data, int64_t delay = 0); - static ModuleMessageResult sendToRandom(std::string toModuleType, - MessageType type, std::string data, - int64_t delay = 0); + static ModuleMessageResult broadcastLocal(MessageType type, std::string data, int64_t delay = 0); + static ModuleMessageResult broadcastGlobal(MessageType type, std::string data, int64_t delay = 0); + static ModuleMessageResult + broadcastTo(std::string toModuleType, MessageType type, std::string data, int64_t delay = 0); + static ModuleMessageResult sendTo(ScriptEngine* engine, MessageType type, std::string data, int64_t delay = 0); + static ModuleMessageResult + sendToRandom(std::string toModuleType, MessageType type, std::string data, int64_t delay = 0); - bool sendResult(MessageType type, std::string data, int64_t delay = 0); + bool sendResult(MessageType type, std::string data, int64_t delay = 0); - static void handle(script::utils::Message &engineMsg); - static void cleanup(script::utils::Message &engineMsg); + static void handle(script::utils::Message& engineMsg); + static void cleanup(script::utils::Message& engineMsg); }; ///////////////////////////// Funcs ///////////////////////////// diff --git a/src/engine/OperationCount.cpp b/src/engine/OperationCount.cpp index 24c9dfdb..b70f53aa 100644 --- a/src/engine/OperationCount.cpp +++ b/src/engine/OperationCount.cpp @@ -4,55 +4,49 @@ #include "main/Configs.h" #include -OperationCount::OperationCount(const string &name) : name(name) {} - -OperationCount OperationCount::create(const string &name) { - if (exists(name)) - return OperationCount(""); - else { - globalShareData->operationCountData[name] = 0; - return OperationCount(name); - } +OperationCount::OperationCount(const string& name) : name(name) {} + +OperationCount OperationCount::create(const string& name) { + if (exists(name)) return OperationCount(""); + else { + globalShareData->operationCountData[name] = 0; + return OperationCount(name); + } } -bool OperationCount::exists(const string &name) { - return globalShareData->operationCountData.find(name) != - globalShareData->operationCountData.end(); +bool OperationCount::exists(const string& name) { + return globalShareData->operationCountData.find(name) != globalShareData->operationCountData.end(); } bool OperationCount::remove() { - auto p = globalShareData->operationCountData.find(name); - if (p != globalShareData->operationCountData.end()) { - globalShareData->operationCountData.erase(p); - return true; - } - return false; + auto p = globalShareData->operationCountData.find(name); + if (p != globalShareData->operationCountData.end()) { + globalShareData->operationCountData.erase(p); + return true; + } + return false; } bool OperationCount::done() { - auto p = globalShareData->operationCountData.find(name); - if (p != globalShareData->operationCountData.end()) { - InterlockedIncrement((LONG *)&(p->second)); - return true; - } - return false; + auto p = globalShareData->operationCountData.find(name); + if (p != globalShareData->operationCountData.end()) { + InterlockedIncrement((LONG*)&(p->second)); + return true; + } + return false; } int OperationCount::get() { - if (exists(name)) - return globalShareData->operationCountData[name]; - else - return -1; + if (exists(name)) return globalShareData->operationCountData[name]; + else return -1; } bool OperationCount::hasReachCount(int count) { return get() >= count; } bool OperationCount::hasReachMaxEngineCount() { - // Todo - // return hasReachCount(PluginManager::getAllScriptPlugins().size()); - return false; + // Todo + // return hasReachCount(PluginManager::getAllScriptPlugins().size()); + return false; } -bool OperationCount::hasReachMaxBackendCount() { - return hasReachCount(LLSE_VALID_BACKENDS_COUNT); -} \ No newline at end of file +bool OperationCount::hasReachMaxBackendCount() { return hasReachCount(LLSE_VALID_BACKENDS_COUNT); } \ No newline at end of file diff --git a/src/engine/OperationCount.h b/src/engine/OperationCount.h index 55334a40..4d212c34 100644 --- a/src/engine/OperationCount.h +++ b/src/engine/OperationCount.h @@ -9,18 +9,14 @@ class OperationCount { public: OperationCount(const string& name); static OperationCount create(const string& name); - static bool exists(const string& name); - bool remove(); - operator bool() { - return exists(name); - } + static bool exists(const string& name); + bool remove(); + operator bool() { return exists(name); } - bool done(); - inline bool finish() { - return done(); - } + bool done(); + inline bool finish() { return done(); } - int get(); + int get(); bool hasReachCount(int count); bool hasReachMaxEngineCount(); bool hasReachMaxBackendCount(); diff --git a/src/engine/RemoteCall.cpp b/src/engine/RemoteCall.cpp index b9104cfe..6be37cb8 100644 --- a/src/engine/RemoteCall.cpp +++ b/src/engine/RemoteCall.cpp @@ -14,86 +14,80 @@ std::unordered_map remoteResultMap; //////////////////// 消息循环 //////////////////// -void inline StringTrim(string &str) { - if (str.back() == '\n') - str.pop_back(); +void inline StringTrim(string& str) { + if (str.back() == '\n') str.pop_back(); } -void RemoteSyncCallRequest(ModuleMessage &msg) { - // logger.debug("*** Remote call request received."); - // logger.debug("*** Current Module:{}", LLSE_MODULE_TYPE); +void RemoteSyncCallRequest(ModuleMessage& msg) { + // logger.debug("*** Remote call request received."); + // logger.debug("*** Current Module:{}", LLSE_MODULE_TYPE); - std::istringstream sin(msg.getData()); + std::istringstream sin(msg.getData()); - string funcName, argsList; - getline(sin, funcName); - StringTrim(funcName); + string funcName, argsList; + getline(sin, funcName); + StringTrim(funcName); - ScriptEngine *engine = nullptr; - try { - // Real Call - ExportedFuncData *funcData = &(globalShareData->exportedFuncs).at(funcName); - engine = funcData->engine; - EngineScope enter(engine); + ScriptEngine* engine = nullptr; + try { + // Real Call + ExportedFuncData* funcData = &(globalShareData->exportedFuncs).at(funcName); + engine = funcData->engine; + EngineScope enter(engine); - string arg; - vector> argsVector; - while (getline(sin, arg)) { - StringTrim(arg); - argsVector.push_back(JsonToValue(arg)); - } + string arg; + vector> argsVector; + while (getline(sin, arg)) { + StringTrim(arg); + argsVector.push_back(JsonToValue(arg)); + } - // logger.debug("*** Before remote call execute"); - Local result = funcData->func.get().call({}, argsVector); - // logger.debug("*** After remote call execute"); + // logger.debug("*** Before remote call execute"); + Local result = funcData->func.get().call({}, argsVector); + // logger.debug("*** After remote call execute"); - // Feedback - // logger.debug("*** Before remote call result return"); - if (!msg.sendResult(ModuleMessage::MessageType::RemoteSyncCallReturn, - ValueToJson(result))) { - logger.error("Fail to post remote call result return!"); - } - // logger.debug("*** After remote call result return"); - } catch (const Exception &e) { - logger.error("Error occurred in remote engine!\n"); - if (engine) { - EngineScope enter(engine); - PrintException(e); - logger.error("[Error] In Plugin: " + ENGINE_OWN_DATA()->pluginName); - } + // Feedback + // logger.debug("*** Before remote call result return"); + if (!msg.sendResult(ModuleMessage::MessageType::RemoteSyncCallReturn, ValueToJson(result))) { + logger.error("Fail to post remote call result return!"); + } + // logger.debug("*** After remote call result return"); + } catch (const Exception& e) { + logger.error("Error occurred in remote engine!\n"); + if (engine) { + EngineScope enter(engine); + PrintException(e); + logger.error("[Error] In Plugin: " + ENGINE_OWN_DATA()->pluginName); + } - // Feedback - if (!msg.sendResult(ModuleMessage::MessageType::RemoteSyncCallReturn, - "[null]")) { - logger.error("Fail to post remote call result return!"); - } - } catch (const std::out_of_range &e) { - logger.error(string("Fail to import! Function [") + funcName + - "] has not been exported!"); - - // Feedback - if (!msg.sendResult(ModuleMessage::MessageType::RemoteSyncCallReturn, - "[null]")) { - logger.error("Fail to post remote call result return!"); - ; - } - } catch (...) { - logger.error("Error occurred in remote engine!"); - - // Feedback - if (!msg.sendResult(ModuleMessage::MessageType::RemoteSyncCallReturn, - "[null]")) { - logger.error("Fail to post remote call result return!"); - ; + // Feedback + if (!msg.sendResult(ModuleMessage::MessageType::RemoteSyncCallReturn, "[null]")) { + logger.error("Fail to post remote call result return!"); + } + } catch (const std::out_of_range& e) { + logger.error(string("Fail to import! Function [") + funcName + "] has not been exported!"); + + // Feedback + if (!msg.sendResult(ModuleMessage::MessageType::RemoteSyncCallReturn, "[null]")) { + logger.error("Fail to post remote call result return!"); + ; + } + } catch (...) { + logger.error("Error occurred in remote engine!"); + + // Feedback + if (!msg.sendResult(ModuleMessage::MessageType::RemoteSyncCallReturn, "[null]")) { + logger.error("Fail to post remote call result return!"); + ; + } } - } } -void RemoteSyncCallReturn(ModuleMessage &msg) { - // logger.debug("*** Remote call result message received."); - // logger.debug("*** Result: {}", msg.getData()); - remoteResultMap[msg.getId()] = msg.getData(); - OperationCount(std::to_string(msg.getId())).done(); +void RemoteSyncCallReturn(ModuleMessage& msg) { + // logger.debug("*** Remote call result message received."); + // logger.debug("*** Result: {}", msg.getData()); + remoteResultMap[msg.getId()] = msg.getData(); + OperationCount(std::to_string(msg.getId())).done(); } //////////////////// Remote Call //////////////////// diff --git a/src/engine/TimeTaskSystem.cpp b/src/engine/TimeTaskSystem.cpp index 483c6886..69572dcd 100644 --- a/src/engine/TimeTaskSystem.cpp +++ b/src/engine/TimeTaskSystem.cpp @@ -13,43 +13,43 @@ #include #include -std::atomic_uint timeTaskId = 0; -std::shared_mutex locker; +std::atomic_uint timeTaskId = 0; +std::shared_mutex locker; ll::schedule::ServerTimeScheduler scheduler; struct TimeTaskData { - std::shared_ptr> task; - script::Global func; - vector> paras; - script::Global code; - ScriptEngine *engine; - inline void swap(TimeTaskData &rhs) { - std::swap(rhs.task, task); - std::swap(rhs.engine, engine); - rhs.code.swap(code); - rhs.paras.swap(paras); - rhs.func.swap(func); - } + std::shared_ptr> task; + script::Global func; + vector> paras; + script::Global code; + ScriptEngine* engine; + inline void swap(TimeTaskData& rhs) { + std::swap(rhs.task, task); + std::swap(rhs.engine, engine); + rhs.code.swap(code); + rhs.paras.swap(paras); + rhs.func.swap(func); + } }; std::unordered_map timeTaskMap; -#define TIMETASK_CATCH(TASK_TYPE) \ - catch (const Exception &e) { \ - EngineScope scope(engine); \ - logger.error("Error occurred in {}", TASK_TYPE); \ - PrintException(e); \ - logger.error("In Plugin: " + ENGINE_GET_DATA(engine)->pluginName); \ - } \ - catch (const std::exception &e) { \ - logger.error("Error occurred in {}", TASK_TYPE); \ - logger.error("C++ Uncaught Exception Detected!"); \ - logger.error(ll::string_utils::tou8str(e.what())); \ - logger.error("In Plugin: " + ENGINE_GET_DATA(engine)->pluginName); \ - } \ - catch (...) { \ - logger.error("Error occurred in {}", TASK_TYPE); \ - logger.error("Uncaught Exception Detected!"); \ - logger.error("In Plugin: " + ENGINE_GET_DATA(engine)->pluginName); \ - } +#define TIMETASK_CATCH(TASK_TYPE) \ + catch (const Exception& e) { \ + EngineScope scope(engine); \ + logger.error("Error occurred in {}", TASK_TYPE); \ + PrintException(e); \ + logger.error("In Plugin: " + ENGINE_GET_DATA(engine)->pluginName); \ + } \ + catch (const std::exception& e) { \ + logger.error("Error occurred in {}", TASK_TYPE); \ + logger.error("C++ Uncaught Exception Detected!"); \ + logger.error(ll::string_utils::tou8str(e.what())); \ + logger.error("In Plugin: " + ENGINE_GET_DATA(engine)->pluginName); \ + } \ + catch (...) { \ + logger.error("Error occurred in {}", TASK_TYPE); \ + logger.error("Uncaught Exception Detected!"); \ + logger.error("In Plugin: " + ENGINE_GET_DATA(engine)->pluginName); \ + } //////////////////// API //////////////////// @@ -87,229 +87,208 @@ std::unordered_map timeTaskMap; // } int NewTimeout(Local func, vector> paras, int timeout) { - int tid = ++timeTaskId; - TimeTaskData data; + int tid = ++timeTaskId; + TimeTaskData data; - data.func = func; - data.engine = EngineScope::currentEngine(); - for (auto ¶ : paras) - data.paras.emplace_back(std::move(para)); - data.task = scheduler.add( - ll::chrono::ticks(timeout / 50), - [engine{EngineScope::currentEngine()}, id{tid}]() { - try { - if ((ll::getServerStatus() != ll::ServerStatus::Running)) - return; - if (!EngineManager::isValid(engine)) - return; - // lock after enter EngineScope to prevent deadlock - EngineScope scope(engine); - TimeTaskData taskData; - { - std::unique_lock lock(locker); + data.func = func; + data.engine = EngineScope::currentEngine(); + for (auto& para : paras) data.paras.emplace_back(std::move(para)); + data.task = scheduler.add( + ll::chrono::ticks(timeout / 50), + [engine{EngineScope::currentEngine()}, id{tid}]() { + try { + if ((ll::getServerStatus() != ll::ServerStatus::Running)) return; + if (!EngineManager::isValid(engine)) return; + // lock after enter EngineScope to prevent deadlock + EngineScope scope(engine); + TimeTaskData taskData; + { + std::unique_lock lock(locker); - auto t = timeTaskMap.find(id); - if (t == timeTaskMap.end()) - return; - t->second.swap(taskData); - timeTaskMap.erase(id); - } + auto t = timeTaskMap.find(id); + if (t == timeTaskMap.end()) return; + t->second.swap(taskData); + timeTaskMap.erase(id); + } - if (taskData.func.isEmpty()) - return; - auto func = taskData.func.get(); - if (taskData.paras.empty()) { - func.call(); - } else { - vector> args; - for (auto ¶ : taskData.paras) - if (para.isEmpty()) - return; - else - args.emplace_back(para.get()); - func.call({}, args); - } + if (taskData.func.isEmpty()) return; + auto func = taskData.func.get(); + if (taskData.paras.empty()) { + func.call(); + } else { + vector> args; + for (auto& para : taskData.paras) + if (para.isEmpty()) return; + else args.emplace_back(para.get()); + func.call({}, args); + } + } + TIMETASK_CATCH("setTimeout-Function"); } - TIMETASK_CATCH("setTimeout-Function"); - }); - std::unique_lock lock(locker); - data.swap(timeTaskMap[tid]); - return tid; + ); + std::unique_lock lock(locker); + data.swap(timeTaskMap[tid]); + return tid; } int NewTimeout(Local func, int timeout) { - int tid = ++timeTaskId; - TimeTaskData data; + int tid = ++timeTaskId; + TimeTaskData data; - data.code = func; - data.engine = EngineScope::currentEngine(); + data.code = func; + data.engine = EngineScope::currentEngine(); - data.task = scheduler.add( - ll::chrono::ticks(timeout / 50), - [engine{EngineScope::currentEngine()}, id{tid}]() { - try { - if ((ll::getServerStatus() != ll::ServerStatus::Running)) - return; - if (!EngineManager::isValid(engine)) - return; - EngineScope scope(engine); - TimeTaskData taskData; - { - std::unique_lock lock(locker); + data.task = scheduler.add( + ll::chrono::ticks(timeout / 50), + [engine{EngineScope::currentEngine()}, id{tid}]() { + try { + if ((ll::getServerStatus() != ll::ServerStatus::Running)) return; + if (!EngineManager::isValid(engine)) return; + EngineScope scope(engine); + TimeTaskData taskData; + { + std::unique_lock lock(locker); - auto t = timeTaskMap.find(id); - if (t == timeTaskMap.end()) - return; - t->second.swap(taskData); - timeTaskMap.erase(id); - } + auto t = timeTaskMap.find(id); + if (t == timeTaskMap.end()) return; + t->second.swap(taskData); + timeTaskMap.erase(id); + } - if (taskData.code.isEmpty()) - return; - auto code = taskData.code.get().toString(); - engine->eval(code); + if (taskData.code.isEmpty()) return; + auto code = taskData.code.get().toString(); + engine->eval(code); + } + TIMETASK_CATCH("setTimeout-String"); } - TIMETASK_CATCH("setTimeout-String"); - }); + ); - std::unique_lock lock(locker); - data.swap(timeTaskMap[tid]); - return tid; + std::unique_lock lock(locker); + data.swap(timeTaskMap[tid]); + return tid; } int NewInterval(Local func, vector> paras, int timeout) { - int tid = ++timeTaskId; - TimeTaskData data; + int tid = ++timeTaskId; + TimeTaskData data; - data.func = func; - data.engine = EngineScope::currentEngine(); - for (auto ¶ : paras) - data.paras.emplace_back(std::move(para)); + data.func = func; + data.engine = EngineScope::currentEngine(); + for (auto& para : paras) data.paras.emplace_back(std::move(para)); - data.task = scheduler.add( - ll::chrono::ticks(timeout / 50), - [engine{EngineScope::currentEngine()}, id{tid}]() { - try { - if ((ll::getServerStatus() != ll::ServerStatus::Running)) - return; - if (!EngineManager::isValid(engine)) { - ClearTimeTask(id); - return; - } - EngineScope scope(engine); - Local func = Local(); - vector> args; - { - std::unique_lock lock(locker); + data.task = scheduler.add( + ll::chrono::ticks(timeout / 50), + [engine{EngineScope::currentEngine()}, id{tid}]() { + try { + if ((ll::getServerStatus() != ll::ServerStatus::Running)) return; + if (!EngineManager::isValid(engine)) { + ClearTimeTask(id); + return; + } + EngineScope scope(engine); + Local func = Local(); + vector> args; + { + std::unique_lock lock(locker); - auto t = timeTaskMap.find(id); - if (t == timeTaskMap.end()) - return; + auto t = timeTaskMap.find(id); + if (t == timeTaskMap.end()) return; - TimeTaskData &taskData = t->second; + TimeTaskData& taskData = t->second; - if (taskData.func.isEmpty()) - return; - func = taskData.func.get(); - if (!taskData.paras.empty()) { - vector> args; - for (auto ¶ : taskData.paras) - if (para.isEmpty()) - return; - else - args.emplace_back(para.get()); + if (taskData.func.isEmpty()) return; + func = taskData.func.get(); + if (!taskData.paras.empty()) { + vector> args; + for (auto& para : taskData.paras) + if (para.isEmpty()) return; + else args.emplace_back(para.get()); + } + } + if (!func.isFunction()) return; + if (args.size() > 0) func.asFunction().call({}, args); + else func.asFunction().call(); } - } - if (!func.isFunction()) - return; - if (args.size() > 0) - func.asFunction().call({}, args); - else - func.asFunction().call(); + TIMETASK_CATCH("setInterval-Function"); } - TIMETASK_CATCH("setInterval-Function"); - }); + ); - std::unique_lock lock(locker); - data.swap(timeTaskMap[tid]); - return tid; + std::unique_lock lock(locker); + data.swap(timeTaskMap[tid]); + return tid; } int NewInterval(Local func, int timeout) { - int tid = ++timeTaskId; - TimeTaskData data; + int tid = ++timeTaskId; + TimeTaskData data; - data.code = func; - data.engine = EngineScope::currentEngine(); + data.code = func; + data.engine = EngineScope::currentEngine(); - data.task = scheduler.add( - ll::chrono::ticks(timeout / 50), - [engine{EngineScope::currentEngine()}, id{tid}]() { - try { - if ((ll::getServerStatus() != ll::ServerStatus::Running)) - return; - if (!EngineManager::isValid(engine)) { - ClearTimeTask(id); - return; - } - EngineScope scope(engine); - std::string code; - { - std::unique_lock lock(locker); + data.task = scheduler.add( + ll::chrono::ticks(timeout / 50), + [engine{EngineScope::currentEngine()}, id{tid}]() { + try { + if ((ll::getServerStatus() != ll::ServerStatus::Running)) return; + if (!EngineManager::isValid(engine)) { + ClearTimeTask(id); + return; + } + EngineScope scope(engine); + std::string code; + { + std::unique_lock lock(locker); - auto t = timeTaskMap.find(id); - if (t == timeTaskMap.end()) - return; - TimeTaskData &taskData = t->second; + auto t = timeTaskMap.find(id); + if (t == timeTaskMap.end()) return; + TimeTaskData& taskData = t->second; - if (taskData.code.isEmpty()) - return; - code = taskData.code.get().toString(); - } - if (!code.empty()) - engine->eval(code); + if (taskData.code.isEmpty()) return; + code = taskData.code.get().toString(); + } + if (!code.empty()) engine->eval(code); + } + TIMETASK_CATCH("setInterval-String"); } - TIMETASK_CATCH("setInterval-String"); - }); + ); - std::unique_lock lock(locker); - data.swap(timeTaskMap[tid]); - return tid; + std::unique_lock lock(locker); + data.swap(timeTaskMap[tid]); + return tid; } bool ClearTimeTask(int id) { - assert(EngineScope::currentEngine() != nullptr); - TimeTaskData data; - try { - std::unique_lock lock(locker); - auto it = timeTaskMap.find(id); - if (it != timeTaskMap.end()) { - data.swap(timeTaskMap[id]); - timeTaskMap.erase(id); + assert(EngineScope::currentEngine() != nullptr); + TimeTaskData data; + try { + std::unique_lock lock(locker); + auto it = timeTaskMap.find(id); + if (it != timeTaskMap.end()) { + data.swap(timeTaskMap[id]); + timeTaskMap.erase(id); + } + } catch (...) { + logger.error("Fail in ClearTimeTask"); } - } catch (...) { - logger.error("Fail in ClearTimeTask"); - } - return true; + return true; } ///////////////////////// Func ///////////////////////// -void LLSERemoveTimeTaskData(ScriptEngine *engine) { - // enter scope to prevent script::Global::~Global() from crashing - EngineScope enter(engine); - std::unordered_map tmpMap; - try { - std::unique_lock lock(locker); - for (auto it = timeTaskMap.begin(); it != timeTaskMap.end();) { - if (it->second.engine == engine) { - it->second.swap(tmpMap[it->first]); - it = timeTaskMap.erase(it); - } else - ++it; +void LLSERemoveTimeTaskData(ScriptEngine* engine) { + // enter scope to prevent script::Global::~Global() from crashing + EngineScope enter(engine); + std::unordered_map tmpMap; + try { + std::unique_lock lock(locker); + for (auto it = timeTaskMap.begin(); it != timeTaskMap.end();) { + if (it->second.engine == engine) { + it->second.swap(tmpMap[it->first]); + it = timeTaskMap.erase(it); + } else ++it; + } + } catch (...) { + logger.info("Fail in LLSERemoveTimeTaskData"); } - } catch (...) { - logger.info("Fail in LLSERemoveTimeTaskData"); - } - tmpMap.clear(); + tmpMap.clear(); } diff --git a/src/engine/TimeTaskSystem.h b/src/engine/TimeTaskSystem.h index a72188b8..40fc7cc5 100644 --- a/src/engine/TimeTaskSystem.h +++ b/src/engine/TimeTaskSystem.h @@ -1,16 +1,17 @@ #pragma once #include "api/APIHelp.h" -#include #include "engine/MessageSystem.h" +#include ///////////////////////// API ///////////////////////// -// void NewTimeout_s(script::Global func, vector> paras, int timeout, ScriptEngine* engine = EngineScope::currentEngine()); +// void NewTimeout_s(script::Global func, vector> paras, int timeout, ScriptEngine* +// engine = EngineScope::currentEngine()); -int NewTimeout(Local func, std::vector> paras, int timeout); -int NewTimeout(Local func, int timeout); -int NewInterval(Local func, std::vector> paras, int timeout); -int NewInterval(Local func, int timeout); +int NewTimeout(Local func, std::vector> paras, int timeout); +int NewTimeout(Local func, int timeout); +int NewInterval(Local func, std::vector> paras, int timeout); +int NewInterval(Local func, int timeout); bool ClearTimeTask(int id); diff --git a/src/legacyapi/Base64.hpp b/src/legacyapi/Base64.h similarity index 81% rename from src/legacyapi/Base64.hpp rename to src/legacyapi/Base64.h index 0f706bb6..01894064 100644 --- a/src/legacyapi/Base64.hpp +++ b/src/legacyapi/Base64.h @@ -29,13 +29,9 @@ inline const char _base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; -inline size_t getEncodeLength(size_t len) { - return (len + 2 - ((len + 2) % 3)) / 3 * 4; -} +inline size_t getEncodeLength(size_t len) { return (len + 2 - ((len + 2) % 3)) / 3 * 4; } -inline size_t getEncodeLength(const std::string& str) { - return getEncodeLength(str.length()); -} +inline size_t getEncodeLength(const std::string& str) { return getEncodeLength(str.length()); } inline size_t getDecodeLength(const std::string& in) { unsigned char count = 0; @@ -44,7 +40,7 @@ inline size_t getDecodeLength(const std::string& in) { ++count; } input_size -= count; // remove padding size - count = 0; // reset padding counter + count = 0; // reset padding counter while (input_size % 4) { // redo padding input_size++; count++; @@ -53,16 +49,11 @@ inline size_t getDecodeLength(const std::string& in) { } inline unsigned char decodeLookup(unsigned char c) { - if (c >= 'A' && c <= 'Z') - return c - 'A'; - if (c >= 'a' && c <= 'z') - return c - 71; - if (c >= '0' && c <= '9') - return c + 4; - if (c == '+') - return 62; - if (c == '/') - return 63; + if (c >= 'A' && c <= 'Z') return c - 'A'; + if (c >= 'a' && c <= 'z') return c - 71; + if (c >= '0' && c <= '9') return c + 4; + if (c == '+') return 62; + if (c == '/') return 63; return 64; } @@ -78,7 +69,7 @@ inline std::string Encode(const std::string& text_input) { j += 8; while (j >= 0) { result += _base64_table[(i >> j) & 0x3F]; - j -= 6; + j -= 6; } } @@ -107,12 +98,9 @@ inline std::string Decode(const std::string& base64_input) { uint32_t data = (c1 << 3 * 6) + (c2 << 2 * 6) + (c3 << 1 * 6) + (c4 << 0 * 6); - if (j < output_size) - out[j++] = (data >> 2 * 8) & 0xFF; - if (j < output_size) - out[j++] = (data >> 1 * 8) & 0xFF; - if (j < output_size) - out[j++] = (data >> 0 * 8) & 0xFF; + if (j < output_size) out[j++] = (data >> 2 * 8) & 0xFF; + if (j < output_size) out[j++] = (data >> 1 * 8) & 0xFF; + if (j < output_size) out[j++] = (data >> 0 * 8) & 0xFF; } return out; diff --git a/src/legacyapi/db/Any.cpp b/src/legacyapi/db/Any.cpp index 2891a95e..49712208 100644 --- a/src/legacyapi/db/Any.cpp +++ b/src/legacyapi/db/Any.cpp @@ -3,213 +3,200 @@ namespace DB { Any::Any() { - type = Type::Null; - value.boolean = false; + type = Type::Null; + value.boolean = false; } Any::Any(bool v) { - type = Type::Boolean; - value.boolean = v; + type = Type::Boolean; + value.boolean = v; } Any::Any(int64_t v) { - type = Type::Integer; - value.integer = v; + type = Type::Integer; + value.integer = v; } Any::Any(uint64_t v) { - type = Type::UInteger; - value.uinteger = v; + type = Type::UInteger; + value.uinteger = v; } Any::Any(double v) { - type = Type::Floating; - value.floating = v; + type = Type::Floating; + value.floating = v; } -Any::Any(const std::string &v) { - type = Type::String; - value.string = new std::string(v); +Any::Any(const std::string& v) { + type = Type::String; + value.string = new std::string(v); } -Any::Any(const char *v) { - type = Type::String; - value.string = new std::string(v); +Any::Any(const char* v) { + type = Type::String; + value.string = new std::string(v); } -Any::Any(char *v, size_t len) { - type = Type::String; - value.string = new std::string(v, len); +Any::Any(char* v, size_t len) { + type = Type::String; + value.string = new std::string(v, len); } -Any::Any(const Date &v) { - type = Type::Date; - value.date = new Date(v); +Any::Any(const Date& v) { + type = Type::Date; + value.date = new Date(v); } -Any::Any(const Time &v) { - type = Type::Time; - value.time = new Time(v); +Any::Any(const Time& v) { + type = Type::Time; + value.time = new Time(v); } -Any::Any(const DateTime &v) { - type = Type::DateTime; - value.datetime = new DateTime(v); +Any::Any(const DateTime& v) { + type = Type::DateTime; + value.datetime = new DateTime(v); } Any::Any(char v) { - type = Type::Integer; - value.integer = v; + type = Type::Integer; + value.integer = v; } Any::Any(unsigned char v) { - type = Type::UInteger; - value.uinteger = v; + type = Type::UInteger; + value.uinteger = v; } Any::Any(short v) { - type = Type::Integer; - value.integer = v; + type = Type::Integer; + value.integer = v; } Any::Any(unsigned short v) { - type = Type::UInteger; - value.uinteger = v; + type = Type::UInteger; + value.uinteger = v; } Any::Any(int v) { - type = Type::Integer; - value.integer = v; + type = Type::Integer; + value.integer = v; } Any::Any(unsigned int v) { - type = Type::UInteger; - value.uinteger = v; + type = Type::UInteger; + value.uinteger = v; } Any::Any(long v) { - type = Type::Integer; - value.integer = v; + type = Type::Integer; + value.integer = v; } Any::Any(unsigned long v) { - type = Type::UInteger; - value.uinteger = v; + type = Type::UInteger; + value.uinteger = v; } Any::Any(float v) { - type = Type::Floating; - value.floating = v; + type = Type::Floating; + value.floating = v; } -Any::Any(const ByteArray &v) { - type = Type::Blob; - value.blob = new ByteArray(v); +Any::Any(const ByteArray& v) { + type = Type::Blob; + value.blob = new ByteArray(v); } -Any::Any(const Any &v) { *this = v; } +Any::Any(const Any& v) { *this = v; } -Any &Any::operator=(const Any &v) { - if (this == &v) +Any& Any::operator=(const Any& v) { + if (this == &v) return *this; + type = v.type; + value = v.value; + switch (type) { + case Type::String: + value.string = new std::string(*v.value.string); + break; + case Type::Date: + value.date = new Date(*v.value.date); + break; + case Type::Time: + value.time = new Time(*v.value.time); + break; + case Type::DateTime: + value.datetime = new DateTime(*v.value.datetime); + break; + case Type::Blob: + value.blob = new ByteArray(*v.value.blob); + break; + } return *this; - type = v.type; - value = v.value; - switch (type) { - case Type::String: - value.string = new std::string(*v.value.string); - break; - case Type::Date: - value.date = new Date(*v.value.date); - break; - case Type::Time: - value.time = new Time(*v.value.time); - break; - case Type::DateTime: - value.datetime = new DateTime(*v.value.datetime); - break; - case Type::Blob: - value.blob = new ByteArray(*v.value.blob); - break; - } - return *this; } Any::~Any() { - if (type == Type::String) { - delete value.string; - value.string = nullptr; - } else if (type == Type::Date) { - delete value.date; - value.date = nullptr; - } else if (type == Type::Time) { - delete value.time; - value.time = nullptr; - } else if (type == Type::DateTime) { - delete value.datetime; - value.datetime = nullptr; - } else if (type == Type::Blob) { - delete value.blob; - value.blob = nullptr; - } + if (type == Type::String) { + delete value.string; + value.string = nullptr; + } else if (type == Type::Date) { + delete value.date; + value.date = nullptr; + } else if (type == Type::Time) { + delete value.time; + value.time = nullptr; + } else if (type == Type::DateTime) { + delete value.datetime; + value.datetime = nullptr; + } else if (type == Type::Blob) { + delete value.blob; + value.blob = nullptr; + } } bool Any::is_null() const { return type == Type::Null; } bool Any::is_boolean() const { return type == Type::Boolean; } -bool Any::is_integer() const { - return type == Type::Integer || type == Type::UInteger; -} +bool Any::is_integer() const { return type == Type::Integer || type == Type::UInteger; } bool Any::is_uinteger() const { return type == Type::UInteger; } bool Any::is_floating() const { return type == Type::Floating; } bool Any::is_string() const { return type == Type::String; } bool Any::is_date() const { return type == Type::Date; } bool Any::is_time() const { return type == Type::Time; } bool Any::is_datetime() const { return type == Type::DateTime; } -bool Any::is_number() const { - return type == Type::Integer || type == Type::UInteger || - type == Type::Floating; -} +bool Any::is_number() const { return type == Type::Integer || type == Type::UInteger || type == Type::Floating; } bool Any::is_blob() const { return type == Type::Blob; } std::string Any::type2str(Any::Type type) { - switch (type) { - case Type::Null: - return "null"; - case Type::Boolean: - return "boolean"; - case Type::Integer: - return "integer"; - case Type::UInteger: - return "uinteger"; - case Type::Floating: - return "floating"; - case Type::String: - return "string"; - case Type::Date: - return "date"; - case Type::Time: - return "time"; - case Type::DateTime: - return "datetime"; - case Type::Blob: - return "blob"; - default: - return "unknown"; - } + switch (type) { + case Type::Null: + return "null"; + case Type::Boolean: + return "boolean"; + case Type::Integer: + return "integer"; + case Type::UInteger: + return "uinteger"; + case Type::Floating: + return "floating"; + case Type::String: + return "string"; + case Type::Date: + return "date"; + case Type::Time: + return "time"; + case Type::DateTime: + return "datetime"; + case Type::Blob: + return "blob"; + default: + return "unknown"; + } } -Any Any::str2any(const std::string &str) { - if (str.empty()) - return Any(); - bool isInteger = true; - bool isFloating = false; - bool first = true; - for (auto &ch : str) { - if (first && ch == '-') { - first = false; - continue; - } - if (ch >= '0' && ch <= '9') - continue; - if (ch == '.') { - if (isFloating) - isFloating = false; - else { - isInteger = false; - isFloating = true; - } - continue; +Any Any::str2any(const std::string& str) { + if (str.empty()) return Any(); + bool isInteger = true; + bool isFloating = false; + bool first = true; + for (auto& ch : str) { + if (first && ch == '-') { + first = false; + continue; + } + if (ch >= '0' && ch <= '9') continue; + if (ch == '.') { + if (isFloating) isFloating = false; + else { + isInteger = false; + isFloating = true; + } + continue; + } } - } - if (isFloating) - return Any(std::stod(str)); - else if (isInteger) { - auto floating = std::stod(str); - if (floating > ULLONG_MAX || floating < LLONG_MIN) - return Any(floating); - else if (floating > LLONG_MAX) - return Any(std::stoull(str)); - return Any(std::stoll(str)); - } else - return Any(str); + if (isFloating) return Any(std::stod(str)); + else if (isInteger) { + auto floating = std::stod(str); + if (floating > ULLONG_MAX || floating < LLONG_MIN) return Any(floating); + else if (floating > LLONG_MAX) return Any(std::stoull(str)); + return Any(std::stoll(str)); + } else return Any(str); } } // namespace DB \ No newline at end of file diff --git a/src/legacyapi/db/Any.h b/src/legacyapi/db/Any.h index 66014a35..67f1a064 100644 --- a/src/legacyapi/db/Any.h +++ b/src/legacyapi/db/Any.h @@ -22,24 +22,23 @@ class Any; * @param v The Any object * @return T The converted value */ -template inline T any_to(const DB::Any &v) { - throw std::bad_cast(); +template +inline T any_to(const DB::Any& v) { + throw std::bad_cast(); } template -inline std::vector to_any_container(const std::vector &v); +inline std::vector to_any_container(const std::vector& v); template -inline std::set to_any_container(const std::set &v); +inline std::set to_any_container(const std::set& v); template -inline std::list to_any_container(const std::list &v); +inline std::list to_any_container(const std::list& v); template -inline std::unordered_set -to_any_container(const std::unordered_set &v); +inline std::unordered_set to_any_container(const std::unordered_set& v); template -inline std::map to_any_container(const std::map &v); +inline std::map to_any_container(const std::map& v); template -inline std::unordered_map -to_any_unordered_map(const std::unordered_map &v); +inline std::unordered_map to_any_unordered_map(const std::unordered_map& v); #pragma endregion @@ -48,628 +47,658 @@ namespace DB { class Any { public: - union Value { - bool boolean; - int64_t integer; - uint64_t uinteger; - double floating; - std::string *string; - Date *date; - Time *time; - DateTime *datetime; - ByteArray *blob; - } value; ///< Value + union Value { + bool boolean; + int64_t integer; + uint64_t uinteger; + double floating; + std::string* string; + Date* date; + Time* time; + DateTime* datetime; + ByteArray* blob; + } value; ///< Value - enum class Type : char { - Null = 0, - Boolean = 1, - Integer = 2, - UInteger = 3, - Floating = 4, - String = 5, - Date = 6, - Time = 7, - DateTime = 8, - Blob = 9 - } type = Type::Null; ///< Type of the value + enum class Type : char { + Null = 0, + Boolean = 1, + Integer = 2, + UInteger = 3, + Floating = 4, + String = 5, + Date = 6, + Time = 7, + DateTime = 8, + Blob = 9 + } type = Type::Null; ///< Type of the value - /** - * @brief Construct a new Any object with null value. - * - */ - Any(); - /** - * @brief Construct a new Any object with boolean value. - * - * @param v The boolean value - */ - Any(bool v); - /** - * @brief Construct a new Any object with int64 value. - * - * @param v The integer value - */ - Any(int64_t v); - /** - * @brief Construct a new Any object with uint64 value. - * - * @param v The unsigned integer value - */ - Any(uint64_t v); - /** - * @brief Construct a new Any object with double value. - * - * @param v The floating value - */ - Any(double v); - /** - * @brief Construct a new Any object with string value. - * - * @param v The string value - */ - Any(const std::string &v); - /** - * @brief Construct a new Any object with const char* value. - * - * @param v The const char* value - */ - Any(const char *v); - /** - * @brief Construct a new Any object with char* value. - * - * @param v The char* value - * @param len The length of the char* value - */ - Any(char *v, size_t len); - /** - * @brief Construct a new Any object with date value. - * - * @param v The Date object - */ - Any(const Date &v); - /** - * @brief Construct a new Any object with time value. - * - * @param v The Time object - */ - Any(const Time &v); - /** - * @brief Construct a new Any object with date time value. - * - * @param v The DateTime object - */ - Any(const DateTime &v); - /** - * @brief Construct a new Any object with int8(char) value. - * - * @param v The char value - */ - Any(char v); - /** - * @brief Construct a new Any object with uint8(unsigned char) value. - * - * @param v The unsigned char value - */ - Any(unsigned char v); - /** - * @brief Construct a new Any object with int16(short) value. - * - * @param v The short value - */ - Any(short v); - /** - * @brief Construct a new Any object with uint16(unsigned short) value. - * - * @param v The unsigned short value - */ - Any(unsigned short v); - /** - * @brief Construct a new Any object with int32(int) value. - * - * @param v The int value - */ - Any(int v); - /** - * @brief Construct a new Any object with uint32(unsigned int) value. - * - * @param v The unsigned int value - */ - Any(unsigned int v); - /** - * @brief Construct a new Any object with long value. - * - * @param v The long value - */ - Any(long v); - /** - * @brief Construct a new Any object with unsigned long value. - * - * @param v The unsigned long value - */ - Any(unsigned long v); - /** - * @brief Construct a new Any object with float value. - * - * @param v The float value - */ - Any(float v); - /** - * @brief Construct a new Any object with byte array value. - * - * @param v The byte array value - */ - Any(const ByteArray &v); - /// Copy constructor - Any(const Any &v); - /// Copy assignment operator - Any &operator=(const Any &v); + /** + * @brief Construct a new Any object with null value. + * + */ + Any(); + /** + * @brief Construct a new Any object with boolean value. + * + * @param v The boolean value + */ + Any(bool v); + /** + * @brief Construct a new Any object with int64 value. + * + * @param v The integer value + */ + Any(int64_t v); + /** + * @brief Construct a new Any object with uint64 value. + * + * @param v The unsigned integer value + */ + Any(uint64_t v); + /** + * @brief Construct a new Any object with double value. + * + * @param v The floating value + */ + Any(double v); + /** + * @brief Construct a new Any object with string value. + * + * @param v The string value + */ + Any(const std::string& v); + /** + * @brief Construct a new Any object with const char* value. + * + * @param v The const char* value + */ + Any(const char* v); + /** + * @brief Construct a new Any object with char* value. + * + * @param v The char* value + * @param len The length of the char* value + */ + Any(char* v, size_t len); + /** + * @brief Construct a new Any object with date value. + * + * @param v The Date object + */ + Any(const Date& v); + /** + * @brief Construct a new Any object with time value. + * + * @param v The Time object + */ + Any(const Time& v); + /** + * @brief Construct a new Any object with date time value. + * + * @param v The DateTime object + */ + Any(const DateTime& v); + /** + * @brief Construct a new Any object with int8(char) value. + * + * @param v The char value + */ + Any(char v); + /** + * @brief Construct a new Any object with uint8(unsigned char) value. + * + * @param v The unsigned char value + */ + Any(unsigned char v); + /** + * @brief Construct a new Any object with int16(short) value. + * + * @param v The short value + */ + Any(short v); + /** + * @brief Construct a new Any object with uint16(unsigned short) value. + * + * @param v The unsigned short value + */ + Any(unsigned short v); + /** + * @brief Construct a new Any object with int32(int) value. + * + * @param v The int value + */ + Any(int v); + /** + * @brief Construct a new Any object with uint32(unsigned int) value. + * + * @param v The unsigned int value + */ + Any(unsigned int v); + /** + * @brief Construct a new Any object with long value. + * + * @param v The long value + */ + Any(long v); + /** + * @brief Construct a new Any object with unsigned long value. + * + * @param v The unsigned long value + */ + Any(unsigned long v); + /** + * @brief Construct a new Any object with float value. + * + * @param v The float value + */ + Any(float v); + /** + * @brief Construct a new Any object with byte array value. + * + * @param v The byte array value + */ + Any(const ByteArray& v); + /// Copy constructor + Any(const Any& v); + /// Copy assignment operator + Any& operator=(const Any& v); - /// Destructor - ~Any(); + /// Destructor + ~Any(); - /** - * @brief Get if the value is null. - * - */ - bool is_null() const; - /** - * @brief Get if the value is boolean. - * - */ - bool is_boolean() const; - /** - * @brief Get if the value is (unsigned) integer. - * - */ - bool is_integer() const; - /** - * @brief Get if the value is unsigned integer. - * - */ - bool is_uinteger() const; - /** - * @brief Get if the value is floating. - * - */ - bool is_floating() const; - /** - * @brief Get if the value is string. - * - */ - bool is_string() const; - /** - * @brief Get if the value is date. - * - */ - bool is_date() const; - /** - * @brief Get if the value is time. - * - */ - bool is_time() const; - /** - * @brief Get if the value is date time. - * - */ - bool is_datetime() const; - /** - * @brief Get if the value is blob. - * - */ - bool is_blob() const; - /** - * @brief Get if the value is floating or (unsigned) integer. - * - */ - bool is_number() const; + /** + * @brief Get if the value is null. + * + */ + bool is_null() const; + /** + * @brief Get if the value is boolean. + * + */ + bool is_boolean() const; + /** + * @brief Get if the value is (unsigned) integer. + * + */ + bool is_integer() const; + /** + * @brief Get if the value is unsigned integer. + * + */ + bool is_uinteger() const; + /** + * @brief Get if the value is floating. + * + */ + bool is_floating() const; + /** + * @brief Get if the value is string. + * + */ + bool is_string() const; + /** + * @brief Get if the value is date. + * + */ + bool is_date() const; + /** + * @brief Get if the value is time. + * + */ + bool is_time() const; + /** + * @brief Get if the value is date time. + * + */ + bool is_datetime() const; + /** + * @brief Get if the value is blob. + * + */ + bool is_blob() const; + /** + * @brief Get if the value is floating or (unsigned) integer. + * + */ + bool is_number() const; - /** - * @brief Get the number value as T - * - * @tparam T The C++ basic number type to convert to, such as int, - * long, double, etc. - * @return T The value - * @throws std::bad_cast If the value cannot be converted to T or the value is - * not a number - * @note You can use Any::is_number() to check if the value is a number - * before calling this function. - * @see is_number() - */ - template inline T get_number() const { - switch (type) { + /** + * @brief Get the number value as T + * + * @tparam T The C++ basic number type to convert to, such as int, + * long, double, etc. + * @return T The value + * @throws std::bad_cast If the value cannot be converted to T or the value is + * not a number + * @note You can use Any::is_number() to check if the value is a number + * before calling this function. + * @see is_number() + */ + template + inline T get_number() const { + switch (type) { #if !defined(DBANY_NO_NULL_CONVERSION) - case Type::Null: - return 0; + case Type::Null: + return 0; #endif - case Type::Boolean: - return static_cast(value.boolean); - case Type::Integer: - case Type::UInteger: - return static_cast(value.integer); - case Type::Floating: - return static_cast(value.floating); - case Type::String: - case Type::Date: - case Type::Time: - case Type::DateTime: - case Type::Blob: - default: - throw std::bad_cast(); + case Type::Boolean: + return static_cast(value.boolean); + case Type::Integer: + case Type::UInteger: + return static_cast(value.integer); + case Type::Floating: + return static_cast(value.floating); + case Type::String: + case Type::Date: + case Type::Time: + case Type::DateTime: + case Type::Blob: + default: + throw std::bad_cast(); + } } - } - /** - * @brief Get the value as T. - * - * @tparam T The type of the value - * @return T The value - * @throws std::bad_cast If the value cannot be converted to T - * @par Custom Type Conversion - * Define a custom type conversion function for the type T - * @code - * template <> - * MyClass any_to(const Any& v) { - * MyClass result; - * switch (v.type) { - * case Any::Type::String: - * result.a = *v.value.string; - * default: - * throw std::bad_cast(); - * } - * return result; - * } - * @endcode - * @note You can use `#define DBANY_NO_NULL_CONVERSION` to disable null - * conversion. (throw an exception when trying converting from a null type - * value) - * @see any_to - */ - template inline T get() const { return any_to(*this); } - /** - * @brief Get the value as string - * - * @tparam T = bool - * @return bool The value - * @throws std::bad_cast If the value cannot be converted to string - */ - template <> inline bool get() const { - switch (type) { + /** + * @brief Get the value as T. + * + * @tparam T The type of the value + * @return T The value + * @throws std::bad_cast If the value cannot be converted to T + * @par Custom Type Conversion + * Define a custom type conversion function for the type T + * @code + * template <> + * MyClass any_to(const Any& v) { + * MyClass result; + * switch (v.type) { + * case Any::Type::String: + * result.a = *v.value.string; + * default: + * throw std::bad_cast(); + * } + * return result; + * } + * @endcode + * @note You can use `#define DBANY_NO_NULL_CONVERSION` to disable null + * conversion. (throw an exception when trying converting from a null type + * value) + * @see any_to + */ + template + inline T get() const { + return any_to(*this); + } + /** + * @brief Get the value as string + * + * @tparam T = bool + * @return bool The value + * @throws std::bad_cast If the value cannot be converted to string + */ + template <> + inline bool get() const { + switch (type) { #if !defined(DBANY_NO_NULL_CONVERSION) - case Type::Null: - return false; + case Type::Null: + return false; #endif - case Type::Boolean: - return value.boolean; - case Type::Integer: - case Type::UInteger: - case Type::Floating: - return (bool)value.integer; - case Type::String: - case Type::Date: - case Type::Time: - case Type::DateTime: - case Type::Blob: - default: - throw std::bad_cast(); + case Type::Boolean: + return value.boolean; + case Type::Integer: + case Type::UInteger: + case Type::Floating: + return (bool)value.integer; + case Type::String: + case Type::Date: + case Type::Time: + case Type::DateTime: + case Type::Blob: + default: + throw std::bad_cast(); + } + } + /** + * @brief Get the value as char + * + * @tparam T = char + * @return char The value + * @throws std::bad_cast If the value cannot be converted to char + */ + template <> + inline char get() const { + return get_number(); + } + /** + * @brief Get the value as unsigned char + * + * @tparam T = unsigned char + * @return unsigned char The value + * @throws std::bad_cast If the value cannot be converted to unsigned char + */ + template <> + inline unsigned char get() const { + return get_number(); + } + /** + * @brief Get the value as short + * + * @tparam T = short + * @return short The value + * @throws std::bad_cast If the value cannot be converted to short + */ + template <> + inline short get() const { + return get_number(); + } + /** + * @brief Get the value as unsigned short + * + * @tparam T = unsigned short + * @return unsigned short The value + * @throws std::bad_cast If the value cannot be converted to unsigned short + */ + template <> + inline unsigned short get() const { + return get_number(); + } + /** + * @brief Get the value as int + * + * @tparam T = int + * @return int The value + * @throws std::bad_cast If the value cannot be converted to int + */ + template <> + inline int get() const { + return get_number(); + } + /** + * @brief Get the value as unsigned int + * + * @tparam T = unsigned int + * @return unsigned int The value + * @throws std::bad_cast If the value cannot be converted to unsigned int + */ + template <> + inline unsigned int get() const { + return get_number(); + } + /** + * @brief Get the value as long + * + * @tparam T = long + * @return long The value + * @throws std::bad_cast If the value cannot be converted to long + */ + template <> + inline long get() const { + return get_number(); + } + /** + * @brief Get the value as unsigned long + * + * @tparam T = unsigned long + * @return unsigned long The value + * @throws std::bad_cast If the value cannot be converted to unsigned long + */ + template <> + inline unsigned long get() const { + return get_number(); } - } - /** - * @brief Get the value as char - * - * @tparam T = char - * @return char The value - * @throws std::bad_cast If the value cannot be converted to char - */ - template <> inline char get() const { return get_number(); } - /** - * @brief Get the value as unsigned char - * - * @tparam T = unsigned char - * @return unsigned char The value - * @throws std::bad_cast If the value cannot be converted to unsigned char - */ - template <> inline unsigned char get() const { - return get_number(); - } - /** - * @brief Get the value as short - * - * @tparam T = short - * @return short The value - * @throws std::bad_cast If the value cannot be converted to short - */ - template <> inline short get() const { return get_number(); } - /** - * @brief Get the value as unsigned short - * - * @tparam T = unsigned short - * @return unsigned short The value - * @throws std::bad_cast If the value cannot be converted to unsigned short - */ - template <> inline unsigned short get() const { - return get_number(); - } - /** - * @brief Get the value as int - * - * @tparam T = int - * @return int The value - * @throws std::bad_cast If the value cannot be converted to int - */ - template <> inline int get() const { return get_number(); } - /** - * @brief Get the value as unsigned int - * - * @tparam T = unsigned int - * @return unsigned int The value - * @throws std::bad_cast If the value cannot be converted to unsigned int - */ - template <> inline unsigned int get() const { - return get_number(); - } - /** - * @brief Get the value as long - * - * @tparam T = long - * @return long The value - * @throws std::bad_cast If the value cannot be converted to long - */ - template <> inline long get() const { return get_number(); } - /** - * @brief Get the value as unsigned long - * - * @tparam T = unsigned long - * @return unsigned long The value - * @throws std::bad_cast If the value cannot be converted to unsigned long - */ - template <> inline unsigned long get() const { - return get_number(); - } - /** - * @brief Get the value as long long - * - * @tparam T = long long - * @return long long The value - * @throws std::bad_cast If the value cannot be converted to long long - */ - template <> inline long long get() const { return get_number(); } - /** - * @brief Get the value as unsigned long long - * - * @tparam T = unsigned long long - * @return unsigned long long The value - * @throws std::bad_cast If the value cannot be converted to unsigned - * long long - */ - template <> inline unsigned long long get() const { - return get_number(); - } - /** - * @brief Get the value as double. - * - * @tparam T = double - * @return double The value - * @throws std::bad_cast If the value cannot be converted to double - */ - template <> inline double get() const { return get_number(); } - /** - * @brief Get the value as float. - * - * @tparam T = float - * @return float The value - * @throws std::bad_cast If the value cannot be converted to float - */ - template <> inline float get() const { return get_number(); } - /** - * @brief Get the value as string. - * - * @tparam T = std::string - * @return std::string The value - * @throws std::bad_cast If the value cannot be converted to string - */ - template <> std::string get() const { - switch (type) { + /** + * @brief Get the value as long long + * + * @tparam T = long long + * @return long long The value + * @throws std::bad_cast If the value cannot be converted to long long + */ + template <> + inline long long get() const { + return get_number(); + } + /** + * @brief Get the value as unsigned long long + * + * @tparam T = unsigned long long + * @return unsigned long long The value + * @throws std::bad_cast If the value cannot be converted to unsigned + * long long + */ + template <> + inline unsigned long long get() const { + return get_number(); + } + /** + * @brief Get the value as double. + * + * @tparam T = double + * @return double The value + * @throws std::bad_cast If the value cannot be converted to double + */ + template <> + inline double get() const { + return get_number(); + } + /** + * @brief Get the value as float. + * + * @tparam T = float + * @return float The value + * @throws std::bad_cast If the value cannot be converted to float + */ + template <> + inline float get() const { + return get_number(); + } + /** + * @brief Get the value as string. + * + * @tparam T = std::string + * @return std::string The value + * @throws std::bad_cast If the value cannot be converted to string + */ + template <> + std::string get() const { + switch (type) { #if !defined(DBANY_NO_NULL_CONVERSION) - case Type::Null: - return ""; + case Type::Null: + return ""; #endif - case Type::Boolean: - return value.boolean ? "true" : "false"; - case Type::Integer: - return std::to_string(value.integer); - case Type::UInteger: - return std::to_string(value.uinteger); - case Type::Floating: - return std::to_string(value.floating); - case Type::String: - return *value.string; - case Type::Date: - return std::to_string(value.date->year) + "-" + - std::to_string(value.date->month) + "-" + - std::to_string(value.date->day); - break; - case Type::Time: - return std::to_string(value.time->hour) + ":" + - std::to_string(value.time->minute) + ":" + - std::to_string(value.time->second); - case Type::DateTime: - return std::to_string(value.datetime->date.year) + "-" + - std::to_string(value.datetime->date.month) + "-" + - std::to_string(value.datetime->date.day) + " " + - std::to_string(value.datetime->time.hour) + ":" + - std::to_string(value.datetime->time.minute) + ":" + - std::to_string(value.datetime->time.second); - case Type::Blob: - return std::string(value.blob->begin(), value.blob->end()); - default: - throw std::bad_cast(); + case Type::Boolean: + return value.boolean ? "true" : "false"; + case Type::Integer: + return std::to_string(value.integer); + case Type::UInteger: + return std::to_string(value.uinteger); + case Type::Floating: + return std::to_string(value.floating); + case Type::String: + return *value.string; + case Type::Date: + return std::to_string(value.date->year) + "-" + std::to_string(value.date->month) + "-" + + std::to_string(value.date->day); + break; + case Type::Time: + return std::to_string(value.time->hour) + ":" + std::to_string(value.time->minute) + ":" + + std::to_string(value.time->second); + case Type::DateTime: + return std::to_string(value.datetime->date.year) + "-" + std::to_string(value.datetime->date.month) + "-" + + std::to_string(value.datetime->date.day) + " " + std::to_string(value.datetime->time.hour) + ":" + + std::to_string(value.datetime->time.minute) + ":" + std::to_string(value.datetime->time.second); + case Type::Blob: + return std::string(value.blob->begin(), value.blob->end()); + default: + throw std::bad_cast(); + } } - } - /** - * @brief Get the value as Date - * - * @tparam T = DB::Date - * @return DB::Date The value - * @throws std::bad_cast If the value cannot be converted to DB::Date - */ - template <> Date get() const { - switch (type) { - case Type::Date: - return *value.date; - case Type::DateTime: - return value.datetime->date; - case Type::String: - case Type::Integer: - case Type::UInteger: - case Type::Floating: - case Type::Time: - case Type::Blob: - default: - throw std::bad_cast(); + /** + * @brief Get the value as Date + * + * @tparam T = DB::Date + * @return DB::Date The value + * @throws std::bad_cast If the value cannot be converted to DB::Date + */ + template <> + Date get() const { + switch (type) { + case Type::Date: + return *value.date; + case Type::DateTime: + return value.datetime->date; + case Type::String: + case Type::Integer: + case Type::UInteger: + case Type::Floating: + case Type::Time: + case Type::Blob: + default: + throw std::bad_cast(); + } } - } - /** - * @brief Get the value as Time - * - * @tparam T = DB::Time - * @return DB::Time The value - * @throws std::bad_cast If the value cannot be converted to DB::Time - */ - template <> Time get() const { - switch (type) { - case Type::Time: - return *value.time; - case Type::DateTime: - return value.datetime->time; - case Type::String: - case Type::Integer: - case Type::UInteger: - case Type::Floating: - case Type::Date: - case Type::Blob: - default: - throw std::bad_cast(); + /** + * @brief Get the value as Time + * + * @tparam T = DB::Time + * @return DB::Time The value + * @throws std::bad_cast If the value cannot be converted to DB::Time + */ + template <> + Time get() const { + switch (type) { + case Type::Time: + return *value.time; + case Type::DateTime: + return value.datetime->time; + case Type::String: + case Type::Integer: + case Type::UInteger: + case Type::Floating: + case Type::Date: + case Type::Blob: + default: + throw std::bad_cast(); + } } - } - /** - * @brief Get the value as DateTime - * - * @tparam T = DB::DateTime - * @return DB::DateTime The value - * @throws std::bad_cast If the value cannot be converted to DB::DateTime - */ - template <> DateTime get() const { - switch (type) { - case Type::DateTime: - return *value.datetime; - case Type::String: - case Type::Integer: - case Type::UInteger: - case Type::Floating: - case Type::Date: - case Type::Time: - case Type::Blob: - default: - throw std::bad_cast(); + /** + * @brief Get the value as DateTime + * + * @tparam T = DB::DateTime + * @return DB::DateTime The value + * @throws std::bad_cast If the value cannot be converted to DB::DateTime + */ + template <> + DateTime get() const { + switch (type) { + case Type::DateTime: + return *value.datetime; + case Type::String: + case Type::Integer: + case Type::UInteger: + case Type::Floating: + case Type::Date: + case Type::Time: + case Type::Blob: + default: + throw std::bad_cast(); + } } - } - /** - * @brief Get the value as ByteArray - * - * @tparam T = DB::ByteArray - * @return DB::ByteArray The value - * @throws std::bad_cast If the value cannot be converted to DB::ByteArray - */ - template <> ByteArray get() const { - switch (type) { - case Type::Blob: - return *value.blob; - case Type::String: - return ByteArray((unsigned char *)value.string->data(), - (unsigned char *)value.string->data() + - value.string->size()); - case Type::Integer: - case Type::UInteger: - case Type::Floating: - case Type::Date: - case Type::Time: - case Type::DateTime: - default: - throw std::bad_cast(); + /** + * @brief Get the value as ByteArray + * + * @tparam T = DB::ByteArray + * @return DB::ByteArray The value + * @throws std::bad_cast If the value cannot be converted to DB::ByteArray + */ + template <> + ByteArray get() const { + switch (type) { + case Type::Blob: + return *value.blob; + case Type::String: + return ByteArray( + (unsigned char*)value.string->data(), + (unsigned char*)value.string->data() + value.string->size() + ); + case Type::Integer: + case Type::UInteger: + case Type::Floating: + case Type::Date: + case Type::Time: + case Type::DateTime: + default: + throw std::bad_cast(); + } } - } - /** - * @brief Convert Any::Type to string. - * - * @param type The Any::Type value - * @return std::string The string value - */ - static std::string type2str(Any::Type type); + /** + * @brief Convert Any::Type to string. + * + * @param type The Any::Type value + * @return std::string The string value + */ + static std::string type2str(Any::Type type); - /** - * @brief Convert string to Any. - * - * @param str The string - * @return Any The converted value - */ - static Any str2any(const std::string &str); + /** + * @brief Convert string to Any. + * + * @param str The string + * @return Any The converted value + */ + static Any str2any(const std::string& str); }; } // namespace DB template -inline std::vector to_any_container(const std::vector &v) { - std::vector result; - for (auto &i : v) { - result.push_back(DB::Any(i)); - } - return result; +inline std::vector to_any_container(const std::vector& v) { + std::vector result; + for (auto& i : v) { + result.push_back(DB::Any(i)); + } + return result; } template -inline std::set to_any_container(const std::set &v) { - std::set result; - for (auto &i : v) { - result.insert(DB::Any(i)); - } - return result; +inline std::set to_any_container(const std::set& v) { + std::set result; + for (auto& i : v) { + result.insert(DB::Any(i)); + } + return result; } template -inline std::list to_any_container(const std::list &v) { - std::list result; - for (auto &i : v) { - result.push_back(DB::Any(i)); - } - return result; +inline std::list to_any_container(const std::list& v) { + std::list result; + for (auto& i : v) { + result.push_back(DB::Any(i)); + } + return result; } template -inline std::unordered_set -to_any_container(const std::unordered_set &v) { - std::unordered_set result; - for (auto &i : v) { - result.insert(DB::Any(i)); - } - return result; +inline std::unordered_set to_any_container(const std::unordered_set& v) { + std::unordered_set result; + for (auto& i : v) { + result.insert(DB::Any(i)); + } + return result; } template -inline std::map to_any_container(const std::map &v) { - std::map result; - for (auto &i : v) { - result.insert(std::make_pair(i.first, DB::Any(i.second))); - } - return result; +inline std::map to_any_container(const std::map& v) { + std::map result; + for (auto& i : v) { + result.insert(std::make_pair(i.first, DB::Any(i.second))); + } + return result; } template -inline std::unordered_map -to_any_unordered_map(const std::unordered_map &v) { - std::unordered_map result; - for (auto &i : v) { - result.insert(std::make_pair(i.first, DB::Any(i.second))); - } - return result; +inline std::unordered_map to_any_unordered_map(const std::unordered_map& v) { + std::unordered_map result; + for (auto& i : v) { + result.insert(std::make_pair(i.first, DB::Any(i.second))); + } + return result; } diff --git a/src/legacyapi/db/ConnParams.cpp b/src/legacyapi/db/ConnParams.cpp index 1b7a8664..9dc654a3 100644 --- a/src/legacyapi/db/ConnParams.cpp +++ b/src/legacyapi/db/ConnParams.cpp @@ -7,205 +7,174 @@ namespace DB { #pragma region URL_Parser struct URL { - std::string scheme; - std::string user; - std::string password; - std::string host; - uint16_t port = 0; - std::string path; - std::map query; - std::string fragment; + std::string scheme; + std::string user; + std::string password; + std::string host; + uint16_t port = 0; + std::string path; + std::map query; + std::string fragment; }; -URL ParseURL(const std::string &url) { - URL result; - std::string cur = url; - - size_t pos = cur.find("://"); - if (pos != std::string::npos) { - result.scheme = cur.substr(0, pos); - cur = cur.substr(pos + 3); - } - pos = cur.find('@'); - auto pos0 = pos; - if (pos != std::string::npos) { - std::string userInfo = cur.substr(0, pos); - pos = userInfo.find(':'); - if (pos != std::string::npos) { - result.user = userInfo.substr(0, pos); - result.password = userInfo.substr(pos + 1); - } else - result.user = userInfo; - cur = cur.substr(pos0 + 1); - } - pos = cur.find_first_of("/?#"); - auto pos1 = pos; - std::string address = cur.substr(0, pos); - pos = address.find(':'); - if (pos != std::string::npos) { - result.host = address.substr(0, pos); - result.port = static_cast(std::stoi(address.substr(pos + 1))); - } else - result.host = address; - if (pos1 == std::string::npos) - return result; - else - cur = cur.substr(pos1); +URL ParseURL(const std::string& url) { + URL result; + std::string cur = url; - pos = cur.find_first_of("?#"); - result.path = cur.substr(0, pos); - if (pos == std::string::npos) - return result; - else - cur = cur.substr(pos); - if (cur[0] == '?') { - cur = cur.substr(1); - pos = cur.find('#'); - std::string query = cur.substr(0, pos); + size_t pos = cur.find("://"); + if (pos != std::string::npos) { + result.scheme = cur.substr(0, pos); + cur = cur.substr(pos + 3); + } + pos = cur.find('@'); + auto pos0 = pos; if (pos != std::string::npos) { - result.fragment = cur.substr(pos + 1); + std::string userInfo = cur.substr(0, pos); + pos = userInfo.find(':'); + if (pos != std::string::npos) { + result.user = userInfo.substr(0, pos); + result.password = userInfo.substr(pos + 1); + } else result.user = userInfo; + cur = cur.substr(pos0 + 1); } - std::vector pairs = - ll::string_utils::splitByPattern(query, "&"); - for (auto &pair : pairs) { - std::string k, v; - pos = pair.find('='); - if (pos == std::string::npos) - k = pair; - else { - k = pair.substr(0, pos); - v = pair.substr(pos + 1); - } - result.query.emplace(k, v); + pos = cur.find_first_of("/?#"); + auto pos1 = pos; + std::string address = cur.substr(0, pos); + pos = address.find(':'); + if (pos != std::string::npos) { + result.host = address.substr(0, pos); + result.port = static_cast(std::stoi(address.substr(pos + 1))); + } else result.host = address; + if (pos1 == std::string::npos) return result; + else cur = cur.substr(pos1); + + pos = cur.find_first_of("?#"); + result.path = cur.substr(0, pos); + if (pos == std::string::npos) return result; + else cur = cur.substr(pos); + if (cur[0] == '?') { + cur = cur.substr(1); + pos = cur.find('#'); + std::string query = cur.substr(0, pos); + if (pos != std::string::npos) { + result.fragment = cur.substr(pos + 1); + } + std::vector pairs = ll::string_utils::splitByPattern(query, "&"); + for (auto& pair : pairs) { + std::string k, v; + pos = pair.find('='); + if (pos == std::string::npos) k = pair; + else { + k = pair.substr(0, pos); + v = pair.substr(pos + 1); + } + result.query.emplace(k, v); + } + } else if (cur[0] == '#') { + result.fragment = cur.substr(1); } - } else if (cur[0] == '#') { - result.fragment = cur.substr(1); - } - return result; + return result; } extern ll::Logger dbLogger; -void PrintURL(const URL &url) { - dbLogger.debug("Parsed URL"); - dbLogger.debug("scheme: {}", url.scheme); - dbLogger.debug("user: {}", url.user); - dbLogger.debug("password: {}", url.password); - dbLogger.debug("host: {}", url.host); - dbLogger.debug("port: {}", url.port); - dbLogger.debug("path: {}", url.path); - dbLogger.debug("query:"); - for (auto &pair : url.query) - dbLogger.debug("- {}: {}", pair.first, pair.second); - dbLogger.debug("fragment: {}", url.fragment); +void PrintURL(const URL& url) { + dbLogger.debug("Parsed URL"); + dbLogger.debug("scheme: {}", url.scheme); + dbLogger.debug("user: {}", url.user); + dbLogger.debug("password: {}", url.password); + dbLogger.debug("host: {}", url.host); + dbLogger.debug("port: {}", url.port); + dbLogger.debug("path: {}", url.path); + dbLogger.debug("query:"); + for (auto& pair : url.query) dbLogger.debug("- {}: {}", pair.first, pair.second); + dbLogger.debug("fragment: {}", url.fragment); } #pragma endregion -ConnParams::ConnParams(const std::initializer_list &list) - : std::unordered_map() { - bool key = true; - std::string keyName; - for (auto &item : list) { - if (key) { - if (item.is_string()) { - throw std::invalid_argument( - "ConnParams::ConnParams: Key must be string"); - } - keyName = item.get(); - key = false; - } else { - insert({keyName, item}); - key = true; +ConnParams::ConnParams(const std::initializer_list& list) : std::unordered_map() { + bool key = true; + std::string keyName; + for (auto& item : list) { + if (key) { + if (item.is_string()) { + throw std::invalid_argument("ConnParams::ConnParams: Key must be string"); + } + keyName = item.get(); + key = false; + } else { + insert({keyName, item}); + key = true; + } + } + auto host = getHost(); + if (host.find(':') != std::string::npos) { + host = host.substr(0, host.find_last_of(':')); + auto port = host.substr(host.find_last_of(':') + 1); + (*this)["host"] = host; + (*this)["port"] = std::stoi(port); } - } - auto host = getHost(); - if (host.find(':') != std::string::npos) { - host = host.substr(0, host.find_last_of(':')); - auto port = host.substr(host.find_last_of(':') + 1); - (*this)["host"] = host; - (*this)["port"] = std::stoi(port); - } } -ConnParams::ConnParams( - const std::initializer_list> &list) - : std::unordered_map() { - for (auto &item : list) { - insert(item); - } - auto host = getHost(); - if (host.find(':') != std::string::npos) { - host = host.substr(0, host.find_last_of(':')); - auto port = host.substr(host.find_last_of(':') + 1); - (*this)["host"] = host; - (*this)["port"] = std::stoi(port); - } +ConnParams::ConnParams(const std::initializer_list>& list) +: std::unordered_map() { + for (auto& item : list) { + insert(item); + } + auto host = getHost(); + if (host.find(':') != std::string::npos) { + host = host.substr(0, host.find_last_of(':')); + auto port = host.substr(host.find_last_of(':') + 1); + (*this)["host"] = host; + (*this)["port"] = std::stoi(port); + } } -ConnParams::ConnParams(const std::string &str) - : std::unordered_map() { - raw = str; - auto url = ParseURL(str); +ConnParams::ConnParams(const std::string& str) : std::unordered_map() { + raw = str; + auto url = ParseURL(str); #if defined(LLDB_DEBUG_MODE) - PrintURL(url); + PrintURL(url); #endif - if (!url.scheme.empty()) - insert({"scheme", url.scheme}); - if (!url.host.empty()) - insert({"host", url.host}); - if (url.port) - insert({"port", url.port}); - if (!url.user.empty()) - insert({"user", url.user}); - if (!url.password.empty()) - insert({"password", url.password}); - if (!url.path.empty()) { - std::string path = url.path; - if (path[0] == '/') - path = path.substr(1); - insert({"path", path}); - } - if (!url.fragment.empty()) - insert({"fragment", url.fragment}); - for (auto &pair : url.query) { - insert({pair.first, Any::str2any(pair.second)}); - } + if (!url.scheme.empty()) insert({"scheme", url.scheme}); + if (!url.host.empty()) insert({"host", url.host}); + if (url.port) insert({"port", url.port}); + if (!url.user.empty()) insert({"user", url.user}); + if (!url.password.empty()) insert({"password", url.password}); + if (!url.path.empty()) { + std::string path = url.path; + if (path[0] == '/') path = path.substr(1); + insert({"path", path}); + } + if (!url.fragment.empty()) insert({"fragment", url.fragment}); + for (auto& pair : url.query) { + insert({pair.first, Any::str2any(pair.second)}); + } } -ConnParams::ConnParams(const char *str) - : std::unordered_map() { - *this = ConnParams(std::string(str)); +ConnParams::ConnParams(const char* str) : std::unordered_map() { + *this = ConnParams(std::string(str)); } -std::string ConnParams::getScheme() { - return get({"scheme", "protocol", "type"}, true); -} +std::string ConnParams::getScheme() { return get({"scheme", "protocol", "type"}, true); } std::string ConnParams::getHost() { - return get( - {"host", "hostname", "server", "server_name", "ip", "address"}, true); + return get({"host", "hostname", "server", "server_name", "ip", "address"}, true); } uint16_t ConnParams::getPort() { - return get({"port", "port_number", "port_num", "port_id", "portid"}, - true, 0); + return get({"port", "port_number", "port_num", "port_id", "portid"}, true, 0); } std::string ConnParams::getUsername() { - return get({"user", "username", "user_name", "usr", "usrname"}, - true); + return get({"user", "username", "user_name", "usr", "usrname"}, true); } -std::string ConnParams::getPassword() { - return get({"password", "pass", "passwd", "pass_word"}, true); -} +std::string ConnParams::getPassword() { return get({"password", "pass", "passwd", "pass_word"}, true); } std::string ConnParams::getDatabase() { - return get({"database", "db", "db_name", "dbname", "path"}, - true); + return get({"database", "db", "db_name", "dbname", "path"}, true); } -std::string ConnParams::getPath() { - return get({"path", "file", "file_name", "filename"}, true); -} +std::string ConnParams::getPath() { return get({"path", "file", "file_name", "filename"}, true); } std::string ConnParams::getRaw() { return raw; } diff --git a/src/legacyapi/db/ConnParams.h b/src/legacyapi/db/ConnParams.h index ccbcd90f..1400f55e 100644 --- a/src/legacyapi/db/ConnParams.h +++ b/src/legacyapi/db/ConnParams.h @@ -7,132 +7,127 @@ namespace DB { class ConnParams : public std::unordered_map { - std::string raw; + std::string raw; public: - ConnParams() = default; - /** - * @brief Construct a new ConnParams object - * - * @param list An initializer list like `{"host", "localhost", "port", 3306}` - * @throw std::invalid_argument If the type of key is not supported - */ - ConnParams(const std::initializer_list &list); - /** - * @brief Construct a new ConnParams object - * - * @param list An initializer list like `{{"key1", "value1"}, {"key2", - * "value2"}}` - */ + ConnParams() = default; + /** + * @brief Construct a new ConnParams object + * + * @param list An initializer list like `{"host", "localhost", "port", 3306}` + * @throw std::invalid_argument If the type of key is not supported + */ + ConnParams(const std::initializer_list& list); + /** + * @brief Construct a new ConnParams object + * + * @param list An initializer list like `{{"key1", "value1"}, {"key2", + * "value2"}}` + */ - ConnParams(const std::initializer_list> &list); - /** - * @brief Construct a new ConnParams object - * - * @param str Connection string like - * `mysql://localhost:3306?key1=value1&key2=value2` - */ - ConnParams(const std::string &str); - /** - * @brief Construct a new ConnParams object - * - * @param str Connection string like - * `mysql://localhost:3306?key1=value1&key2=value2` - */ - ConnParams(const char *str); + ConnParams(const std::initializer_list>& list); + /** + * @brief Construct a new ConnParams object + * + * @param str Connection string like + * `mysql://localhost:3306?key1=value1&key2=value2` + */ + ConnParams(const std::string& str); + /** + * @brief Construct a new ConnParams object + * + * @param str Connection string like + * `mysql://localhost:3306?key1=value1&key2=value2` + */ + ConnParams(const char* str); - /** - * @brief Get the scheme. - * - * @return std::string The scheme - */ - std::string getScheme(); - /** - * @brief Get the host. - * - * @return std::string The host name - */ - std::string getHost(); - /** - * @brief Get the port. - * - * @return uint16_t The port number - */ - uint16_t getPort(); - /** - * @brief Get the username. - * - * @return std::string The username - */ - std::string getUsername(); - /** - * @brief Get the password. - * - * @return std::string The password - */ - std::string getPassword(); - /** - * @brief Get the database. - * - * @return std::string The database name - */ - std::string getDatabase(); - /** - * @brief Get the path. - * - * @return std::string The path - */ - std::string getPath(); - /** - * @brief Get the raw connection string. - * - * @return std::string The connection string - * @note If this object is constructed by `ConnParams(const std::string& - * str)` or `ConnParams(const char* str)`, the return value is the same as the - * parameter `str`. Otherwise, the return value will be empty. - */ - std::string getRaw(); + /** + * @brief Get the scheme. + * + * @return std::string The scheme + */ + std::string getScheme(); + /** + * @brief Get the host. + * + * @return std::string The host name + */ + std::string getHost(); + /** + * @brief Get the port. + * + * @return uint16_t The port number + */ + uint16_t getPort(); + /** + * @brief Get the username. + * + * @return std::string The username + */ + std::string getUsername(); + /** + * @brief Get the password. + * + * @return std::string The password + */ + std::string getPassword(); + /** + * @brief Get the database. + * + * @return std::string The database name + */ + std::string getDatabase(); + /** + * @brief Get the path. + * + * @return std::string The path + */ + std::string getPath(); + /** + * @brief Get the raw connection string. + * + * @return std::string The connection string + * @note If this object is constructed by `ConnParams(const std::string& + * str)` or `ConnParams(const char* str)`, the return value is the same as the + * parameter `str`. Otherwise, the return value will be empty. + */ + std::string getRaw(); - /** - * @brief Get the value of one of the keys. - * - * @tparam T The type of the value - * @param keys The keys (If ignoreCase is true, keys must be - * lowercase) - * @param ignoreCase Whether to ignore the case of the key - * @param defaultValue The default value - * @return T The value - * @note If there are multiple keys matched, - * the first one(keys[0]) will be returned. - */ - template - inline T get(const std::vector &keys, bool ignoreCase = true, - T defaultValue = T()) { - Any value; - int w = INT_MAX; - for (auto &[k, v] : *this) { - std::string lowerKey = k; - if (ignoreCase) { - std::transform(lowerKey.begin(), lowerKey.end(), lowerKey.begin(), - ::tolower); - } - int i = 0; - for (auto &key : keys) { - if (lowerKey == key && i < w) { - value = v; - w = i; - if (w == 0) - break; + /** + * @brief Get the value of one of the keys. + * + * @tparam T The type of the value + * @param keys The keys (If ignoreCase is true, keys must be + * lowercase) + * @param ignoreCase Whether to ignore the case of the key + * @param defaultValue The default value + * @return T The value + * @note If there are multiple keys matched, + * the first one(keys[0]) will be returned. + */ + template + inline T get(const std::vector& keys, bool ignoreCase = true, T defaultValue = T()) { + Any value; + int w = INT_MAX; + for (auto& [k, v] : *this) { + std::string lowerKey = k; + if (ignoreCase) { + std::transform(lowerKey.begin(), lowerKey.end(), lowerKey.begin(), ::tolower); + } + int i = 0; + for (auto& key : keys) { + if (lowerKey == key && i < w) { + value = v; + w = i; + if (w == 0) break; + } + i++; + } + if (w == 0) break; } - i++; - } - if (w == 0) - break; + if (value.is_null()) return defaultValue; + return value.get(); } - if (value.is_null()) - return defaultValue; - return value.get(); - } }; } // namespace DB \ No newline at end of file diff --git a/src/legacyapi/db/Pointer.h b/src/legacyapi/db/Pointer.h index 992d490e..b908be80 100644 --- a/src/legacyapi/db/Pointer.h +++ b/src/legacyapi/db/Pointer.h @@ -6,44 +6,45 @@ namespace DB { class Stmt; -template class SharedPointer : public std::shared_ptr { +template +class SharedPointer : public std::shared_ptr { public: - SharedPointer(T *ptr = nullptr) : std::shared_ptr(ptr) {} - SharedPointer(const std::shared_ptr &ptr) : std::shared_ptr(ptr) {} - SharedPointer(std::shared_ptr &&ptr) : std::shared_ptr(ptr) {} - SharedPointer(const SharedPointer &other) : std::shared_ptr(other) {} - SharedPointer(SharedPointer &&other) : std::shared_ptr(other) {} - ~SharedPointer() {} - inline SharedPointer &operator=(const SharedPointer &other) { - std::shared_ptr::operator=(other); - return *this; - } - inline SharedPointer &operator=(SharedPointer &&other) noexcept { - std::shared_ptr::operator=(other); - return *this; - } - - template inline SharedPointer operator<<(const U &v) { - auto ptr = std::shared_ptr::get(); - if (!ptr) - throw std::runtime_error("The pointer is nullptr"); - return (*ptr) << v; - } - - template inline SharedPointer operator>>(U &v) { - auto ptr = std::shared_ptr::get(); - if (!ptr) - throw std::runtime_error("The pointer is nullptr"); - return (*ptr) >> v; - } - - template inline SharedPointer operator,(U v) { - auto ptr = std::shared_ptr::get(); - if (!ptr) - throw std::runtime_error("The pointer is nullptr"); - return ptr->operator,(v); - } + SharedPointer(T* ptr = nullptr) : std::shared_ptr(ptr) {} + SharedPointer(const std::shared_ptr& ptr) : std::shared_ptr(ptr) {} + SharedPointer(std::shared_ptr&& ptr) : std::shared_ptr(ptr) {} + SharedPointer(const SharedPointer& other) : std::shared_ptr(other) {} + SharedPointer(SharedPointer&& other) : std::shared_ptr(other) {} + ~SharedPointer() {} + inline SharedPointer& operator=(const SharedPointer& other) { + std::shared_ptr::operator=(other); + return *this; + } + inline SharedPointer& operator=(SharedPointer&& other) noexcept { + std::shared_ptr::operator=(other); + return *this; + } + + template + inline SharedPointer operator<<(const U& v) { + auto ptr = std::shared_ptr::get(); + if (!ptr) throw std::runtime_error("The pointer is nullptr"); + return (*ptr) << v; + } + + template + inline SharedPointer operator>>(U& v) { + auto ptr = std::shared_ptr::get(); + if (!ptr) throw std::runtime_error("The pointer is nullptr"); + return (*ptr) >> v; + } + + template + inline SharedPointer operator,(U v) { + auto ptr = std::shared_ptr::get(); + if (!ptr) throw std::runtime_error("The pointer is nullptr"); + return ptr->operator,(v); + } }; } // namespace DB \ No newline at end of file diff --git a/src/legacyapi/db/Row.cpp b/src/legacyapi/db/Row.cpp index 8a8cd9ee..cd7f2e4b 100644 --- a/src/legacyapi/db/Row.cpp +++ b/src/legacyapi/db/Row.cpp @@ -4,44 +4,40 @@ namespace DB { -RowHeader::RowHeader(const std::initializer_list &list) - : std::vector(list) {} +RowHeader::RowHeader(const std::initializer_list& list) : std::vector(list) {} RowHeader::~RowHeader() {} -size_t RowHeader::add(const std::string &name) { - push_back(name); - hashes.push_back(ll::hash_utils::do_hash2(name)); - return size() - 1; +size_t RowHeader::add(const std::string& name) { + push_back(name); + hashes.push_back(ll::hash_utils::do_hash2(name)); + return size() - 1; } -bool RowHeader::contains(const std::string &name) { - return std::find(hashes.begin(), hashes.end(), - ll::hash_utils::do_hash2(name)) != hashes.end(); +bool RowHeader::contains(const std::string& name) { + return std::find(hashes.begin(), hashes.end(), ll::hash_utils::do_hash2(name)) != hashes.end(); } -void RowHeader::remove(const std::string &name) { - auto hs = ll::hash_utils::do_hash2(name); - for (size_t i = 0; i < size(); ++i) { - if (hashes[i] == hs) { - erase(begin() + i); - hashes.erase(hashes.begin() + i); - return; +void RowHeader::remove(const std::string& name) { + auto hs = ll::hash_utils::do_hash2(name); + for (size_t i = 0; i < size(); ++i) { + if (hashes[i] == hs) { + erase(begin() + i); + hashes.erase(hashes.begin() + i); + return; + } } - } - throw std::runtime_error("RowHeader::remove: Column " + name + - " is not found"); + throw std::runtime_error("RowHeader::remove: Column " + name + " is not found"); } -size_t RowHeader::at(const std::string &name) { - auto hs = ll::hash_utils::do_hash2(name); - for (size_t i = 0; i < size(); ++i) { - if (hashes[i] == hs) - return i; - } - throw std::out_of_range("RowHeader::at: Column " + name + " is not found"); +size_t RowHeader::at(const std::string& name) { + auto hs = ll::hash_utils::do_hash2(name); + for (size_t i = 0; i < size(); ++i) { + if (hashes[i] == hs) return i; + } + throw std::out_of_range("RowHeader::at: Column " + name + " is not found"); } -std::string &RowHeader::at(size_t index) { return Base::at(index); } +std::string& RowHeader::at(size_t index) { return Base::at(index); } size_t RowHeader::size() const { return Base::size(); } @@ -51,118 +47,104 @@ std::vector::iterator RowHeader::begin() { return Base::begin(); } std::vector::iterator RowHeader::end() { return Base::end(); } -bool RowHeader::check(const Row &row) const { - if (row.header.get() == this) - return true; +bool RowHeader::check(const Row& row) const { + if (row.header.get() == this) return true; - if (row.size() == size()) { - if (row.header && !row.header->empty()) { - if (row.header->size() == size()) + if (row.size() == size()) { + if (row.header && !row.header->empty()) { + if (row.header->size() == size()) return true; + else return false; + } return true; - else - return false; } - return true; - } - return false; -} - -size_t RowHeader::operator[](const std::string &name) { - auto hs = ll::hash_utils::do_hash2(name); - for (size_t i = 0; i < size(); ++i) { - if (hashes[i] == hs) - return i; - } - return add(name); -} -std::string &RowHeader::operator[](size_t index) { return at(index); } - -Row::Row(const std::shared_ptr &header) : header(header) {} -Row::Row(const RowHeader &header) : header(new RowHeader(header)) {} -Row::Row(const std::initializer_list &list, const RowHeader &header) - : std::vector(list), header(new RowHeader(header)) { - if (!header.empty() && list.size() != header.size()) { - throw std::invalid_argument("Row::Row: The row and the header mismatch"); - } -} -Row::Row(const std::initializer_list &list, - const std::shared_ptr &header) - : std::vector(list), header(header) { - if (header != nullptr && list.size() != header->size()) { - throw std::invalid_argument("Row::Row: The row and the header mismatch"); - } -} -Row::Row(std::vector &&list, const RowHeader &header) - : std::vector(std::move(list)), header(new RowHeader(header)) { - if (size() != header.size()) { - list = std::move(*this); // Restore - throw std::invalid_argument("Row::Row: The row and the header mismatch"); - } -} -Row::Row(const std::vector &list, const RowHeader &header) - : std::vector(list), header(new RowHeader(header)) { - if (list.size() != header.size()) { - throw std::invalid_argument("Row::Row: The row and the header mismatch"); - } -} -Row::Row(const std::initializer_list> &list) - : header(new RowHeader()) { - for (auto &pair : list) { - header->add(pair.first); - this->push_back(pair.second); - } -} -Row::Row(Row &&row) noexcept : header(row.header) { *this = std::move(row); } -Row::Row(const Row &row) : header(row.header) { *this = row; } - -Row &Row::operator=(Row &&row) noexcept { - header = row.header; - this->swap(row); - return *this; -} -Row &Row::operator=(const Row &row) { - header = row.header; - this->assign(row.begin(), row.end()); - return *this; -} - -Any &Row::operator[](const std::string &name) { - auto idx = (*header)[name]; - if (idx < (int)size()) - return std::vector::at(idx); - resize((size_t)idx + 1, Any()); - return std::vector::at(idx); + return false; } -const Any &Row::operator[](const std::string &name) const { - return std::vector::at(header->at(name)); + +size_t RowHeader::operator[](const std::string& name) { + auto hs = ll::hash_utils::do_hash2(name); + for (size_t i = 0; i < size(); ++i) { + if (hashes[i] == hs) return i; + } + return add(name); } +std::string& RowHeader::operator[](size_t index) { return at(index); } -Any &Row::at(const std::string &name) { - return std::vector::at(header->at(name)); +Row::Row(const std::shared_ptr& header) : header(header) {} +Row::Row(const RowHeader& header) : header(new RowHeader(header)) {} +Row::Row(const std::initializer_list& list, const RowHeader& header) +: std::vector(list), + header(new RowHeader(header)) { + if (!header.empty() && list.size() != header.size()) { + throw std::invalid_argument("Row::Row: The row and the header mismatch"); + } } -const Any &Row::at(const std::string &name) const { - return std::vector::at(header->at(name)); +Row::Row(const std::initializer_list& list, const std::shared_ptr& header) +: std::vector(list), + header(header) { + if (header != nullptr && list.size() != header->size()) { + throw std::invalid_argument("Row::Row: The row and the header mismatch"); + } } +Row::Row(std::vector&& list, const RowHeader& header) +: std::vector(std::move(list)), + header(new RowHeader(header)) { + if (size() != header.size()) { + list = std::move(*this); // Restore + throw std::invalid_argument("Row::Row: The row and the header mismatch"); + } +} +Row::Row(const std::vector& list, const RowHeader& header) +: std::vector(list), + header(new RowHeader(header)) { + if (list.size() != header.size()) { + throw std::invalid_argument("Row::Row: The row and the header mismatch"); + } +} +Row::Row(const std::initializer_list>& list) : header(new RowHeader()) { + for (auto& pair : list) { + header->add(pair.first); + this->push_back(pair.second); + } +} +Row::Row(Row&& row) noexcept : header(row.header) { *this = std::move(row); } +Row::Row(const Row& row) : header(row.header) { *this = row; } + +Row& Row::operator=(Row&& row) noexcept { + header = row.header; + this->swap(row); + return *this; +} +Row& Row::operator=(const Row& row) { + header = row.header; + this->assign(row.begin(), row.end()); + return *this; +} + +Any& Row::operator[](const std::string& name) { + auto idx = (*header)[name]; + if (idx < (int)size()) return std::vector::at(idx); + resize((size_t)idx + 1, Any()); + return std::vector::at(idx); +} +const Any& Row::operator[](const std::string& name) const { return std::vector::at(header->at(name)); } + +Any& Row::at(const std::string& name) { return std::vector::at(header->at(name)); } +const Any& Row::at(const std::string& name) const { return std::vector::at(header->at(name)); } -void Row::forEach_ref(std::function cb) { - if (!this->header) - return; - for (auto &col : *this->header) { - if (!cb(col, this->at(col))) - break; - } +void Row::forEach_ref(std::function cb) { + if (!this->header) return; + for (auto& col : *this->header) { + if (!cb(col, this->at(col))) break; + } } -void Row::forEach( - std::function cb) const { - if (!this->header) - return; - int i = 0; - for (auto &col : *this->header) { - if (!cb(col, this->data()[i])) - break; - i++; - } +void Row::forEach(std::function cb) const { + if (!this->header) return; + int i = 0; + for (auto& col : *this->header) { + if (!cb(col, this->data()[i])) break; + i++; + } } } // namespace DB diff --git a/src/legacyapi/db/Row.h b/src/legacyapi/db/Row.h index 7af6a805..544bac68 100644 --- a/src/legacyapi/db/Row.h +++ b/src/legacyapi/db/Row.h @@ -11,235 +11,234 @@ class Row; class RowHeader : private std::vector { - using Base = std::vector; - std::vector hashes; + using Base = std::vector; + std::vector hashes; public: - /** - * @brief Construct a new Row Header object. - * - */ - RowHeader() = default; - /** - * @brief Construct a new Row Header object. - * - * @param list An initializer list like `{"col1", "col2", "col3"}` - */ - RowHeader(const std::initializer_list &list); - /// Move constructor - RowHeader(RowHeader &&other) noexcept = default; - /// Copy constructor - RowHeader(const RowHeader &other) = default; - /// Destructor - ~RowHeader(); - /** - * @brief Add a column to the header. - * - * @param name The name of the column - * @return int The index of the column - */ - size_t add(const std::string &name); - /** - * @brief Get whether the header contains a column. - * - * @param name The name of the column - * @return bool True if the column exists - */ - bool contains(const std::string &name); - /** - * @brief Remove a column from the header. - * - * @param name The name of the column - * @throws std::out_of_range If the column does not exist - */ - void remove(const std::string &name); - /** - * @brief Get the size of the header. - * - * @return int The size of the header - */ - size_t size() const; - /** - * @brief Get weather the header is empty. - * - * @return bool True if the header is empty - */ - bool empty() const; - /** - * @brief Get the index of a column. - * - * @param name The name of the column - * @return int The index of the column - * @throws std::out_of_range If the column does not exist - */ - size_t at(const std::string &name); - /** - * @brief Get the index of a column. - * - * @param index The index of the column - * @return std::string& The name of the column - * @throws std::out_of_range If the column does not exist - */ - std::string &at(size_t index); - /** - * @brief Get the iterator to the first element - * - * @return std::unordered_map::iterator The iterator - */ - std::vector::iterator begin(); - /** - * @brief Get the iterator to the last element. - * - * @return std::unordered_map::iterator The iterator - */ - std::vector::iterator end(); - /** - * @brief Check whether the row can be adapted to the header. - * - * @param row The row to adapt - * @return bool True if the row can be adapted - */ - bool check(const Row &row) const; + /** + * @brief Construct a new Row Header object. + * + */ + RowHeader() = default; + /** + * @brief Construct a new Row Header object. + * + * @param list An initializer list like `{"col1", "col2", "col3"}` + */ + RowHeader(const std::initializer_list& list); + /// Move constructor + RowHeader(RowHeader&& other) noexcept = default; + /// Copy constructor + RowHeader(const RowHeader& other) = default; + /// Destructor + ~RowHeader(); + /** + * @brief Add a column to the header. + * + * @param name The name of the column + * @return int The index of the column + */ + size_t add(const std::string& name); + /** + * @brief Get whether the header contains a column. + * + * @param name The name of the column + * @return bool True if the column exists + */ + bool contains(const std::string& name); + /** + * @brief Remove a column from the header. + * + * @param name The name of the column + * @throws std::out_of_range If the column does not exist + */ + void remove(const std::string& name); + /** + * @brief Get the size of the header. + * + * @return int The size of the header + */ + size_t size() const; + /** + * @brief Get weather the header is empty. + * + * @return bool True if the header is empty + */ + bool empty() const; + /** + * @brief Get the index of a column. + * + * @param name The name of the column + * @return int The index of the column + * @throws std::out_of_range If the column does not exist + */ + size_t at(const std::string& name); + /** + * @brief Get the index of a column. + * + * @param index The index of the column + * @return std::string& The name of the column + * @throws std::out_of_range If the column does not exist + */ + std::string& at(size_t index); + /** + * @brief Get the iterator to the first element + * + * @return std::unordered_map::iterator The iterator + */ + std::vector::iterator begin(); + /** + * @brief Get the iterator to the last element. + * + * @return std::unordered_map::iterator The iterator + */ + std::vector::iterator end(); + /** + * @brief Check whether the row can be adapted to the header. + * + * @param row The row to adapt + * @return bool True if the row can be adapted + */ + bool check(const Row& row) const; - /** - * @brief Get the index of a column. - * - * @param name The name of the column - * @return int The index of the column - * @note It will create the column(=add) if it does not exist - */ - size_t operator[](const std::string &name); - /** - * @brief Get the name of a column. - * - * @param index The index of the column - * @return std::string& The name of the column - */ - std::string &operator[](size_t index); + /** + * @brief Get the index of a column. + * + * @param name The name of the column + * @return int The index of the column + * @note It will create the column(=add) if it does not exist + */ + size_t operator[](const std::string& name); + /** + * @brief Get the name of a column. + * + * @param index The index of the column + * @return std::string& The name of the column + */ + std::string& operator[](size_t index); - /// Move assignment operator - RowHeader &operator=(RowHeader &&other) noexcept = default; - /// Copy assignment operator - RowHeader &operator=(const RowHeader &other) = default; + /// Move assignment operator + RowHeader& operator=(RowHeader&& other) noexcept = default; + /// Copy assignment operator + RowHeader& operator=(const RowHeader& other) = default; }; class Row : public std::vector { public: - std::shared_ptr header; //!< The header of the row + std::shared_ptr header; //!< The header of the row - /** - * @brief Construct a new Row object. - * - * @param header The header(column names) of the row(shared_ptr) - */ - Row(const std::shared_ptr &header = nullptr); - /** - * @brief Construct a new Row object. - * - * @param header The header(column names) of the row - * @note This will create a shared_ptr of the header - */ - Row(const RowHeader &header); - /** - * @brief Construct a new Row object. - * - * @param list List of values - * @param header The header(column names) of the row - * @throw std::invalid_argument If the size of the list is not equal to the - * size of the header - * @par Example - * @code - * RowHeader header{"id", "age", "name"}; - * Row row1({114, 24, "alex"}, header); - * Row row2({514, 24, "steve"}, {"id", "age", "name"}); - * @endcode - */ - Row(const std::initializer_list &list, const RowHeader &header); - /** - * @brief Construct a new Row object. - * - * @param list List of values - * @param header The header(column names) of the row(shared_ptr) - * @throw std::invalid_argument If the size of the list is not equal to the - * size of the header - */ - Row(const std::initializer_list &list, - const std::shared_ptr &header = nullptr); - /** - * @brief Construct a new Row object(move). - * - * @param list Vector of values - * @param header The header(column names) of the row - * @throw std::invalid_argument If the size of the vector is not equal to the - * size of the header - */ - Row(std::vector &&list, const RowHeader &header); - /** - * @brief Construct a new Row object. - * - * @param list Vector of values - * @param header The header(column names) of the row - * @throw std::invalid_argument If the size of the vector is not equal to the - * size of the header - */ - Row(const std::vector &list, const RowHeader &header); - /** - * @brief Construct a new Row object(move). - * - * @param list Vector of column names(header) and values - * @par Example - * @code - * Row row({{"id", 114}, {"age", 2000}, {"name", "alex"}}); - * @endcode - */ - Row(const std::initializer_list> &list); - /// Move constructor - Row(Row &&other) noexcept; - /// Copy constructor - Row(const Row &other); - /// Move assignment operator - Row &operator=(Row &&other) noexcept; - /// Copy assignment operator - Row &operator=(const Row &other); - /** - * @brief Get the value of a column - * - * @param name The name of the column - * @return Any& The value of the column - * @note It will create a new Any object if the column doesn't exist - */ - Any &operator[](const std::string &name); - /** - * @brief Get the value of a column - * - * @param name The name of the column - * @return Any& The value of the column - * @see Row::at - */ - const Any &operator[](const std::string &name) const; - /** - * @brief Get the value of a column - * - * @param column The name of the column - * @return Any& The value of the column - * @throw std::out_of_range If the column does not exist - */ - Any &at(const std::string &column); - const Any &at(const std::string &column) const; - /** - * @brief Traverse the row(references) - * - * @param cb The function to call for each element - * @note Return false in callback function to stop the iteration - */ - void forEach_ref(std::function cb); - /** - * @brief Traverse the row - * - * @param cb The function to call for each element - * @note Return false in callback function to stop the iteration - */ - void forEach(std::function cb) const; + /** + * @brief Construct a new Row object. + * + * @param header The header(column names) of the row(shared_ptr) + */ + Row(const std::shared_ptr& header = nullptr); + /** + * @brief Construct a new Row object. + * + * @param header The header(column names) of the row + * @note This will create a shared_ptr of the header + */ + Row(const RowHeader& header); + /** + * @brief Construct a new Row object. + * + * @param list List of values + * @param header The header(column names) of the row + * @throw std::invalid_argument If the size of the list is not equal to the + * size of the header + * @par Example + * @code + * RowHeader header{"id", "age", "name"}; + * Row row1({114, 24, "alex"}, header); + * Row row2({514, 24, "steve"}, {"id", "age", "name"}); + * @endcode + */ + Row(const std::initializer_list& list, const RowHeader& header); + /** + * @brief Construct a new Row object. + * + * @param list List of values + * @param header The header(column names) of the row(shared_ptr) + * @throw std::invalid_argument If the size of the list is not equal to the + * size of the header + */ + Row(const std::initializer_list& list, const std::shared_ptr& header = nullptr); + /** + * @brief Construct a new Row object(move). + * + * @param list Vector of values + * @param header The header(column names) of the row + * @throw std::invalid_argument If the size of the vector is not equal to the + * size of the header + */ + Row(std::vector&& list, const RowHeader& header); + /** + * @brief Construct a new Row object. + * + * @param list Vector of values + * @param header The header(column names) of the row + * @throw std::invalid_argument If the size of the vector is not equal to the + * size of the header + */ + Row(const std::vector& list, const RowHeader& header); + /** + * @brief Construct a new Row object(move). + * + * @param list Vector of column names(header) and values + * @par Example + * @code + * Row row({{"id", 114}, {"age", 2000}, {"name", "alex"}}); + * @endcode + */ + Row(const std::initializer_list>& list); + /// Move constructor + Row(Row&& other) noexcept; + /// Copy constructor + Row(const Row& other); + /// Move assignment operator + Row& operator=(Row&& other) noexcept; + /// Copy assignment operator + Row& operator=(const Row& other); + /** + * @brief Get the value of a column + * + * @param name The name of the column + * @return Any& The value of the column + * @note It will create a new Any object if the column doesn't exist + */ + Any& operator[](const std::string& name); + /** + * @brief Get the value of a column + * + * @param name The name of the column + * @return Any& The value of the column + * @see Row::at + */ + const Any& operator[](const std::string& name) const; + /** + * @brief Get the value of a column + * + * @param column The name of the column + * @return Any& The value of the column + * @throw std::out_of_range If the column does not exist + */ + Any& at(const std::string& column); + const Any& at(const std::string& column) const; + /** + * @brief Traverse the row(references) + * + * @param cb The function to call for each element + * @note Return false in callback function to stop the iteration + */ + void forEach_ref(std::function cb); + /** + * @brief Traverse the row + * + * @param cb The function to call for each element + * @note Return false in callback function to stop the iteration + */ + void forEach(std::function cb) const; }; } // namespace DB @@ -251,8 +250,12 @@ class Row : public std::vector { * @param row A row * @return T The converted value */ -template inline T row_to(const DB::Row &row) { - throw std::bad_cast(); +template +inline T row_to(const DB::Row& row) { + throw std::bad_cast(); } -template <> inline DB::Row row_to(const DB::Row &row) { return row; } \ No newline at end of file +template <> +inline DB::Row row_to(const DB::Row& row) { + return row; +} \ No newline at end of file diff --git a/src/legacyapi/db/RowSet.cpp b/src/legacyapi/db/RowSet.cpp index 4b569511..7a5b579f 100644 --- a/src/legacyapi/db/RowSet.cpp +++ b/src/legacyapi/db/RowSet.cpp @@ -5,102 +5,93 @@ namespace DB { -RowSet::RowSet(const std::shared_ptr &header) - : std::vector(), header(header) { - if (!header) { - this->header = std::make_shared(); - } +RowSet::RowSet(const std::shared_ptr& header) : std::vector(), header(header) { + if (!header) { + this->header = std::make_shared(); + } } -RowSet::RowSet(const RowHeader &header) - : std::vector(), header(new RowHeader(header)) {} -RowSet::RowSet(RowSet &&set) noexcept - : std::vector(std::move(set)), header(set.header) {} -RowSet::RowSet(const RowSet &set) : std::vector(set), header(set.header) {} -RowSet &RowSet::operator=(RowSet &&set) noexcept { - Base::operator=(std::move(set)); - header = set.header; - return *this; +RowSet::RowSet(const RowHeader& header) : std::vector(), header(new RowHeader(header)) {} +RowSet::RowSet(RowSet&& set) noexcept : std::vector(std::move(set)), header(set.header) {} +RowSet::RowSet(const RowSet& set) : std::vector(set), header(set.header) {} +RowSet& RowSet::operator=(RowSet&& set) noexcept { + Base::operator=(std::move(set)); + header = set.header; + return *this; } -RowSet &RowSet::operator=(const RowSet &set) { - Base::operator=(set); - header = set.header; - return *this; +RowSet& RowSet::operator=(const RowSet& set) { + Base::operator=(set); + header = set.header; + return *this; } -void RowSet::add(const Row &row) { - if (header && !header->empty()) { - if (!header->check(row)) - throw std::runtime_error("RowSet::add: Row doesn't match header"); - } else if (row.header && !row.header->empty()) { - header = row.header; - } - Base::push_back(row); - if (!row.header || row.header->empty()) { - Base::back().header = header; - } +void RowSet::add(const Row& row) { + if (header && !header->empty()) { + if (!header->check(row)) throw std::runtime_error("RowSet::add: Row doesn't match header"); + } else if (row.header && !row.header->empty()) { + header = row.header; + } + Base::push_back(row); + if (!row.header || row.header->empty()) { + Base::back().header = header; + } } bool RowSet::valid() { - if (!header) - return false; - size_t rowSize = header->size(); - if (!rowSize) - return false; - for (auto &row : *this) { - if (row.size() != rowSize) - return false; - } - return true; + if (!header) return false; + size_t rowSize = header->size(); + if (!rowSize) return false; + for (auto& row : *this) { + if (row.size() != rowSize) return false; + } + return true; } -void RowSet::push_back(const Row &row) { add(row); } +void RowSet::push_back(const Row& row) { add(row); } -std::string RowSet::toTableString(const std::string &nullPattern) const { - if (!header || !header->size()) - return ""; - std::string result, dividingLine; - // Get the field widths - std::vector colWidths; - for (size_t i = 0; i < header->size(); ++i) { - colWidths.push_back(header->at(i).size()); - } - for (auto &row : *this) { - for (size_t i = 0; i < row.size(); ++i) { - auto val = row.data()[i]; - if (val.is_null()) { - colWidths[i] = std::max(sizeof(nullPattern) - 1, colWidths[i]); - } - colWidths[i] = std::max(val.get().size(), colWidths[i]); +std::string RowSet::toTableString(const std::string& nullPattern) const { + if (!header || !header->size()) return ""; + std::string result, dividingLine; + // Get the field widths + std::vector colWidths; + for (size_t i = 0; i < header->size(); ++i) { + colWidths.push_back(header->at(i).size()); } - } - // Build the dividing line like '|====|=====|' - for (auto &w : colWidths) { - dividingLine += "|" + std::string(w + 2, '='); - } - dividingLine += "|\n"; - // Build the table header - for (size_t i = 0; i < header->size(); ++i) { - result += fmt::format("| {:^{}} ", header->at(i), colWidths[i]); - } - result += "|\n"; - result += dividingLine; - // Build the table body - for (auto &row : *this) { - for (size_t i = 0; i < row.size(); ++i) { - auto val = row.data()[i]; - if (val.is_null()) { - result += fmt::format("| {:<{}} ", nullPattern, colWidths[i]); - } else { - result += - fmt::format("| {:<{}} ", val.get(), colWidths[i]); - } + for (auto& row : *this) { + for (size_t i = 0; i < row.size(); ++i) { + auto val = row.data()[i]; + if (val.is_null()) { + colWidths[i] = std::max(sizeof(nullPattern) - 1, colWidths[i]); + } + colWidths[i] = std::max(val.get().size(), colWidths[i]); + } + } + // Build the dividing line like '|====|=====|' + for (auto& w : colWidths) { + dividingLine += "|" + std::string(w + 2, '='); + } + dividingLine += "|\n"; + // Build the table header + for (size_t i = 0; i < header->size(); ++i) { + result += fmt::format("| {:^{}} ", header->at(i), colWidths[i]); } result += "|\n"; - } - // Last line - result += dividingLine; - return result; + result += dividingLine; + // Build the table body + for (auto& row : *this) { + for (size_t i = 0; i < row.size(); ++i) { + auto val = row.data()[i]; + if (val.is_null()) { + result += fmt::format("| {:<{}} ", nullPattern, colWidths[i]); + } else { + result += fmt::format("| {:<{}} ", val.get(), colWidths[i]); + } + } + result += "|\n"; + } + // Last line + result += dividingLine; + return result; } } // namespace DB \ No newline at end of file diff --git a/src/legacyapi/db/RowSet.h b/src/legacyapi/db/RowSet.h index bfb307fb..cca7d959 100644 --- a/src/legacyapi/db/RowSet.h +++ b/src/legacyapi/db/RowSet.h @@ -8,68 +8,68 @@ namespace DB { class RowSet : public std::vector { - using Base = std::vector; + using Base = std::vector; public: - std::shared_ptr header; //!< The header of the rows + std::shared_ptr header; //!< The header of the rows - /** - * @brief Construct a new Row Set object - * - * @param header The header(column names) of rows(shared_ptr) - */ - RowSet(const std::shared_ptr &header = nullptr); - /** - * @brief Construct a new Row Set object - * - * @param header The header(column names) of rows - */ - RowSet(const RowHeader &header); - /// Move constructor - RowSet(RowSet &&set) noexcept; - /// Copy constructor - RowSet(const RowSet &set); - /// Move assignment operator - RowSet &operator=(RowSet &&set) noexcept; - /// Copy assignment operator - RowSet &operator=(const RowSet &set); + /** + * @brief Construct a new Row Set object + * + * @param header The header(column names) of rows(shared_ptr) + */ + RowSet(const std::shared_ptr& header = nullptr); + /** + * @brief Construct a new Row Set object + * + * @param header The header(column names) of rows + */ + RowSet(const RowHeader& header); + /// Move constructor + RowSet(RowSet&& set) noexcept; + /// Copy constructor + RowSet(const RowSet& set); + /// Move assignment operator + RowSet& operator=(RowSet&& set) noexcept; + /// Copy assignment operator + RowSet& operator=(const RowSet& set); - /** - * @brief Add a row to the set. - * - * @param row The row to add - */ - void add(const Row &row); - /** - * @brief Get if the set is valid - * - * @return bool True if valid - */ - bool valid(); - /** - * @brief Add a row to the set. - * - * @param row The row to add - * @see add(const Row&) - */ - void push_back(const Row &row); - /** - * @brief Convert to the table string. - * - * @param nullPattern When the value is null, what to replace with(default - * '\') - * @return std::string The result string - * @par sample - * @code - * | a | b | - * |=====|========| - * | awa | 114514 | - * | qwq | 233 | - * | ll | | - * |=====|========| - * @endcode - */ - std::string toTableString(const std::string &nullPattern = "") const; + /** + * @brief Add a row to the set. + * + * @param row The row to add + */ + void add(const Row& row); + /** + * @brief Get if the set is valid + * + * @return bool True if valid + */ + bool valid(); + /** + * @brief Add a row to the set. + * + * @param row The row to add + * @see add(const Row&) + */ + void push_back(const Row& row); + /** + * @brief Convert to the table string. + * + * @param nullPattern When the value is null, what to replace with(default + * '\') + * @return std::string The result string + * @par sample + * @code + * | a | b | + * |=====|========| + * | awa | 114514 | + * | qwq | 233 | + * | ll | | + * |=====|========| + * @endcode + */ + std::string toTableString(const std::string& nullPattern = "") const; }; using ResultSet = RowSet; diff --git a/src/legacyapi/db/Session.cpp b/src/legacyapi/db/Session.cpp index c574b5be..5d58c9a9 100644 --- a/src/legacyapi/db/Session.cpp +++ b/src/legacyapi/db/Session.cpp @@ -8,111 +8,114 @@ ll::Logger dbLogger("LLSEDB"); void Session::setDebugOutput(bool enable) { debugOutput = enable; } -bool Session::relogin(const std::string &user, const std::string &password, - const std::string &db) { - throw std::runtime_error("Session::relogin: Not implemented"); +bool Session::relogin(const std::string& user, const std::string& password, const std::string& db) { + throw std::runtime_error("Session::relogin: Not implemented"); } -ResultSet Session::query(const std::string &query) { - bool headerSet = false; - ResultSet result; - this->query(query, [&](const Row &row) { - if (!headerSet) { - result.header = row.header; - headerSet = true; +ResultSet Session::query(const std::string& query) { + bool headerSet = false; + ResultSet result; + this->query(query, [&](const Row& row) { + if (!headerSet) { + result.header = row.header; + headerSet = true; + } + result.push_back(row); + return true; + }); + IF_ENDBG { + if (result.valid()) { + dbLogger.debug("Session::query: Results >"); + for (auto& str : ll::string_utils::splitByPattern(result.toTableString(), "\n")) { + dbLogger.debug(str); + } + } else { + dbLogger.debug("Session::query: Query returned no result"); + } } - result.push_back(row); - return true; - }); - IF_ENDBG { - if (result.valid()) { - dbLogger.debug("Session::query: Results >"); - for (auto &str : - ll::string_utils::splitByPattern(result.toTableString(), "\n")) { - dbLogger.debug(str); - } - } else { - dbLogger.debug("Session::query: Query returned no result"); - } - } - return result; + return result; } -std::string Session::getLastError() const { - throw std::runtime_error("Session::getLastError: Not implemented"); -} +std::string Session::getLastError() const { throw std::runtime_error("Session::getLastError: Not implemented"); } std::weak_ptr Session::getOrSetSelf() { - if (self.expired()) { - IF_ENDBG dbLogger.debug( - "Session::getOrSetSelf: `self` expired, trying fetching"); - return self = getSession(this); - } - return self; + if (self.expired()) { + IF_ENDBG dbLogger.debug("Session::getOrSetSelf: `self` expired, trying fetching"); + return self = getSession(this); + } + return self; } -SharedPointer Session::operator<<(const std::string &query) { - return prepare(query); -} +SharedPointer Session::operator<<(const std::string& query) { return prepare(query); } SharedPointer Session::create(DBType type) { return _Create(type); } -SharedPointer Session::create(const ConnParams ¶ms) { - static std::unordered_map names{ - {"sqlite", DBType::SQLite}, - {"sqlite3", DBType::SQLite}, - {"file", DBType::SQLite}, - {"mysql", DBType::MySQL}, - {"mysqlc", DBType::MySQL}}; - ConnParams copy = params; - auto scheme = copy.getScheme(); - std::transform(scheme.begin(), scheme.end(), scheme.begin(), ::tolower); - if (names.count(scheme)) { - return _Create(names[scheme], params); - } else { - throw std::runtime_error( - "Session::create: Unknown/Unsupported database type"); - } -} -SharedPointer Session::create(DBType type, const ConnParams ¶ms) { - return _Create(type, params); +SharedPointer Session::create(const ConnParams& params) { + static std::unordered_map names{ + {"sqlite", DBType::SQLite}, + {"sqlite3", DBType::SQLite}, + {"file", DBType::SQLite}, + {"mysql", DBType::MySQL }, + {"mysqlc", DBType::MySQL } + }; + ConnParams copy = params; + auto scheme = copy.getScheme(); + std::transform(scheme.begin(), scheme.end(), scheme.begin(), ::tolower); + if (names.count(scheme)) { + return _Create(names[scheme], params); + } else { + throw std::runtime_error("Session::create: Unknown/Unsupported database type"); + } } -SharedPointer Session::create(DBType type, const std::string &host, - uint16_t port, const std::string &user, - const std::string &password, - const std::string &database) { - return _Create(type, {{"host", host}, - {"port", port}, - {"user", user}, - {"password", password}, - {"database", database}}); +SharedPointer Session::create(DBType type, const ConnParams& params) { return _Create(type, params); } +SharedPointer Session::create( + DBType type, + const std::string& host, + uint16_t port, + const std::string& user, + const std::string& password, + const std::string& database +) { + return _Create( + type, + { + {"host", host }, + {"port", port }, + {"user", user }, + {"password", password}, + {"database", database} + } + ); } -SharedPointer Session::create(DBType type, const std::string &path) { - return _Create(type, {{"path", path}}); +SharedPointer Session::create(DBType type, const std::string& path) { + return _Create( + type, + { + {"path", path} + } + ); } -SharedPointer Session::_Create(DBType type, const ConnParams ¶ms) { - Session *session = nullptr; - switch (type) { - case DBType::SQLite: - session = params.empty() ? new SQLiteSession() : new SQLiteSession(params); - break; - case DBType::MySQL: - session = params.empty() ? new MySQLSession() : new MySQLSession(params); - break; - default: - throw std::runtime_error( - "Session::_Create: Unknown/Unsupported database type"); - } - if (session) { - auto result = SharedPointer(session); - result->self = result; - sessionPool.push_back(result); - return result; - } - return SharedPointer(); +SharedPointer Session::_Create(DBType type, const ConnParams& params) { + Session* session = nullptr; + switch (type) { + case DBType::SQLite: + session = params.empty() ? new SQLiteSession() : new SQLiteSession(params); + break; + case DBType::MySQL: + session = params.empty() ? new MySQLSession() : new MySQLSession(params); + break; + default: + throw std::runtime_error("Session::_Create: Unknown/Unsupported database type"); + } + if (session) { + auto result = SharedPointer(session); + result->self = result; + sessionPool.push_back(result); + return result; + } + return SharedPointer(); } -std::vector> Session::sessionPool = - std::vector>(); +std::vector> Session::sessionPool = std::vector>(); } // namespace DB \ No newline at end of file diff --git a/src/legacyapi/db/Session.h b/src/legacyapi/db/Session.h index 7e444e13..c25f7389 100644 --- a/src/legacyapi/db/Session.h +++ b/src/legacyapi/db/Session.h @@ -13,221 +13,216 @@ class Session { protected: #if defined(LLDB_DEBUG_MODE) - bool debugOutput = true; + bool debugOutput = true; #else - bool debugOutput = false; + bool debugOutput = false; #endif - std::weak_ptr self; - std::vector> - stmtPool; ///< List of statements opened by prepare method. + std::weak_ptr self; + std::vector> stmtPool; ///< List of statements opened by prepare method. public: - /// Destructor - virtual ~Session() = default; - /** - * @brief Open the database connection. - * - * @par Implementation - * @see SQLiteSession::open - */ - virtual void open(const ConnParams ¶ms) = 0; - /** - * @brief Turn on/off debug output. - * - * @param enable Enable or not - */ - void setDebugOutput(bool enable); - /** - * @brief Change current user and database. - * - * @param user Username - * @param password Password - * @param db Database name - * @return bool Success or not - * @throws std::runtime_error If not implemented - * @par Implementation - * None - */ - virtual bool relogin(const std::string &user, const std::string &password, - const std::string &db = ""); - /** - * @brief Execute a query. - * - * @param query Query to execute - * @param callback Callback to process results - * @return *this - * - * @par Implementation - * @see SQLiteSession::query - */ - virtual Session &query(const std::string &query, - std::function callback) = 0; - /** - * @brief Execute a query. - * - * @param query The query to execute - * @return ResultSet Result set - */ - virtual ResultSet query(const std::string &query); - /** - * @brief Execute a query without results. - * - * @param query The query to execute - * @return bool Success or not - */ - virtual bool execute(const std::string &query) = 0; - /** - * @brief Prepare a query. - * - * @param query The query to execute - * @param autoExecute Whether to execute the statement automatically - * after binding all parameters - * @return SharedPointer The statement - * @par Example - * @code - * auto& stmt = session.prepare("SELECT * FROM table WHERE id = ?"); - * stmt.bind(1); - * auto res = stmt.getResults(); - * stmt.close(); - * @endcode - */ - virtual SharedPointer prepare(const std::string &query, - bool autoExecute = false) = 0; - /** - * @brief Get the last error message - * - * @return std::string Error message - */ - virtual std::string getLastError() const; - /** - * @brief Get the number of affected rows by the last query. - * - * @return uint64_t The number of affected rows - */ - virtual uint64_t getAffectedRows() const = 0; - /** - * @brief Get the last insert id - * - * @return uint64_t The row id of the last inserted row - */ - virtual uint64_t getLastInsertId() const = 0; - /** - * @brief Close the session. - * - */ - virtual void close() = 0; - /** - * @brief Get whether the session is open. - * - */ - virtual bool isOpen() = 0; - /** - * @brief Get the type of session - * - * @return DBType The database type - */ - virtual DBType getType() = 0; - /** - * @brief Get or set the self pointer - * - * @return std::weak_ptr self - */ - virtual std::weak_ptr getOrSetSelf(); + /// Destructor + virtual ~Session() = default; + /** + * @brief Open the database connection. + * + * @par Implementation + * @see SQLiteSession::open + */ + virtual void open(const ConnParams& params) = 0; + /** + * @brief Turn on/off debug output. + * + * @param enable Enable or not + */ + void setDebugOutput(bool enable); + /** + * @brief Change current user and database. + * + * @param user Username + * @param password Password + * @param db Database name + * @return bool Success or not + * @throws std::runtime_error If not implemented + * @par Implementation + * None + */ + virtual bool relogin(const std::string& user, const std::string& password, const std::string& db = ""); + /** + * @brief Execute a query. + * + * @param query Query to execute + * @param callback Callback to process results + * @return *this + * + * @par Implementation + * @see SQLiteSession::query + */ + virtual Session& query(const std::string& query, std::function callback) = 0; + /** + * @brief Execute a query. + * + * @param query The query to execute + * @return ResultSet Result set + */ + virtual ResultSet query(const std::string& query); + /** + * @brief Execute a query without results. + * + * @param query The query to execute + * @return bool Success or not + */ + virtual bool execute(const std::string& query) = 0; + /** + * @brief Prepare a query. + * + * @param query The query to execute + * @param autoExecute Whether to execute the statement automatically + * after binding all parameters + * @return SharedPointer The statement + * @par Example + * @code + * auto& stmt = session.prepare("SELECT * FROM table WHERE id = ?"); + * stmt.bind(1); + * auto res = stmt.getResults(); + * stmt.close(); + * @endcode + */ + virtual SharedPointer prepare(const std::string& query, bool autoExecute = false) = 0; + /** + * @brief Get the last error message + * + * @return std::string Error message + */ + virtual std::string getLastError() const; + /** + * @brief Get the number of affected rows by the last query. + * + * @return uint64_t The number of affected rows + */ + virtual uint64_t getAffectedRows() const = 0; + /** + * @brief Get the last insert id + * + * @return uint64_t The row id of the last inserted row + */ + virtual uint64_t getLastInsertId() const = 0; + /** + * @brief Close the session. + * + */ + virtual void close() = 0; + /** + * @brief Get whether the session is open. + * + */ + virtual bool isOpen() = 0; + /** + * @brief Get the type of session + * + * @return DBType The database type + */ + virtual DBType getType() = 0; + /** + * @brief Get or set the self pointer + * + * @return std::weak_ptr self + */ + virtual std::weak_ptr getOrSetSelf(); - /** - * @brief Operator<< to execute a query. - * - * @param query The query to execute - * @return SharedPointer The prepared statement - * @par Example - * @code - * ResultSet res; - * session << "SELECT * FROM table WHERE id = ?", bind(114514), into(res); - * @endcode - * @note It is not recommended to store the DB::Stmt reference returned by - * this method, it will be closed on the next execution. - */ - virtual SharedPointer operator<<(const std::string &query); + /** + * @brief Operator<< to execute a query. + * + * @param query The query to execute + * @return SharedPointer The prepared statement + * @par Example + * @code + * ResultSet res; + * session << "SELECT * FROM table WHERE id = ?", bind(114514), into(res); + * @endcode + * @note It is not recommended to store the DB::Stmt reference returned by + * this method, it will be closed on the next execution. + */ + virtual SharedPointer operator<<(const std::string& query); - /** - * @brief Create a new session. - * - * @param type Database type - * @return SharedPointer The session - */ - static SharedPointer create(DBType type); - /** - * @brief Create and open a new session. - * - * @param params Connection parameters - * @return SharedPointer The session - */ - static SharedPointer create(const ConnParams ¶ms); - /** - * @brief Create and open a new session. - * - * @param type Database type - * @param params Connection parameters - * @return SharedPointer The session - */ - static SharedPointer create(DBType type, const ConnParams ¶ms); - /** - * @brief Create and open a new session. - * - * @param type Database type - * @param host Hostname - * @param port Port - * @param user Username - * @param password Password - * @param database Database name - * @return SharedPointer The session - */ - static SharedPointer create(DBType type, const std::string &host, - uint16_t port, const std::string &user, - const std::string &password, - const std::string &database); - /** - * @brief Create and open a new session. - * - * @param type Database type - * @param path Path to the database file - * @return SharedPointer The session - */ - static SharedPointer create(DBType type, const std::string &path); + /** + * @brief Create a new session. + * + * @param type Database type + * @return SharedPointer The session + */ + static SharedPointer create(DBType type); + /** + * @brief Create and open a new session. + * + * @param params Connection parameters + * @return SharedPointer The session + */ + static SharedPointer create(const ConnParams& params); + /** + * @brief Create and open a new session. + * + * @param type Database type + * @param params Connection parameters + * @return SharedPointer The session + */ + static SharedPointer create(DBType type, const ConnParams& params); + /** + * @brief Create and open a new session. + * + * @param type Database type + * @param host Hostname + * @param port Port + * @param user Username + * @param password Password + * @param database Database name + * @return SharedPointer The session + */ + static SharedPointer create( + DBType type, + const std::string& host, + uint16_t port, + const std::string& user, + const std::string& password, + const std::string& database + ); + /** + * @brief Create and open a new session. + * + * @param type Database type + * @param path Path to the database file + * @return SharedPointer The session + */ + static SharedPointer create(DBType type, const std::string& path); private: - /** - * @brief Create a new session(internal). - * - * @param type Database type - * @param params Connection parameters - * @return SharedPointer The session - */ - static SharedPointer _Create(DBType type, - const ConnParams ¶ms = {}); + /** + * @brief Create a new session(internal). + * + * @param type Database type + * @param params Connection parameters + * @return SharedPointer The session + */ + static SharedPointer _Create(DBType type, const ConnParams& params = {}); private: - static std::vector> - sessionPool; ///< List of sessions(weak pointers) + static std::vector> sessionPool; ///< List of sessions(weak pointers) public: - /** - * @brief Get the Session ptr by the (this) pointer. - * - * @param session The (this) pointer - * @return std::shared_ptr The Session ptr - */ - static std::shared_ptr getSession(Session *session) { - for (auto &s : sessionPool) { - if (s.expired()) - continue; - auto ptr = s.lock(); - if (ptr.get() == session) - return ptr; + /** + * @brief Get the Session ptr by the (this) pointer. + * + * @param session The (this) pointer + * @return std::shared_ptr The Session ptr + */ + static std::shared_ptr getSession(Session* session) { + for (auto& s : sessionPool) { + if (s.expired()) continue; + auto ptr = s.lock(); + if (ptr.get() == session) return ptr; + } + throw std::runtime_error("Session::getSession: Session is not found or expired"); } - throw std::runtime_error( - "Session::getSession: Session is not found or expired"); - } }; } // namespace DB \ No newline at end of file diff --git a/src/legacyapi/db/Stmt.cpp b/src/legacyapi/db/Stmt.cpp index a85385fe..77dfaf17 100644 --- a/src/legacyapi/db/Stmt.cpp +++ b/src/legacyapi/db/Stmt.cpp @@ -2,8 +2,7 @@ namespace DB { -Stmt::Stmt(const std::weak_ptr &parent, bool autoExecute) - : parent(parent), autoExecute(autoExecute) {} +Stmt::Stmt(const std::weak_ptr& parent, bool autoExecute) : parent(parent), autoExecute(autoExecute) {} Stmt::~Stmt() {} @@ -12,47 +11,46 @@ void Stmt::setDebugOutput(bool enable) { debugOutput = enable; } std::weak_ptr Stmt::getParent() const { return parent; } SharedPointer Stmt::getSharedPointer() const { - if (!self.expired()) { - return self.lock(); - } - return nullptr; - /* Get the stmt ptr - if (!session.expired()) - { - auto ptr = session.lock(); - if (ptr) - { - for (auto& wptr : ptr->stmtPool) - { - if (!wptr.expired()) - { - auto stmt = wptr.lock(); - if (stmt.get() == this) - { - self = wptr; - return stmt; - } - } - } - } - } - throw std::runtime_error("Stmt::getSharedPointer: The pointer is not found or - expired"); - */ + if (!self.expired()) { + return self.lock(); + } + return nullptr; + /* Get the stmt ptr + if (!session.expired()) + { + auto ptr = session.lock(); + if (ptr) + { + for (auto& wptr : ptr->stmtPool) + { + if (!wptr.expired()) + { + auto stmt = wptr.lock(); + if (stmt.get() == this) + { + self = wptr; + return stmt; + } + } + } + } + } + throw std::runtime_error("Stmt::getSharedPointer: The pointer is not found or + expired"); + */ } -SharedPointer Stmt::operator,(const BindType &b) { - if (b.name.empty() && b.idx == -1) { - bind(b.value); - } else if (!b.name.empty()) { - bind(b.value, b.name); - } else if (b.idx != -1) { - bind(b.value, b.idx); - } else { - throw std::invalid_argument( - "Stmt::operator,: Parameter `b`(const BindType&) is invalid"); - } - return getSharedPointer(); +SharedPointer Stmt::operator,(const BindType& b) { + if (b.name.empty() && b.idx == -1) { + bind(b.value); + } else if (!b.name.empty()) { + bind(b.value, b.name); + } else if (b.idx != -1) { + bind(b.value, b.idx); + } else { + throw std::invalid_argument("Stmt::operator,: Parameter `b`(const BindType&) is invalid"); + } + return getSharedPointer(); } } // namespace DB \ No newline at end of file diff --git a/src/legacyapi/db/Stmt.h b/src/legacyapi/db/Stmt.h index b5f6da2d..5e10c0e9 100644 --- a/src/legacyapi/db/Stmt.h +++ b/src/legacyapi/db/Stmt.h @@ -12,588 +12,582 @@ extern ll::Logger dbLogger; class Session; struct BindType { - Any value; - std::string name; - int idx = -1; + Any value; + std::string name; + int idx = -1; }; -template struct BindSequenceType { - T values; - static_assert(std::is_same::value, - "Container value type must be DB::Any"); +template +struct BindSequenceType { + T values; + static_assert(std::is_same::value, "Container value type must be DB::Any"); }; -template struct BindMapType { - T values; - static_assert(std::is_same::value, - "Map key type must be std::string"); - static_assert(std::is_same::value, - "Map value type must be DB::Any"); +template +struct BindMapType { + T values; + static_assert(std::is_same::value, "Map key type must be std::string"); + static_assert(std::is_same::value, "Map value type must be DB::Any"); }; -template struct IntoType { - T &value; +template +struct IntoType { + T& value; }; class Stmt { protected: #if defined(LLDB_DEBUG_MODE) - bool debugOutput = true; + bool debugOutput = true; #else - bool debugOutput = false; + bool debugOutput = false; #endif - bool autoExecute = - false; ///< Whether to automatically execute the statement on bind - std::weak_ptr parent; ///< Parent session - std::weak_ptr self; + bool autoExecute = false; ///< Whether to automatically execute the statement on bind + std::weak_ptr parent; ///< Parent session + std::weak_ptr self; public: - Stmt(const std::weak_ptr &parent, bool autoExecute = false); - - virtual ~Stmt(); - - /** - * @brief Turn on/off debug output. - * - * @param enable Enable or not - */ - void setDebugOutput(bool enable); - - /** - * @brief Bind a value to a statement parameter. - * - * @param value Value to bind - * @param index Parameter index - * @throws std::runtime_error If error occurs - * - * @par Implementation - * @see SQLiteStmt::bind - */ - virtual Stmt &bind(const Any &value, int index) = 0; - - /** - * @brief Bind a value to a statement parameter. - * - * @param value Value to bind - * @param name Parameter name - * @throws std::runtime_error If error occurs - * - * @par Impletementation - * @see SQLiteStmt::bind - */ - virtual Stmt &bind(const Any &value, const std::string &name) = 0; - - /** - * @brief Bind a value to the next statement parameter. - * - * @param value Value to bind - * @throws std::runtime_error If error occurs - * - * @par Impletementation - * @see SQLiteStmt::bind - */ - virtual Stmt &bind(const Any &value) = 0; - - /** - * @brief Execute the statement(after binding all the parameters) - * - * @return Stmt& *this - * @note If `this->autoExecute` is true, there is no need to call this - * method - */ - virtual Stmt &execute() = 0; - - /** - * @brief Step to the next row(not fetch). - * - * @return bool True if there is a next row - * - * @par Impletementation - * @see SQLiteStmt::step - */ - virtual bool step() = 0; - - /** - * @brief Step to the next row(=step). - * - * @return bool True if there is a next row - * - * @par Impletementation - * @see SQLiteStmt::next - */ - virtual bool next() = 0; - - /** - * @brief Get weather all the rows have been fetched. - * - * @return bool True if all the rows have been fetched - * - * @par Impletementation - * @see SQLiteStmt::done - */ - virtual bool done() = 0; - - /** - * @brief Fetch the current row. - * - * @tparam T The type of the value to return - * @return T The current row(converted) - * @throws std::runtime_error If there is no row to fetch - * - * @par Example - * @code - * auto stmt = sess->prepare("SELECT * FROM table"); - * while (stmt->step()) { - * auto row = stmt->fetch(); - * // Do something with the row - * } - * stmt->close(); - * @endcode - */ - template inline T fetch() { return row_to(_Fetch()); } - - /** - * @brief Fetch the current row. - * - * @param[out] row The current row - * @return Stmt& *this - */ - template inline Stmt &fetch(T &row) { - row = row_to(_Fetch()); - return *this; - } - - /** - * @brief Fetch each of the result rows. - * - * @param cb Callback function to handle the result rows - * @return Stmt& *this - * @note Return false in callback to stop fetching - * - * @par Example - * @code - * sess->prepare("SELECT * FROM table") - * ->fetchEach([](const Row& row) { - * // Do something with the row - * return true; - * }) - * ->close(); - * @endcode - */ - inline Stmt &fetchEach(std::function cb) { - do { - auto res = _Fetch(); - if (res.size() == 0) { - continue; - } - if (!cb(res)) { - break; - } - } while (step()); - return *this; - } - - /** - * @brief Fetch each of the result rows(For compatibility). - * - * @param cb Callback function to handle the result rows - * @return Stmt& *this - * @note Return false in callback to stop fetching - * @see Stmt::fetchEach - */ - inline Stmt &fetchAll(std::function cb) { - return fetchEach(cb); - } - // virtual Stmt& fetchAll(std::function cb); - - /** - * @brief Fetch all the result rows. - * - * @tparam T The value type of vector - * @param[out] rows The result set - * @return Stmt& *this - */ - template inline Stmt &fetchAll(std::vector &rows) { - return fetchEach([&](const Row &row) { - rows.push_back(row_to(row)); - return true; - }); - return *this; - } - - /** - * @brief Fetch all the result rows. - * - * @tparam T The value type of vector - * @return std::vector The result rows - */ - template inline std::vector fetchAll() { - std::vector result; - fetchAll(result); - return result; - } - // virtual ResultSet fetchAll() = 0; - // virtual Stmt& fetchAll(ResultSet& rows); - - inline ResultSet fetchAll() { - ResultSet set; - fetchAll(set); - return set; - } - - inline Stmt &fetchAll(ResultSet &rows) { - return fetchEach([&rows](const Row &row) { - rows.push_back(row); - return true; - }); - } - - /** - * @brief Reset the statement from executing state to perpared state - * - * @return Stmt& *this - * - * @par Note - * Different between `reset()`, `reexec` and `clear()`: - * - `reset()` : Reset the statement to the prepared state - * - `reexec()`: Reset the statement to the prepared state and execute it - * - `clear()` : Reset the statement to the prepared state and clear the - * parameters, but not execute it - */ - virtual Stmt &reset() = 0; - - /** - * @brief Re-execute the statement(keep the currently bound value to - * re-excute). - * - * @return Stmt& *this - * @note If you want to clear the bound value, use clear() instead. - * @see Stmt::reset - * - * @par Impletementation - * @see SQLiteStmt::reexec - */ - virtual Stmt &reexec() = 0; - - /** - * @brief Clear all the bound values. - * - * @return Stmt& *this - * @see Stmt::reset - * - * @par Impletementation - * @see SQLiteStmt::clear - */ - virtual Stmt &clear() = 0; - - /** - * @brief Close the statement. - * - * - * @par Impletementation - * @see SQLiteStmt::close - */ - virtual void close() = 0; - - /** - * @brief Get the number of rows affected by the statement. - * - * @return int The number of rows affected - * @note It will return -1(ULLONG_MAX - 1) if the row count is not available - * - * @par Impletementation - * @see SQLiteStmt::getAffectedRows - */ - virtual uint64_t getAffectedRows() const = 0; - - /** - * @brief Get the insert id of the statement - * - * @return uint64_t The insert id - * @throws std::runtime_error If error occurs - * @note It will return -1(ULLONG_MAX - 1) if the insert id is not available - * - * @par Implementation - * @see SQLiteStmt::getInsertId - */ - virtual uint64_t getInsertId() const = 0; - - /** - * @brief Get the number of the unbound parameters. - * - * @return int The number of the unbound parameters - * - * @par Impletementation - * @see SQLiteStmt::getUnboundParams - */ - virtual int getUnboundParams() const = 0; - - /** - * @brief Get the number of the bound parameters. - * - * @return int The number of the bound parameters - * - * @par Impletementation - * @see SQLiteStmt::getBoundParams - */ - virtual int getBoundParams() const = 0; - - /** - * @brief Get the number of parameters. - * - * @return int The number of parameters - * - * @par Impletementation - * @see SQLiteStmt::getParamsCount - */ - virtual int getParamsCount() const = 0; - - /** - * @brief Get the session. - * - * @return std::weak_ptr The session ptr - */ - virtual std::weak_ptr getParent() const; - - /** - * @brief Get the shared pointer point to this - * - * @return SharedPointer The ptr - */ - virtual SharedPointer getSharedPointer() const; - - /** - * @brief Get the session type - * - * @return DB::DBType The database type - * - * @par Impletementation - * @see SQLiteStmt::getType - */ - virtual DBType getType() const = 0; - - /** - * @brief Fetch the current row(internal). - * - * @return Row The current row - */ - virtual Row _Fetch() = 0; - - /** - * @brief Operator<< to bind values. - * - * @param v The value - * @return SharedPointer this - */ - inline SharedPointer operator<<(const Any &v) { - bind(v); - return getSharedPointer(); - } - - /** - * @brief Operator>> to store the result. - * - * @tparam T The value type - * @param v Where to store - * @return SharedPointer this - */ - template inline SharedPointer operator>>(T &v) { - fetch(v); - return getSharedPointer(); - } - template <> inline SharedPointer operator>>(ResultSet &v) { - fetchAll(v); - return getSharedPointer(); - } - template - inline SharedPointer operator>>(std::vector &v) { - fetchAll(v); - return getSharedPointer(); - } - - /** - * @brief Operator, to bind single values. - * - * @param b The return value of DB::use - * @return SharedPointer this - */ - virtual SharedPointer operator,(const BindType &b); - /** - * @brief Operator, to bind a sequence container. - * - * @param b The return value of DB::use - * @return SharedPointer this - */ - template - inline SharedPointer operator,(const BindSequenceType &b) { - for (auto &v : b.values) { - bind(v); + Stmt(const std::weak_ptr& parent, bool autoExecute = false); + + virtual ~Stmt(); + + /** + * @brief Turn on/off debug output. + * + * @param enable Enable or not + */ + void setDebugOutput(bool enable); + + /** + * @brief Bind a value to a statement parameter. + * + * @param value Value to bind + * @param index Parameter index + * @throws std::runtime_error If error occurs + * + * @par Implementation + * @see SQLiteStmt::bind + */ + virtual Stmt& bind(const Any& value, int index) = 0; + + /** + * @brief Bind a value to a statement parameter. + * + * @param value Value to bind + * @param name Parameter name + * @throws std::runtime_error If error occurs + * + * @par Impletementation + * @see SQLiteStmt::bind + */ + virtual Stmt& bind(const Any& value, const std::string& name) = 0; + + /** + * @brief Bind a value to the next statement parameter. + * + * @param value Value to bind + * @throws std::runtime_error If error occurs + * + * @par Impletementation + * @see SQLiteStmt::bind + */ + virtual Stmt& bind(const Any& value) = 0; + + /** + * @brief Execute the statement(after binding all the parameters) + * + * @return Stmt& *this + * @note If `this->autoExecute` is true, there is no need to call this + * method + */ + virtual Stmt& execute() = 0; + + /** + * @brief Step to the next row(not fetch). + * + * @return bool True if there is a next row + * + * @par Impletementation + * @see SQLiteStmt::step + */ + virtual bool step() = 0; + + /** + * @brief Step to the next row(=step). + * + * @return bool True if there is a next row + * + * @par Impletementation + * @see SQLiteStmt::next + */ + virtual bool next() = 0; + + /** + * @brief Get weather all the rows have been fetched. + * + * @return bool True if all the rows have been fetched + * + * @par Impletementation + * @see SQLiteStmt::done + */ + virtual bool done() = 0; + + /** + * @brief Fetch the current row. + * + * @tparam T The type of the value to return + * @return T The current row(converted) + * @throws std::runtime_error If there is no row to fetch + * + * @par Example + * @code + * auto stmt = sess->prepare("SELECT * FROM table"); + * while (stmt->step()) { + * auto row = stmt->fetch(); + * // Do something with the row + * } + * stmt->close(); + * @endcode + */ + template + inline T fetch() { + return row_to(_Fetch()); + } + + /** + * @brief Fetch the current row. + * + * @param[out] row The current row + * @return Stmt& *this + */ + template + inline Stmt& fetch(T& row) { + row = row_to(_Fetch()); + return *this; + } + + /** + * @brief Fetch each of the result rows. + * + * @param cb Callback function to handle the result rows + * @return Stmt& *this + * @note Return false in callback to stop fetching + * + * @par Example + * @code + * sess->prepare("SELECT * FROM table") + * ->fetchEach([](const Row& row) { + * // Do something with the row + * return true; + * }) + * ->close(); + * @endcode + */ + inline Stmt& fetchEach(std::function cb) { + do { + auto res = _Fetch(); + if (res.size() == 0) { + continue; + } + if (!cb(res)) { + break; + } + } while (step()); + return *this; + } + + /** + * @brief Fetch each of the result rows(For compatibility). + * + * @param cb Callback function to handle the result rows + * @return Stmt& *this + * @note Return false in callback to stop fetching + * @see Stmt::fetchEach + */ + inline Stmt& fetchAll(std::function cb) { return fetchEach(cb); } + // virtual Stmt& fetchAll(std::function cb); + + /** + * @brief Fetch all the result rows. + * + * @tparam T The value type of vector + * @param[out] rows The result set + * @return Stmt& *this + */ + template + inline Stmt& fetchAll(std::vector& rows) { + return fetchEach([&](const Row& row) { + rows.push_back(row_to(row)); + return true; + }); + return *this; } - return getSharedPointer(); - } - /** - * @brief Operator, to bind a row. - * - * @param b The return value of DB::use - * @return SharedPointer this - */ - template <> - inline SharedPointer operator,(const BindSequenceType &b) { - if (b.values.header && b.values.header->size()) { - b.values.forEach([&](const std::string &name, const Any &value) { - bind(value, name); - return true; - }); - } else { - for (auto &v : b.values) { + + /** + * @brief Fetch all the result rows. + * + * @tparam T The value type of vector + * @return std::vector The result rows + */ + template + inline std::vector fetchAll() { + std::vector result; + fetchAll(result); + return result; + } + // virtual ResultSet fetchAll() = 0; + // virtual Stmt& fetchAll(ResultSet& rows); + + inline ResultSet fetchAll() { + ResultSet set; + fetchAll(set); + return set; + } + + inline Stmt& fetchAll(ResultSet& rows) { + return fetchEach([&rows](const Row& row) { + rows.push_back(row); + return true; + }); + } + + /** + * @brief Reset the statement from executing state to perpared state + * + * @return Stmt& *this + * + * @par Note + * Different between `reset()`, `reexec` and `clear()`: + * - `reset()` : Reset the statement to the prepared state + * - `reexec()`: Reset the statement to the prepared state and execute it + * - `clear()` : Reset the statement to the prepared state and clear the + * parameters, but not execute it + */ + virtual Stmt& reset() = 0; + + /** + * @brief Re-execute the statement(keep the currently bound value to + * re-excute). + * + * @return Stmt& *this + * @note If you want to clear the bound value, use clear() instead. + * @see Stmt::reset + * + * @par Impletementation + * @see SQLiteStmt::reexec + */ + virtual Stmt& reexec() = 0; + + /** + * @brief Clear all the bound values. + * + * @return Stmt& *this + * @see Stmt::reset + * + * @par Impletementation + * @see SQLiteStmt::clear + */ + virtual Stmt& clear() = 0; + + /** + * @brief Close the statement. + * + * + * @par Impletementation + * @see SQLiteStmt::close + */ + virtual void close() = 0; + + /** + * @brief Get the number of rows affected by the statement. + * + * @return int The number of rows affected + * @note It will return -1(ULLONG_MAX - 1) if the row count is not available + * + * @par Impletementation + * @see SQLiteStmt::getAffectedRows + */ + virtual uint64_t getAffectedRows() const = 0; + + /** + * @brief Get the insert id of the statement + * + * @return uint64_t The insert id + * @throws std::runtime_error If error occurs + * @note It will return -1(ULLONG_MAX - 1) if the insert id is not available + * + * @par Implementation + * @see SQLiteStmt::getInsertId + */ + virtual uint64_t getInsertId() const = 0; + + /** + * @brief Get the number of the unbound parameters. + * + * @return int The number of the unbound parameters + * + * @par Impletementation + * @see SQLiteStmt::getUnboundParams + */ + virtual int getUnboundParams() const = 0; + + /** + * @brief Get the number of the bound parameters. + * + * @return int The number of the bound parameters + * + * @par Impletementation + * @see SQLiteStmt::getBoundParams + */ + virtual int getBoundParams() const = 0; + + /** + * @brief Get the number of parameters. + * + * @return int The number of parameters + * + * @par Impletementation + * @see SQLiteStmt::getParamsCount + */ + virtual int getParamsCount() const = 0; + + /** + * @brief Get the session. + * + * @return std::weak_ptr The session ptr + */ + virtual std::weak_ptr getParent() const; + + /** + * @brief Get the shared pointer point to this + * + * @return SharedPointer The ptr + */ + virtual SharedPointer getSharedPointer() const; + + /** + * @brief Get the session type + * + * @return DB::DBType The database type + * + * @par Impletementation + * @see SQLiteStmt::getType + */ + virtual DBType getType() const = 0; + + /** + * @brief Fetch the current row(internal). + * + * @return Row The current row + */ + virtual Row _Fetch() = 0; + + /** + * @brief Operator<< to bind values. + * + * @param v The value + * @return SharedPointer this + */ + inline SharedPointer operator<<(const Any& v) { bind(v); - } + return getSharedPointer(); } - return getSharedPointer(); - } - /** - * @brief Operator, to bind a map container. - * - * @param b The return value of DB::bind - * @return SharedPointer this - */ - template - inline SharedPointer operator,(const BindMapType &b) { - for (auto &v : b.values) { - bind(v.second, v.first); + + /** + * @brief Operator>> to store the result. + * + * @tparam T The value type + * @param v Where to store + * @return SharedPointer this + */ + template + inline SharedPointer operator>>(T& v) { + fetch(v); + return getSharedPointer(); } - return getSharedPointer(); - } - /** - * @brief Operator, to store a row of results. - * - * @param i The return value of DB::into - * @return SharedPointer this - */ - template inline SharedPointer operator,(IntoType &i) { - if (!done()) - fetch(i.value); - return getSharedPointer(); - } - /** - * @brief Operator, to store a set of results. - * - * @param i The return value of DB::into - * @return SharedPointer this - */ - template - inline SharedPointer operator,(IntoType> &i) { - fetchAll>(i.value); - return getSharedPointer(); - } - /** - * @brief Operator, to store a set of results. - * - * @param i The return value of DB::into - * @return SharedPointer this - */ - template <> inline SharedPointer operator,(IntoType &i) { - fetchAll(i.value); - return getSharedPointer(); - } - /** - * @brief Operator, to store a row of results. - * - * @param i The return value of DB::into - * @return SharedPointer this - */ - template <> inline SharedPointer operator,(IntoType &i) { - fetch(i.value); - return getSharedPointer(); - } - - /** - * @brief Operator-> to implement better API. - * - * @return Stmt* this - */ - inline Stmt *operator->() { return this; } + template <> + inline SharedPointer operator>>(ResultSet& v) { + fetchAll(v); + return getSharedPointer(); + } + template + inline SharedPointer operator>>(std::vector& v) { + fetchAll(v); + return getSharedPointer(); + } + + /** + * @brief Operator, to bind single values. + * + * @param b The return value of DB::use + * @return SharedPointer this + */ + virtual SharedPointer operator,(const BindType& b); + /** + * @brief Operator, to bind a sequence container. + * + * @param b The return value of DB::use + * @return SharedPointer this + */ + template + inline SharedPointer operator,(const BindSequenceType& b) { + for (auto& v : b.values) { + bind(v); + } + return getSharedPointer(); + } + /** + * @brief Operator, to bind a row. + * + * @param b The return value of DB::use + * @return SharedPointer this + */ + template <> + inline SharedPointer operator,(const BindSequenceType& b) { + if (b.values.header && b.values.header->size()) { + b.values.forEach([&](const std::string& name, const Any& value) { + bind(value, name); + return true; + }); + } else { + for (auto& v : b.values) { + bind(v); + } + } + return getSharedPointer(); + } + /** + * @brief Operator, to bind a map container. + * + * @param b The return value of DB::bind + * @return SharedPointer this + */ + template + inline SharedPointer operator,(const BindMapType& b) { + for (auto& v : b.values) { + bind(v.second, v.first); + } + return getSharedPointer(); + } + /** + * @brief Operator, to store a row of results. + * + * @param i The return value of DB::into + * @return SharedPointer this + */ + template + inline SharedPointer operator,(IntoType& i) { + if (!done()) fetch(i.value); + return getSharedPointer(); + } + /** + * @brief Operator, to store a set of results. + * + * @param i The return value of DB::into + * @return SharedPointer this + */ + template + inline SharedPointer operator,(IntoType>& i) { + fetchAll>(i.value); + return getSharedPointer(); + } + /** + * @brief Operator, to store a set of results. + * + * @param i The return value of DB::into + * @return SharedPointer this + */ + template <> + inline SharedPointer operator,(IntoType& i) { + fetchAll(i.value); + return getSharedPointer(); + } + /** + * @brief Operator, to store a row of results. + * + * @param i The return value of DB::into + * @return SharedPointer this + */ + template <> + inline SharedPointer operator,(IntoType& i) { + fetch(i.value); + return getSharedPointer(); + } + + /** + * @brief Operator-> to implement better API. + * + * @return Stmt* this + */ + inline Stmt* operator->() { return this; } }; -inline BindType use(const Any &value, int idx = -1) { - return BindType{value, std::string(), idx}; -} -inline BindType use(const Any &value, const std::string &name) { - return BindType{value, name}; -} -inline BindSequenceType use(const Row &values) { - return BindSequenceType{values}; -} +inline BindType use(const Any& value, int idx = -1) { return BindType{value, std::string(), idx}; } +inline BindType use(const Any& value, const std::string& name) { return BindType{value, name}; } +inline BindSequenceType use(const Row& values) { return BindSequenceType{values}; } template -inline BindSequenceType> use(const std::vector &values) { - return BindSequenceType>{to_any_container(values)}; +inline BindSequenceType> use(const std::vector& values) { + return BindSequenceType>{to_any_container(values)}; } template -inline BindSequenceType> use(const std::set &values) { - return BindSequenceType>{to_any_container(values)}; +inline BindSequenceType> use(const std::set& values) { + return BindSequenceType>{to_any_container(values)}; } template -inline BindSequenceType> use(const std::list &values) { - return BindSequenceType>{to_any_container(values)}; +inline BindSequenceType> use(const std::list& values) { + return BindSequenceType>{to_any_container(values)}; } template -inline BindSequenceType> -use(const std::initializer_list &values) { - return BindSequenceType>{ - to_any_container(std::vector(values))}; +inline BindSequenceType> use(const std::initializer_list& values) { + return BindSequenceType>{to_any_container(std::vector(values))}; } template <> -inline BindSequenceType> use(const std::vector &values) { - return BindSequenceType>{values}; +inline BindSequenceType> use(const std::vector& values) { + return BindSequenceType>{values}; } template <> -inline BindSequenceType> use(const std::set &values) { - return BindSequenceType>{values}; +inline BindSequenceType> use(const std::set& values) { + return BindSequenceType>{values}; } template <> -inline BindSequenceType> use(const std::list &values) { - return BindSequenceType>{values}; +inline BindSequenceType> use(const std::list& values) { + return BindSequenceType>{values}; } template <> -inline BindSequenceType> -use(const std::initializer_list &values) { - return BindSequenceType>{std::vector(values)}; +inline BindSequenceType> use(const std::initializer_list& values) { + return BindSequenceType>{std::vector(values)}; } // Map template -inline BindMapType> -use(const std::map &values) { - return BindMapType>{values}; +inline BindMapType> use(const std::map& values) { + return BindMapType>{values}; } template -inline BindMapType> -use(const std::unordered_map &values) { - return BindMapType>{values}; +inline BindMapType> use(const std::unordered_map& values) { + return BindMapType>{values}; } template <> -inline BindMapType> -use(const std::map &values) { - return BindMapType>{values}; +inline BindMapType> use(const std::map& values) { + return BindMapType>{values}; } template <> -inline BindMapType> -use(const std::unordered_map &values) { - return BindMapType>{values}; +inline BindMapType> use(const std::unordered_map& values) { + return BindMapType>{values}; } -inline BindMapType> -use(const std::initializer_list> &values) { - std::map result; - for (auto &pair : values) { - result.insert(std::make_pair(pair.first, pair.second)); - } - return BindMapType>{result}; +inline BindMapType> use(const std::initializer_list>& values) { + std::map result; + for (auto& pair : values) { + result.insert(std::make_pair(pair.first, pair.second)); + } + return BindMapType>{result}; } -template inline IntoType into(T &out) { - return IntoType{out}; +template +inline IntoType into(T& out) { + return IntoType{out}; } } // namespace DB \ No newline at end of file diff --git a/src/legacyapi/db/Types.h b/src/legacyapi/db/Types.h index 5ccae494..83333e94 100644 --- a/src/legacyapi/db/Types.h +++ b/src/legacyapi/db/Types.h @@ -1,42 +1,36 @@ #pragma once #include -//#define LLDB_DEBUG_MODE +// #define LLDB_DEBUG_MODE -namespace DB -{ +namespace DB { -enum class DBType : char -{ +enum class DBType : char { None, SQLite, MySQL, }; -struct Date -{ +struct Date { int year; int month; int day; }; -struct Time -{ +struct Time { int hour; int minute; int second; int timezone = -1; }; -struct DateTime -{ +struct DateTime { Date date; Time time; }; -struct Decimal -{ +struct Decimal { int64_t value; - int scale; + int scale; }; using ByteArray = std::vector; diff --git a/src/legacyapi/db/impl/mysql/Session.cpp b/src/legacyapi/db/impl/mysql/Session.cpp index 75ec2087..37455dd4 100644 --- a/src/legacyapi/db/impl/mysql/Session.cpp +++ b/src/legacyapi/db/impl/mysql/Session.cpp @@ -6,221 +6,212 @@ namespace DB { MySQLSession::MySQLSession() { - IF_ENDBG dbLogger.info("MySQLSession::MySQLSession: Constructed! this: {}", - (void *)this); - conn = mysql_init(nullptr); + IF_ENDBG dbLogger.info("MySQLSession::MySQLSession: Constructed! this: {}", (void*)this); + conn = mysql_init(nullptr); } -MySQLSession::MySQLSession(const ConnParams ¶ms) { - IF_ENDBG dbLogger.info("MySQLSession::MySQLSession: Constructed! this: {}", - (void *)this); - conn = mysql_init(nullptr); - open(params); +MySQLSession::MySQLSession(const ConnParams& params) { + IF_ENDBG dbLogger.info("MySQLSession::MySQLSession: Constructed! this: {}", (void*)this); + conn = mysql_init(nullptr); + open(params); } MySQLSession::~MySQLSession() { - IF_ENDBG dbLogger.info("MySQLSession::MySQLSession: Destructor: this: {}", - (void *)this); - close(); + IF_ENDBG dbLogger.info("MySQLSession::MySQLSession: Destructor: this: {}", (void*)this); + close(); } -void MySQLSession::setSSL(const ConnParams ¶ms) { - auto p = params; - auto key = - p.get({"sslkey", "ssl_key", "ssl-key"}); // Private key path - auto cert = p.get( - {"sslcert", "ssl_cert", "ssl-cert"}); // Public certificate path - auto ca = p.get( - {"sslca", "ssl_ca", "ssl-ca"}); // Certificate authority path - auto capath = - p.get({"sslcapath", "ssl_capath", - "ssl-capath"}); // Certificate authority directory - auto cipher = p.get( - {"sslcipher", "ssl_cipher", "ssl-cipher"}); // List of ciphers to use - if (key.empty() || cert.empty()) { - return; - } - mysql_ssl_set( - conn, key.c_str(), cert.c_str(), (ca.empty() ? nullptr : ca.c_str()), - (capath.empty() ? nullptr : capath.c_str()), - (cipher.empty() ? nullptr : cipher.c_str())); // Always returns 0 +void MySQLSession::setSSL(const ConnParams& params) { + auto p = params; + auto key = p.get({"sslkey", "ssl_key", "ssl-key"}); // Private key path + auto cert = p.get({"sslcert", "ssl_cert", "ssl-cert"}); // Public certificate path + auto ca = p.get({"sslca", "ssl_ca", "ssl-ca"}); // Certificate authority path + auto capath = p.get({"sslcapath", "ssl_capath", "ssl-capath"}); // Certificate authority directory + auto cipher = p.get({"sslcipher", "ssl_cipher", "ssl-cipher"}); // List of ciphers to use + if (key.empty() || cert.empty()) { + return; + } + mysql_ssl_set( + conn, + key.c_str(), + cert.c_str(), + (ca.empty() ? nullptr : ca.c_str()), + (capath.empty() ? nullptr : capath.c_str()), + (cipher.empty() ? nullptr : cipher.c_str()) + ); // Always returns 0 } -void MySQLSession::open(const ConnParams ¶ms) { - auto p = params; - unsigned long flags = 0; - uint16_t port = 0; - if ((port = p.getPort()) == 0) { - port = 3306; - } - std::string db = p.getDatabase(); - if (p.get({"compress"}, true, false)) { - flags |= CLIENT_COMPRESS; - } - if (p.get({"ssl", "ssl_mode", "sslmode", "ssl-mode"}, true, false)) { - flags |= CLIENT_SSL; - setSSL(p); - } - // auto defaultCharset = mysql_character_set_name(conn); - auto charset = p.get( - {"charset", "char_set", "characterset", "character_set", "charsetname", - "char_set_name", "charactersetname", "character_set_name"}, - "true", "utf8"); - // IF_ENDBG dbLogger.debug("MySQLSession::open: MySQL default charset name: - // {}", defaultCharset); - mysql_options(conn, MYSQL_SET_CHARSET_NAME, charset.c_str()); - auto res = - mysql_real_connect(conn, p.getHost().c_str(), p.getUsername().c_str(), - p.getPassword().c_str(), - (db.empty() ? nullptr : db.c_str()), port, nullptr, 0); - if (!res) { - throw std::runtime_error( - "MySQLSession::MySQLSession: Failed to open database: " + - std::string(mysql_error(conn))); - } - IF_ENDBG dbLogger.debug( - "MySQLSession::open: Opened database: " + std::string(p.getHost()) + ":" + - std::to_string(port) + "/" + db); +void MySQLSession::open(const ConnParams& params) { + auto p = params; + unsigned long flags = 0; + uint16_t port = 0; + if ((port = p.getPort()) == 0) { + port = 3306; + } + std::string db = p.getDatabase(); + if (p.get({"compress"}, true, false)) { + flags |= CLIENT_COMPRESS; + } + if (p.get({"ssl", "ssl_mode", "sslmode", "ssl-mode"}, true, false)) { + flags |= CLIENT_SSL; + setSSL(p); + } + // auto defaultCharset = mysql_character_set_name(conn); + auto charset = p.get( + {"charset", + "char_set", + "characterset", + "character_set", + "charsetname", + "char_set_name", + "charactersetname", + "character_set_name"}, + "true", + "utf8" + ); + // IF_ENDBG dbLogger.debug("MySQLSession::open: MySQL default charset name: + // {}", defaultCharset); + mysql_options(conn, MYSQL_SET_CHARSET_NAME, charset.c_str()); + auto res = mysql_real_connect( + conn, + p.getHost().c_str(), + p.getUsername().c_str(), + p.getPassword().c_str(), + (db.empty() ? nullptr : db.c_str()), + port, + nullptr, + 0 + ); + if (!res) { + throw std::runtime_error( + "MySQLSession::MySQLSession: Failed to open database: " + std::string(mysql_error(conn)) + ); + } + IF_ENDBG dbLogger.debug( + "MySQLSession::open: Opened database: " + std::string(p.getHost()) + ":" + std::to_string(port) + "/" + db + ); #if defined(LLDB_DEBUG_MODE) - mysql_dump_debug_info(conn); + mysql_dump_debug_info(conn); #endif } -bool MySQLSession::execute(const std::string &query) { - IF_ENDBG dbLogger.debug("MySQLSession::execute: Executing > " + query); - auto res = mysql_query(conn, query.c_str()); - return res == OK; +bool MySQLSession::execute(const std::string& query) { + IF_ENDBG dbLogger.debug("MySQLSession::execute: Executing > " + query); + auto res = mysql_query(conn, query.c_str()); + return res == OK; } -bool MySQLSession::relogin(const std::string &user, const std::string &password, - const std::string &db) { - IF_ENDBG dbLogger.debug( - "MySQLSession::change: Changing user to {} and database to {}", user, db); - auto res = mysql_change_user(conn, user.c_str(), password.c_str(), - (db.empty() ? nullptr : db.c_str())); - return res == OK; +bool MySQLSession::relogin(const std::string& user, const std::string& password, const std::string& db) { + IF_ENDBG dbLogger.debug("MySQLSession::change: Changing user to {} and database to {}", user, db); + auto res = mysql_change_user(conn, user.c_str(), password.c_str(), (db.empty() ? nullptr : db.c_str())); + return res == OK; } -Session &MySQLSession::query(const std::string &query, - std::function callback) { - IF_ENDBG dbLogger.debug("MySQLSession::query: Querying > " + query); - auto res = mysql_query(conn, query.c_str()); - if (res != OK) { - throw std::runtime_error("MySQLSession::query: Failed to query database: " + - std::string(mysql_error(conn))); - } - auto result = mysql_store_result(conn); - if (!result) { - // throw std::runtime_error("MySQLSession::query: Failed to store result: " - // + std::string(mysql_error(conn))); - return *this; // No result set - } - auto numFields = mysql_num_fields(result); - auto numRows = mysql_num_rows(result); - auto fields = mysql_fetch_fields(result); - IF_ENDBG dbLogger.debug( - "MySQLSession::query: Query returned {} rows and {} fields", numRows, - numFields); - // Fetch column names - RowHeader header; - for (unsigned int i = 0; i < numFields; i++) - header.add(std::string(fields[i].name, fields[i].name_length)); - // Fetch rows - while (auto row = mysql_fetch_row(result)) { - Row r(header); - for (unsigned int i = 0; i < numFields; i++) { - auto type = fields[i].type; - switch (type) { - case MYSQL_TYPE_TINY: - case MYSQL_TYPE_SHORT: - case MYSQL_TYPE_LONG: - case MYSQL_TYPE_LONGLONG: - case MYSQL_TYPE_INT24: - case MYSQL_TYPE_YEAR: - if (fields[i].flags & UNSIGNED_FLAG) - r.push_back(std::stoull(row[i])); - else - r.push_back(std::stoll(row[i])); - break; - case MYSQL_TYPE_FLOAT: - r.push_back(std::stof(row[i])); - break; - case MYSQL_TYPE_DOUBLE: - r.push_back(std::stod(row[i])); - break; - case MYSQL_TYPE_BIT: { - uint64_t val = 0; - auto len = fields[i].length; - for (unsigned int j = 0; j < len; j++) { - if (row[i][j] == '1') - val |= (1ULL << j); - } - r.push_back(val); - break; - } - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_VAR_STRING: - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_SET: - case MYSQL_TYPE_VARCHAR: - case MYSQL_TYPE_JSON: - r.push_back(std::string(row[i])); - break; - case MYSQL_TYPE_DECIMAL: - case MYSQL_TYPE_NEWDECIMAL: { - r.push_back(Any()); - // TODO: Decimal - break; - } - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - case MYSQL_TYPE_BLOB: - r.push_back(ByteArray(row[i], row[i] + strlen(row[i]))); - break; - case MYSQL_TYPE_GEOMETRY: - default: - r.push_back(Any()); - break; - } +Session& MySQLSession::query(const std::string& query, std::function callback) { + IF_ENDBG dbLogger.debug("MySQLSession::query: Querying > " + query); + auto res = mysql_query(conn, query.c_str()); + if (res != OK) { + throw std::runtime_error("MySQLSession::query: Failed to query database: " + std::string(mysql_error(conn))); } - if (!callback(r)) { - break; + auto result = mysql_store_result(conn); + if (!result) { + // throw std::runtime_error("MySQLSession::query: Failed to store result: " + // + std::string(mysql_error(conn))); + return *this; // No result set } - } - return *this; + auto numFields = mysql_num_fields(result); + auto numRows = mysql_num_rows(result); + auto fields = mysql_fetch_fields(result); + IF_ENDBG dbLogger.debug("MySQLSession::query: Query returned {} rows and {} fields", numRows, numFields); + // Fetch column names + RowHeader header; + for (unsigned int i = 0; i < numFields; i++) header.add(std::string(fields[i].name, fields[i].name_length)); + // Fetch rows + while (auto row = mysql_fetch_row(result)) { + Row r(header); + for (unsigned int i = 0; i < numFields; i++) { + auto type = fields[i].type; + switch (type) { + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_LONGLONG: + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_YEAR: + if (fields[i].flags & UNSIGNED_FLAG) r.push_back(std::stoull(row[i])); + else r.push_back(std::stoll(row[i])); + break; + case MYSQL_TYPE_FLOAT: + r.push_back(std::stof(row[i])); + break; + case MYSQL_TYPE_DOUBLE: + r.push_back(std::stod(row[i])); + break; + case MYSQL_TYPE_BIT: { + uint64_t val = 0; + auto len = fields[i].length; + for (unsigned int j = 0; j < len; j++) { + if (row[i][j] == '1') val |= (1ULL << j); + } + r.push_back(val); + break; + } + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_SET: + case MYSQL_TYPE_VARCHAR: + case MYSQL_TYPE_JSON: + r.push_back(std::string(row[i])); + break; + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_NEWDECIMAL: { + r.push_back(Any()); + // TODO: Decimal + break; + } + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_BLOB: + r.push_back(ByteArray(row[i], row[i] + strlen(row[i]))); + break; + case MYSQL_TYPE_GEOMETRY: + default: + r.push_back(Any()); + break; + } + } + if (!callback(r)) { + break; + } + } + return *this; } -SharedPointer MySQLSession::prepare(const std::string &query, - bool autoExecute) { - auto stmt = MySQLStmt::create(getOrSetSelf(), query, autoExecute); - stmtPool.push_back(stmt); - return stmt; +SharedPointer MySQLSession::prepare(const std::string& query, bool autoExecute) { + auto stmt = MySQLStmt::create(getOrSetSelf(), query, autoExecute); + stmtPool.push_back(stmt); + return stmt; } -std::string MySQLSession::getLastError() const { - return std::string(mysql_error(conn)); -} +std::string MySQLSession::getLastError() const { return std::string(mysql_error(conn)); } -uint64_t MySQLSession::getAffectedRows() const { - return mysql_affected_rows(conn); -} +uint64_t MySQLSession::getAffectedRows() const { return mysql_affected_rows(conn); } uint64_t MySQLSession::getLastInsertId() const { return mysql_insert_id(conn); } void MySQLSession::close() { - if (conn) { - mysql_close(conn); - conn = nullptr; - IF_ENDBG dbLogger.debug("MySQLSession::close: Closed database"); - } + if (conn) { + mysql_close(conn); + conn = nullptr; + IF_ENDBG dbLogger.debug("MySQLSession::close: Closed database"); + } } bool MySQLSession::isOpen() { return mysql_ping(conn) == OK; } DBType MySQLSession::getType() { return DBType::MySQL; } -SharedPointer MySQLSession::operator<<(const std::string &query) { - return prepare(query, true); -} +SharedPointer MySQLSession::operator<<(const std::string& query) { return prepare(query, true); } } // namespace DB \ No newline at end of file diff --git a/src/legacyapi/db/impl/mysql/Session.h b/src/legacyapi/db/impl/mysql/Session.h index dde788bc..add52e75 100644 --- a/src/legacyapi/db/impl/mysql/Session.h +++ b/src/legacyapi/db/impl/mysql/Session.h @@ -8,32 +8,29 @@ class MySQLStmt; class MySQLSession : public Session { - MYSQL *conn = nullptr; + MYSQL* conn = nullptr; - void setSSL(const ConnParams ¶ms); + void setSSL(const ConnParams& params); public: - MySQLSession(); - MySQLSession(const ConnParams ¶ms); - ~MySQLSession(); - void open(const ConnParams ¶ms); - bool execute(const std::string &query); - bool relogin(const std::string &user, const std::string &password, - const std::string &db = ""); - Session &query(const std::string &query, - std::function callback); - SharedPointer prepare(const std::string &query, - bool autoExecute = false); - std::string getLastError() const; - uint64_t getAffectedRows() const; - uint64_t getLastInsertId() const; - void close(); - bool isOpen(); - DBType getType(); - - SharedPointer operator<<(const std::string &query); - - friend class MySQLStmt; + MySQLSession(); + MySQLSession(const ConnParams& params); + ~MySQLSession(); + void open(const ConnParams& params); + bool execute(const std::string& query); + bool relogin(const std::string& user, const std::string& password, const std::string& db = ""); + Session& query(const std::string& query, std::function callback); + SharedPointer prepare(const std::string& query, bool autoExecute = false); + std::string getLastError() const; + uint64_t getAffectedRows() const; + uint64_t getLastInsertId() const; + void close(); + bool isOpen(); + DBType getType(); + + SharedPointer operator<<(const std::string& query); + + friend class MySQLStmt; }; } // namespace DB \ No newline at end of file diff --git a/src/legacyapi/db/impl/mysql/Stmt.cpp b/src/legacyapi/db/impl/mysql/Stmt.cpp index bde6fdd7..50fec8ec 100644 --- a/src/legacyapi/db/impl/mysql/Stmt.cpp +++ b/src/legacyapi/db/impl/mysql/Stmt.cpp @@ -4,51 +4,52 @@ #include "ll/api/Logger.h" #include "mariadb/mysql.h" -#define Wptr2MySQLSession(x) ((MySQLSession *)x.lock().get()) +#define Wptr2MySQLSession(x) ((MySQLSession*)x.lock().get()) #pragma warning(disable : 4267) #pragma warning(disable : 26812) -template <> MYSQL_TIME any_to(const DB::Any &v) { - switch (v.type) { - case DB::Any::Type::Date: { - MYSQL_TIME t; - t.year = v.value.date->year; - t.month = v.value.date->month; - t.day = v.value.date->day; - t.hour = 0; - t.minute = 0; - t.second = 0; - t.second_part = 0; - t.time_type = MYSQL_TIMESTAMP_DATE; - return t; - } - case DB::Any::Type::Time: { - MYSQL_TIME t; - t.year = 0; - t.month = 0; - t.day = 0; - t.hour = v.value.time->hour; - t.minute = v.value.time->minute; - t.second = v.value.time->second; - t.second_part = 0; - t.time_type = MYSQL_TIMESTAMP_TIME; - return t; - } - case DB::Any::Type::DateTime: { - MYSQL_TIME t; - t.year = v.value.datetime->date.year; - t.month = v.value.datetime->date.month; - t.day = v.value.datetime->date.day; - t.hour = v.value.datetime->time.hour; - t.minute = v.value.datetime->time.minute; - t.second = v.value.datetime->time.second; - t.second_part = 0; - t.time_type = MYSQL_TIMESTAMP_DATETIME; - return t; - } - default: - throw std::bad_cast(); - } +template <> +MYSQL_TIME any_to(const DB::Any& v) { + switch (v.type) { + case DB::Any::Type::Date: { + MYSQL_TIME t; + t.year = v.value.date->year; + t.month = v.value.date->month; + t.day = v.value.date->day; + t.hour = 0; + t.minute = 0; + t.second = 0; + t.second_part = 0; + t.time_type = MYSQL_TIMESTAMP_DATE; + return t; + } + case DB::Any::Type::Time: { + MYSQL_TIME t; + t.year = 0; + t.month = 0; + t.day = 0; + t.hour = v.value.time->hour; + t.minute = v.value.time->minute; + t.second = v.value.time->second; + t.second_part = 0; + t.time_type = MYSQL_TIMESTAMP_TIME; + return t; + } + case DB::Any::Type::DateTime: { + MYSQL_TIME t; + t.year = v.value.datetime->date.year; + t.month = v.value.datetime->date.month; + t.day = v.value.datetime->date.day; + t.hour = v.value.datetime->time.hour; + t.minute = v.value.datetime->time.minute; + t.second = v.value.datetime->time.second; + t.second_part = 0; + t.time_type = MYSQL_TIMESTAMP_DATETIME; + return t; + } + default: + throw std::bad_cast(); + } } namespace DB { @@ -59,52 +60,50 @@ namespace DB { * @param query Query with named parameters * @return std::unordered_map Indexes of parameters */ -std::unordered_map ParseStmtParams(std::string &query) { - StringReader reader(query); - std::unordered_map result; - bool inSingleQuote = false; - bool inDoubleQuote = false; - bool inString = false; - int delta = 0; - int cur = 0; - while (reader.isValid()) { - char c = reader.read(); - if (c == '\'') { - if (!inDoubleQuote) { - inSingleQuote = true; - inString = true; - } else if (inSingleQuote) { - inSingleQuote = false; - inString = false; - } - } else if (c == '"') { - if (!inSingleQuote) { - inDoubleQuote = true; - inString = true; - } else if (inDoubleQuote) { - inDoubleQuote = false; - inString = false; - } - } else if (!inString && (c == '?' || c == '$' || c == ':')) { - query[reader.getPos() - 1 - delta] = '?'; // Replace $ or : with ? - auto name = reader.readVariableName(); // Read parameter name - if (name.empty()) // No parameter name - { - cur++; - continue; - } - if (result.count(name)) { - throw std::runtime_error("ParseStmtParams: Duplicate parameter name: " + - name); - } - result[name] = cur++; - // Remove the name so that mysql can parse it - query = query.substr(0, reader.getPos() - name.length() - delta) + - query.substr(reader.getPos() - delta); - delta += name.size(); // Update delta - } - } - return result; +std::unordered_map ParseStmtParams(std::string& query) { + StringReader reader(query); + std::unordered_map result; + bool inSingleQuote = false; + bool inDoubleQuote = false; + bool inString = false; + int delta = 0; + int cur = 0; + while (reader.isValid()) { + char c = reader.read(); + if (c == '\'') { + if (!inDoubleQuote) { + inSingleQuote = true; + inString = true; + } else if (inSingleQuote) { + inSingleQuote = false; + inString = false; + } + } else if (c == '"') { + if (!inSingleQuote) { + inDoubleQuote = true; + inString = true; + } else if (inDoubleQuote) { + inDoubleQuote = false; + inString = false; + } + } else if (!inString && (c == '?' || c == '$' || c == ':')) { + query[reader.getPos() - 1 - delta] = '?'; // Replace $ or : with ? + auto name = reader.readVariableName(); // Read parameter name + if (name.empty()) // No parameter name + { + cur++; + continue; + } + if (result.count(name)) { + throw std::runtime_error("ParseStmtParams: Duplicate parameter name: " + name); + } + result[name] = cur++; + // Remove the name so that mysql can parse it + query = query.substr(0, reader.getPos() - name.length() - delta) + query.substr(reader.getPos() - delta); + delta += name.size(); // Update delta + } + } + return result; } /** @@ -114,70 +113,68 @@ std::unordered_map ParseStmtParams(std::string &query) { * @return std::pair, std::size_t> Allocated memory and * its size */ -std::pair, std::size_t> -AllocateBuffer(const MYSQL_FIELD &field) { - std::size_t len = 0; - switch (field.type) { - case MYSQL_TYPE_NULL: - return {nullptr, 0}; - case MYSQL_TYPE_TINY: - len = sizeof(char); - break; - case MYSQL_TYPE_SHORT: - len = sizeof(short); - break; - case MYSQL_TYPE_INT24: - case MYSQL_TYPE_LONG: - len = sizeof(int); - break; - case MYSQL_TYPE_BIT: - case MYSQL_TYPE_LONGLONG: - len = sizeof(long long); - break; - case MYSQL_TYPE_FLOAT: - len = sizeof(float); - break; - case MYSQL_TYPE_DOUBLE: - len = sizeof(double); - break; - case MYSQL_TYPE_YEAR: - len = sizeof(short); - break; - case MYSQL_TYPE_TIME: - case MYSQL_TYPE_DATE: - case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_TIMESTAMP: - len = sizeof(MYSQL_TIME); - break; - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_VAR_STRING: - case MYSQL_TYPE_VARCHAR: - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - case MYSQL_TYPE_SET: - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_GEOMETRY: - case MYSQL_TYPE_JSON: - len = field.max_length + 1; - break; - case MYSQL_TYPE_DECIMAL: - case MYSQL_TYPE_NEWDECIMAL: - len = 64; - break; - default: - throw std::runtime_error("AllocateBuffer: Unsupported MySQL data type: " + - std::to_string(field.type)); - } - if (len) { - auto buffer = std::shared_ptr(new char[len]); +std::pair, std::size_t> AllocateBuffer(const MYSQL_FIELD& field) { + std::size_t len = 0; + switch (field.type) { + case MYSQL_TYPE_NULL: + return {nullptr, 0}; + case MYSQL_TYPE_TINY: + len = sizeof(char); + break; + case MYSQL_TYPE_SHORT: + len = sizeof(short); + break; + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_LONG: + len = sizeof(int); + break; + case MYSQL_TYPE_BIT: + case MYSQL_TYPE_LONGLONG: + len = sizeof(long long); + break; + case MYSQL_TYPE_FLOAT: + len = sizeof(float); + break; + case MYSQL_TYPE_DOUBLE: + len = sizeof(double); + break; + case MYSQL_TYPE_YEAR: + len = sizeof(short); + break; + case MYSQL_TYPE_TIME: + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_DATETIME: + case MYSQL_TYPE_TIMESTAMP: + len = sizeof(MYSQL_TIME); + break; + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_VARCHAR: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_SET: + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_GEOMETRY: + case MYSQL_TYPE_JSON: + len = field.max_length + 1; + break; + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_NEWDECIMAL: + len = 64; + break; + default: + throw std::runtime_error("AllocateBuffer: Unsupported MySQL data type: " + std::to_string(field.type)); + } + if (len) { + auto buffer = std::shared_ptr(new char[len]); #if defined(LLDB_DEBUG_MODE) - dbLogger.debug("AllocateBuffer: Allocated! Buffer size: {}", len); + dbLogger.debug("AllocateBuffer: Allocated! Buffer size: {}", len); #endif - return std::make_pair(buffer, len); - } - return std::make_pair(std::shared_ptr(), len); + return std::make_pair(buffer, len); + } + return std::make_pair(std::shared_ptr(), len); } /** @@ -186,9 +183,7 @@ AllocateBuffer(const MYSQL_FIELD &field) { * @param field Field to judge * @return bool True if the field is unsigned */ -bool IsUnsigned(const MYSQL_FIELD &field) { - return field.flags & UNSIGNED_FLAG; -} +bool IsUnsigned(const MYSQL_FIELD& field) { return field.flags & UNSIGNED_FLAG; } /** * @brief Convert Receiver to Any @@ -196,312 +191,290 @@ bool IsUnsigned(const MYSQL_FIELD &field) { * @param receiver Receiver to convert * @return Any Converted value */ -Any ReceiverToAny(const Receiver &rec) { - if (rec.isNull || rec.error) { - return Any(); - } - switch (rec.field.type) { - case MYSQL_TYPE_NULL: - return Any(); - case MYSQL_TYPE_TINY: - if (IsUnsigned(rec.field)) - return *reinterpret_cast(rec.buffer.get()); - return *reinterpret_cast(rec.buffer.get()); - case MYSQL_TYPE_SHORT: - if (IsUnsigned(rec.field)) - return *reinterpret_cast(rec.buffer.get()); - return *reinterpret_cast(rec.buffer.get()); - case MYSQL_TYPE_INT24: - case MYSQL_TYPE_LONG: - if (IsUnsigned(rec.field)) - return *reinterpret_cast(rec.buffer.get()); - return *reinterpret_cast(rec.buffer.get()); - case MYSQL_TYPE_BIT: - return *reinterpret_cast(rec.buffer.get()); - case MYSQL_TYPE_LONGLONG: - if (IsUnsigned(rec.field)) - return *reinterpret_cast(rec.buffer.get()); - return *reinterpret_cast(rec.buffer.get()); - case MYSQL_TYPE_FLOAT: - return *reinterpret_cast(rec.buffer.get()); - case MYSQL_TYPE_DOUBLE: - return *reinterpret_cast(rec.buffer.get()); - case MYSQL_TYPE_YEAR: - return *reinterpret_cast(rec.buffer.get()); - case MYSQL_TYPE_TIME: - case MYSQL_TYPE_DATE: - case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_TIMESTAMP: - return Any(); - break; // TODO: return Any(rec.buffer.get()); - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_VAR_STRING: - case MYSQL_TYPE_VARCHAR: - case MYSQL_TYPE_SET: - case MYSQL_TYPE_ENUM: - // case MYSQL_TYPE_GEOMETRY: - case MYSQL_TYPE_JSON: +Any ReceiverToAny(const Receiver& rec) { + if (rec.isNull || rec.error) { + return Any(); + } + switch (rec.field.type) { + case MYSQL_TYPE_NULL: + return Any(); + case MYSQL_TYPE_TINY: + if (IsUnsigned(rec.field)) return *reinterpret_cast(rec.buffer.get()); + return *reinterpret_cast(rec.buffer.get()); + case MYSQL_TYPE_SHORT: + if (IsUnsigned(rec.field)) return *reinterpret_cast(rec.buffer.get()); + return *reinterpret_cast(rec.buffer.get()); + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_LONG: + if (IsUnsigned(rec.field)) return *reinterpret_cast(rec.buffer.get()); + return *reinterpret_cast(rec.buffer.get()); + case MYSQL_TYPE_BIT: + return *reinterpret_cast(rec.buffer.get()); + case MYSQL_TYPE_LONGLONG: + if (IsUnsigned(rec.field)) return *reinterpret_cast(rec.buffer.get()); + return *reinterpret_cast(rec.buffer.get()); + case MYSQL_TYPE_FLOAT: + return *reinterpret_cast(rec.buffer.get()); + case MYSQL_TYPE_DOUBLE: + return *reinterpret_cast(rec.buffer.get()); + case MYSQL_TYPE_YEAR: + return *reinterpret_cast(rec.buffer.get()); + case MYSQL_TYPE_TIME: + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_DATETIME: + case MYSQL_TYPE_TIMESTAMP: + return Any(); + break; // TODO: return Any(rec.buffer.get()); + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_VARCHAR: + case MYSQL_TYPE_SET: + case MYSQL_TYPE_ENUM: + // case MYSQL_TYPE_GEOMETRY: + case MYSQL_TYPE_JSON: #if defined(LLDB_DEBUG_MODE) - dbLogger.debug("ReceiverToAny: string: length: {}, buffer {}", rec.length, - rec.buffer.get()); + dbLogger.debug("ReceiverToAny: string: length: {}, buffer {}", rec.length, rec.buffer.get()); #endif - return Any(std::string(rec.buffer.get())); - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: + return Any(std::string(rec.buffer.get())); + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: #if defined(LLDB_DEBUG_MODE) - dbLogger.debug("ReceiverToAny: blob: length: {}, buffer {}", rec.length, - rec.buffer.get()); + dbLogger.debug("ReceiverToAny: blob: length: {}, buffer {}", rec.length, rec.buffer.get()); #endif - // Unknown bug: rec.length is 0 - return Any(ByteArray(rec.buffer.get(), rec.buffer.get() + rec.length)); - case MYSQL_TYPE_DECIMAL: - case MYSQL_TYPE_NEWDECIMAL: - // TODO: Decimal - dbLogger.debug("MySQL_Decimal: {}", - std::string(rec.buffer.get(), rec.length)); - return Any(); - default: - throw std::runtime_error("ReceiverToAny: Unsupported MySQL data type: " + - std::to_string(rec.field.type)); - } + // Unknown bug: rec.length is 0 + return Any(ByteArray(rec.buffer.get(), rec.buffer.get() + rec.length)); + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_NEWDECIMAL: + // TODO: Decimal + dbLogger.debug("MySQL_Decimal: {}", std::string(rec.buffer.get(), rec.length)); + return Any(); + default: + throw std::runtime_error("ReceiverToAny: Unsupported MySQL data type: " + std::to_string(rec.field.type)); + } } -MySQLStmt::MySQLStmt(MYSQL_STMT *stmt, const std::weak_ptr &parent, - bool autoExecute) - : Stmt(parent, autoExecute), stmt(stmt) { - this->parent = parent; - totalParamsCount = mysql_stmt_param_count(stmt); - if (totalParamsCount) - params.reset(new MYSQL_BIND[totalParamsCount]); - else { - if (autoExecute) - execute(); // Execute without params - } +MySQLStmt::MySQLStmt(MYSQL_STMT* stmt, const std::weak_ptr& parent, bool autoExecute) +: Stmt(parent, autoExecute), + stmt(stmt) { + this->parent = parent; + totalParamsCount = mysql_stmt_param_count(stmt); + if (totalParamsCount) params.reset(new MYSQL_BIND[totalParamsCount]); + else { + if (autoExecute) execute(); // Execute without params + } } int MySQLStmt::getNextParamIndex() { - int result = -1; - // Find the first unbound parameter - for (int i = 0; i < boundIndexes.size() && i < totalParamsCount; i++) { - if (boundIndexes[i] == result + 1) { - result++; - } - } - IF_ENDBG dbLogger.debug( - "MySQLStmt::getNextParamIndex: The next param index is {}", result + 1); - return result + 1; + int result = -1; + // Find the first unbound parameter + for (int i = 0; i < boundIndexes.size() && i < totalParamsCount; i++) { + if (boundIndexes[i] == result + 1) { + result++; + } + } + IF_ENDBG dbLogger.debug("MySQLStmt::getNextParamIndex: The next param index is {}", result + 1); + return result + 1; } void MySQLStmt::bindResult() { - metadata = mysql_stmt_result_metadata(stmt); // Get the result metadata - if (mysql_stmt_errno(stmt) && !metadata) { - throw std::runtime_error( - "MySQLStmt::bindResult: Failed to get result metadata" + - std::string(mysql_stmt_error(stmt))); - } - if (!metadata) { - IF_ENDBG dbLogger.debug("MySQLStmt::bindResult: No result metadata"); - return; - } - // Set the attribute UPDATE_MAX_LENGTH to true - // so that we can get the max length of the field to allocate the buffer - bool attr_max_length = true; - mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, - (const void *)&attr_max_length); - // Store all the results to client or we can't get the max length of the field - // later - mysql_stmt_store_result(stmt); - auto cnt = mysql_num_fields(metadata); - IF_ENDBG dbLogger.debug("MySQLStmt::bindResult: mysql_num_fields: {}", cnt); - auto fields = mysql_fetch_fields(metadata); - result.reset(new MYSQL_BIND[cnt]); // Allocate result bindings - resultHeader.reset(new RowHeader); // Allocate result header - for (auto i = 0U; i < cnt; i++) { - resultValues.push_back({}); // Allocate result values - auto &rec = resultValues.back(); // Get the binder - auto &field = fields[i]; - auto &data = result[i]; - - data.buffer_type = field.type; // Set the type - data.is_null = &rec.isNull; // Set the isNull receiver - data.is_unsigned = field.flags & UNSIGNED_FLAG; - data.error = &rec.error; // Set the error receiver - data.length = &rec.length; // Set the length receiver - - auto &&[buffer, len] = AllocateBuffer(field); // Allocate buffer - rec.buffer = buffer; // Extend lifetime - data.buffer_length = (unsigned long)len; // Set the buffer length - data.buffer = rec.buffer.get(); // Set the buffer address - - rec.field = field; // Save the field - resultHeader->add(field.name); // Add the field name to the header - IF_ENDBG dbLogger.debug( - "MySQLStmt::bindResult: Bind result {} (type {}) at index {}", - field.name, (int)field.type, i); - } - auto res = mysql_stmt_bind_result(stmt, result.get()); - if (res) { - throw std::runtime_error("MySQLStmt::bindResult: Failed to bind result: " + - std::string(mysql_stmt_error(stmt))); - } + metadata = mysql_stmt_result_metadata(stmt); // Get the result metadata + if (mysql_stmt_errno(stmt) && !metadata) { + throw std::runtime_error( + "MySQLStmt::bindResult: Failed to get result metadata" + std::string(mysql_stmt_error(stmt)) + ); + } + if (!metadata) { + IF_ENDBG dbLogger.debug("MySQLStmt::bindResult: No result metadata"); + return; + } + // Set the attribute UPDATE_MAX_LENGTH to true + // so that we can get the max length of the field to allocate the buffer + bool attr_max_length = true; + mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (const void*)&attr_max_length); + // Store all the results to client or we can't get the max length of the field + // later + mysql_stmt_store_result(stmt); + auto cnt = mysql_num_fields(metadata); + IF_ENDBG dbLogger.debug("MySQLStmt::bindResult: mysql_num_fields: {}", cnt); + auto fields = mysql_fetch_fields(metadata); + result.reset(new MYSQL_BIND[cnt]); // Allocate result bindings + resultHeader.reset(new RowHeader); // Allocate result header + for (auto i = 0U; i < cnt; i++) { + resultValues.push_back({}); // Allocate result values + auto& rec = resultValues.back(); // Get the binder + auto& field = fields[i]; + auto& data = result[i]; + + data.buffer_type = field.type; // Set the type + data.is_null = &rec.isNull; // Set the isNull receiver + data.is_unsigned = field.flags & UNSIGNED_FLAG; + data.error = &rec.error; // Set the error receiver + data.length = &rec.length; // Set the length receiver + + auto&& [buffer, len] = AllocateBuffer(field); // Allocate buffer + rec.buffer = buffer; // Extend lifetime + data.buffer_length = (unsigned long)len; // Set the buffer length + data.buffer = rec.buffer.get(); // Set the buffer address + + rec.field = field; // Save the field + resultHeader->add(field.name); // Add the field name to the header + IF_ENDBG dbLogger + .debug("MySQLStmt::bindResult: Bind result {} (type {}) at index {}", field.name, (int)field.type, i); + } + auto res = mysql_stmt_bind_result(stmt, result.get()); + if (res) { + throw std::runtime_error( + "MySQLStmt::bindResult: Failed to bind result: " + std::string(mysql_stmt_error(stmt)) + ); + } } MySQLStmt::~MySQLStmt() { close(); } -Stmt &MySQLStmt::bind(const Any &value, int index) { - if (index < 0 || index > totalParamsCount) { - throw std::invalid_argument("MySQLStmt::bind: Invalid argument `index`"); - } - if (getUnboundParams() == 0) { - throw std::runtime_error( - "MySQLStmt::bind: All the parameters are already bound"); - } - paramValues.push_back({}); // Save the value or it will be lost - auto ¶m = paramValues.back(); - switch (value.type) { - case Any::Type::Null: - params[index].buffer_type = MYSQL_TYPE_NULL; - break; - case Any::Type::Boolean: - params[index].buffer_type = MYSQL_TYPE_TINY; - param.buffer.reset(new char[1]); - param.buffer[0] = value.value.boolean; - params[index].buffer = param.buffer.get(); - params[index].buffer_length = 1; - params[index].is_unsigned = true; - break; - case Any::Type::Integer: - params[index].buffer_type = MYSQL_TYPE_LONGLONG; - param.buffer.reset(new char[sizeof(int64_t)]); - *reinterpret_cast(param.buffer.get()) = value.value.integer; - params[index].buffer = param.buffer.get(); - params[index].buffer_length = sizeof(int64_t); - params[index].is_unsigned = false; - params[index].is_null = 0; - params[index].length = 0; - break; - case Any::Type::UInteger: - params[index].buffer_type = MYSQL_TYPE_LONGLONG; - param.buffer.reset(new char[sizeof(uint64_t)]); - *reinterpret_cast(param.buffer.get()) = value.value.uinteger; - params[index].buffer = param.buffer.get(); - params[index].buffer_length = sizeof(uint64_t); - params[index].is_unsigned = true; - params[index].is_null = 0; - params[index].length = 0; - break; - case Any::Type::Floating: - params[index].buffer_type = MYSQL_TYPE_DOUBLE; - param.buffer.reset(new char[sizeof(double)]); - *reinterpret_cast(param.buffer.get()) = value.value.floating; - params[index].buffer = param.buffer.get(); - params[index].buffer_length = sizeof(double); - params[index].is_unsigned = false; - params[index].is_null = 0; - params[index].length = 0; - break; - case Any::Type::String: { - params[index].buffer_type = MYSQL_TYPE_STRING; - auto sz = value.value.string->length(); // Don't +1 here!!! - param.buffer.reset(new char[sz]); - memcpy(param.buffer.get(), value.value.string->data(), sz); // No '\0' - param.length = sz; // Must set the length to the buffer size, otherwise it - // will be truncated - params[index].buffer = param.buffer.get(); - params[index].buffer_length = sz; - params[index].is_null = 0; - params[index].length = (unsigned long *)¶m.length; - IF_ENDBG dbLogger.debug("MySQLStmt::bind: Bound string param at {}: {}", - index, param.buffer.get()); - break; - } - case Any::Type::Date: - case Any::Type::Time: - case Any::Type::DateTime: { - params[index].buffer_type = MYSQL_TYPE_TIME; - auto tm = value.get(); - param.buffer.reset(new char[sizeof(MYSQL_TIME)]); - *reinterpret_cast(param.buffer.get()) = tm; - params[index].buffer = param.buffer.get(); - params[index].buffer_length = sizeof(MYSQL_TIME); - params[index].is_null = 0; - params[index].length = 0; - break; - } - case Any::Type::Blob: { - params[index].buffer_type = MYSQL_TYPE_BLOB; - auto blob = value.get(); - auto sz = blob.size(); - param.buffer.reset(new char[sz]); - memcpy(param.buffer.get(), blob.data(), sz); - param.length = sz; // Must set the length to the buffer size, otherwise it - // will be truncated - params[index].buffer = param.buffer.get(); - params[index].buffer_length = sz; - params[index].is_null = 0; - params[index].length = (unsigned long *)¶m.length; - break; - } - default: - throw std::runtime_error("MySQLStmt::bind: Unsupported type"); - } - boundIndexes.push_back(index); - boundParamsCount++; - if (getUnboundParams() == 0) { - auto res = mysql_stmt_bind_param(stmt, params.get()); - if (res) { - throw std::runtime_error("MySQLStmt::bind: " + - std::string(mysql_stmt_error(stmt))); +Stmt& MySQLStmt::bind(const Any& value, int index) { + if (index < 0 || index > totalParamsCount) { + throw std::invalid_argument("MySQLStmt::bind: Invalid argument `index`"); + } + if (getUnboundParams() == 0) { + throw std::runtime_error("MySQLStmt::bind: All the parameters are already bound"); + } + paramValues.push_back({}); // Save the value or it will be lost + auto& param = paramValues.back(); + switch (value.type) { + case Any::Type::Null: + params[index].buffer_type = MYSQL_TYPE_NULL; + break; + case Any::Type::Boolean: + params[index].buffer_type = MYSQL_TYPE_TINY; + param.buffer.reset(new char[1]); + param.buffer[0] = value.value.boolean; + params[index].buffer = param.buffer.get(); + params[index].buffer_length = 1; + params[index].is_unsigned = true; + break; + case Any::Type::Integer: + params[index].buffer_type = MYSQL_TYPE_LONGLONG; + param.buffer.reset(new char[sizeof(int64_t)]); + *reinterpret_cast(param.buffer.get()) = value.value.integer; + params[index].buffer = param.buffer.get(); + params[index].buffer_length = sizeof(int64_t); + params[index].is_unsigned = false; + params[index].is_null = 0; + params[index].length = 0; + break; + case Any::Type::UInteger: + params[index].buffer_type = MYSQL_TYPE_LONGLONG; + param.buffer.reset(new char[sizeof(uint64_t)]); + *reinterpret_cast(param.buffer.get()) = value.value.uinteger; + params[index].buffer = param.buffer.get(); + params[index].buffer_length = sizeof(uint64_t); + params[index].is_unsigned = true; + params[index].is_null = 0; + params[index].length = 0; + break; + case Any::Type::Floating: + params[index].buffer_type = MYSQL_TYPE_DOUBLE; + param.buffer.reset(new char[sizeof(double)]); + *reinterpret_cast(param.buffer.get()) = value.value.floating; + params[index].buffer = param.buffer.get(); + params[index].buffer_length = sizeof(double); + params[index].is_unsigned = false; + params[index].is_null = 0; + params[index].length = 0; + break; + case Any::Type::String: { + params[index].buffer_type = MYSQL_TYPE_STRING; + auto sz = value.value.string->length(); // Don't +1 here!!! + param.buffer.reset(new char[sz]); + memcpy(param.buffer.get(), value.value.string->data(), sz); // No '\0' + param.length = sz; // Must set the length to the buffer size, otherwise it + // will be truncated + params[index].buffer = param.buffer.get(); + params[index].buffer_length = sz; + params[index].is_null = 0; + params[index].length = (unsigned long*)¶m.length; + IF_ENDBG dbLogger.debug("MySQLStmt::bind: Bound string param at {}: {}", index, param.buffer.get()); + break; + } + case Any::Type::Date: + case Any::Type::Time: + case Any::Type::DateTime: { + params[index].buffer_type = MYSQL_TYPE_TIME; + auto tm = value.get(); + param.buffer.reset(new char[sizeof(MYSQL_TIME)]); + *reinterpret_cast(param.buffer.get()) = tm; + params[index].buffer = param.buffer.get(); + params[index].buffer_length = sizeof(MYSQL_TIME); + params[index].is_null = 0; + params[index].length = 0; + break; } - if (autoExecute) - execute(); - } - return *this; + case Any::Type::Blob: { + params[index].buffer_type = MYSQL_TYPE_BLOB; + auto blob = value.get(); + auto sz = blob.size(); + param.buffer.reset(new char[sz]); + memcpy(param.buffer.get(), blob.data(), sz); + param.length = sz; // Must set the length to the buffer size, otherwise it + // will be truncated + params[index].buffer = param.buffer.get(); + params[index].buffer_length = sz; + params[index].is_null = 0; + params[index].length = (unsigned long*)¶m.length; + break; + } + default: + throw std::runtime_error("MySQLStmt::bind: Unsupported type"); + } + boundIndexes.push_back(index); + boundParamsCount++; + if (getUnboundParams() == 0) { + auto res = mysql_stmt_bind_param(stmt, params.get()); + if (res) { + throw std::runtime_error("MySQLStmt::bind: " + std::string(mysql_stmt_error(stmt))); + } + if (autoExecute) execute(); + } + return *this; } -Stmt &MySQLStmt::bind(const Any &value, const std::string &name) { - if (!paramIndexes.count(name)) { - throw std::invalid_argument("MySQLStmt::bind: Parameter name `" + name + - "` not found"); - } - return bind(value, paramIndexes[name]); +Stmt& MySQLStmt::bind(const Any& value, const std::string& name) { + if (!paramIndexes.count(name)) { + throw std::invalid_argument("MySQLStmt::bind: Parameter name `" + name + "` not found"); + } + return bind(value, paramIndexes[name]); } -Stmt &MySQLStmt::bind(const Any &value) { - return bind(value, getNextParamIndex()); -} +Stmt& MySQLStmt::bind(const Any& value) { return bind(value, getNextParamIndex()); } -Stmt &MySQLStmt::execute() { - auto res = mysql_stmt_execute(stmt); // Execute - if (res) { - if (!parent.expired()) - mysql_rollback(Wptr2MySQLSession(parent)->conn); // Rollback - throw std::runtime_error("MySQLStmt::execute: Failed to execute stmt: " + - std::string(mysql_stmt_error(stmt))); - } - mysql_commit(Wptr2MySQLSession(parent)->conn); // Commit - bindResult(); - if (metadata) // If the statement has result - step(); // Step to the first result - paramValues = {}; - return *this; +Stmt& MySQLStmt::execute() { + auto res = mysql_stmt_execute(stmt); // Execute + if (res) { + if (!parent.expired()) mysql_rollback(Wptr2MySQLSession(parent)->conn); // Rollback + throw std::runtime_error("MySQLStmt::execute: Failed to execute stmt: " + std::string(mysql_stmt_error(stmt))); + } + mysql_commit(Wptr2MySQLSession(parent)->conn); // Commit + bindResult(); + if (metadata) // If the statement has result + step(); // Step to the first result + paramValues = {}; + return *this; } bool MySQLStmt::step() { - auto res = mysql_stmt_fetch(stmt); - if (res == MYSQL_NO_DATA) { - fetched = true; - return false; - } else if (res == MYSQL_DATA_TRUNCATED) { - throw std::runtime_error("MySQLStmt::step: Data truncated!"); - } else if (res) { - throw std::runtime_error( - fmt::format("MySQLStmt::step: {}", mysql_stmt_error(stmt))); - } - ++steps; - return true; + auto res = mysql_stmt_fetch(stmt); + if (res == MYSQL_NO_DATA) { + fetched = true; + return false; + } else if (res == MYSQL_DATA_TRUNCATED) { + throw std::runtime_error("MySQLStmt::step: Data truncated!"); + } else if (res) { + throw std::runtime_error(fmt::format("MySQLStmt::step: {}", mysql_stmt_error(stmt))); + } + ++steps; + return true; } bool MySQLStmt::next() { return step(); } @@ -509,93 +482,90 @@ bool MySQLStmt::next() { return step(); } bool MySQLStmt::done() { return fetched; } Row MySQLStmt::_Fetch() { - // TODO: execute check - if (fetched) { - throw std::runtime_error("MySQLStmt::_Fetch: No more rows"); - } - IF_ENDBG dbLogger.debug("MySQLStmt::_Fetch: Fetching row..."); - Row row(resultHeader); - IF_ENDBG dbLogger.debug("MySQLStmt::_Fetch: RowHeader size {}", - row.header->size()); - int i = 0; - for (auto &col : resultValues) { - // Because of the inexplicable problems of MySQL C API, - // we must set the length of the field manually. - auto length = *(stmt->bind + i)->length; - col.length = length; - auto v = ReceiverToAny(col); - row.push_back(v); - IF_ENDBG dbLogger.debug( - "MySQLStmt::_Fetch: Fetched column `{}`, type {}, value {}", - col.field.name, Any::type2str(v.type), v.get()); - i++; - } - return row; + // TODO: execute check + if (fetched) { + throw std::runtime_error("MySQLStmt::_Fetch: No more rows"); + } + IF_ENDBG dbLogger.debug("MySQLStmt::_Fetch: Fetching row..."); + Row row(resultHeader); + IF_ENDBG dbLogger.debug("MySQLStmt::_Fetch: RowHeader size {}", row.header->size()); + int i = 0; + for (auto& col : resultValues) { + // Because of the inexplicable problems of MySQL C API, + // we must set the length of the field manually. + auto length = *(stmt->bind + i)->length; + col.length = length; + auto v = ReceiverToAny(col); + row.push_back(v); + IF_ENDBG dbLogger.debug( + "MySQLStmt::_Fetch: Fetched column `{}`, type {}, value {}", + col.field.name, + Any::type2str(v.type), + v.get() + ); + i++; + } + return row; } -Stmt &MySQLStmt::reset() { - if (mysql_stmt_reset(stmt)) { - throw std::runtime_error("MySQLStmt::reset: " + - std::string(mysql_stmt_error(stmt))); - } - result.reset(); - resultHeader.reset(); - resultValues = {}; - steps = 0; - fetched = false; - return *this; +Stmt& MySQLStmt::reset() { + if (mysql_stmt_reset(stmt)) { + throw std::runtime_error("MySQLStmt::reset: " + std::string(mysql_stmt_error(stmt))); + } + result.reset(); + resultHeader.reset(); + resultValues = {}; + steps = 0; + fetched = false; + return *this; } -Stmt &MySQLStmt::reexec() { - reset(); - execute(); - return *this; +Stmt& MySQLStmt::reexec() { + reset(); + execute(); + return *this; } -Stmt &MySQLStmt::clear() { - if (query.empty()) { - throw std::runtime_error("MySQLStmt::clear: No query"); - } - close(); - *this = *(MySQLStmt *)create(parent, query).get(); - return *this; +Stmt& MySQLStmt::clear() { + if (query.empty()) { + throw std::runtime_error("MySQLStmt::clear: No query"); + } + close(); + *this = *(MySQLStmt*)create(parent, query).get(); + return *this; } void MySQLStmt::close() { - if (metadata) { - mysql_free_result(metadata); - metadata = nullptr; - } - if (stmt) { - // CRASH!? - // I(Jasonzyt) had no idea how to fix it, so I just disabled it - // idk if it will cause any problem like memory leak but it's better than - // crash lol - // mysql_stmt_close(stmt); - // stmt = nullptr; - } - params.reset(); - result.reset(); - resultHeader.reset(); - totalParamsCount = 0; - boundParamsCount = 0; - paramValues = {}; - resultValues = {}; - paramIndexes = {}; - boundIndexes = {}; - steps = 0; - fetched = false; + if (metadata) { + mysql_free_result(metadata); + metadata = nullptr; + } + if (stmt) { + // CRASH!? + // I(Jasonzyt) had no idea how to fix it, so I just disabled it + // idk if it will cause any problem like memory leak but it's better than + // crash lol + // mysql_stmt_close(stmt); + // stmt = nullptr; + } + params.reset(); + result.reset(); + resultHeader.reset(); + totalParamsCount = 0; + boundParamsCount = 0; + paramValues = {}; + resultValues = {}; + paramIndexes = {}; + boundIndexes = {}; + steps = 0; + fetched = false; } -uint64_t MySQLStmt::getAffectedRows() const { - return mysql_stmt_affected_rows(stmt); -} +uint64_t MySQLStmt::getAffectedRows() const { return mysql_stmt_affected_rows(stmt); } uint64_t MySQLStmt::getInsertId() const { return mysql_stmt_insert_id(stmt); } -int MySQLStmt::getUnboundParams() const { - return totalParamsCount - boundParamsCount; -} +int MySQLStmt::getUnboundParams() const { return totalParamsCount - boundParamsCount; } int MySQLStmt::getBoundParams() const { return boundParamsCount; } @@ -603,42 +573,37 @@ int MySQLStmt::getParamsCount() const { return totalParamsCount; } DBType MySQLStmt::getType() const { return DBType::MySQL; } -SharedPointer MySQLStmt::create(const std::weak_ptr &session, - const std::string &sql, - bool autoExecute) { - auto s = session.lock(); - if (!s || s->getType() != DBType::MySQL) { - throw std::invalid_argument("MySQLStmt::create: Session is invalid"); - } - auto raw = (MySQLSession *)s.get(); - auto stmt = mysql_stmt_init(raw->conn); - if (!stmt) { - throw std::runtime_error("MySQLStmt::create: " + s->getLastError()); - } - auto query = sql; - auto params = ParseStmtParams(query); - if (raw->debugOutput && !params.empty()) { - dbLogger.debug("MySQLStmt::create: Parsed named parameters in query: "); - dbLogger.debug("MySQLStmt::create: - SQL without named parameters: {}", - query); - for (auto &[k, v] : params) { - dbLogger.debug("MySQLStmt::create: - {}: {}", k, v); - } - } - auto res = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - if (res) { - throw std::runtime_error("MySQLStmt::create: " + - std::string(mysql_stmt_error(stmt))); - } - auto result = new MySQLStmt(stmt, session, autoExecute); - result->query = sql; - result->paramIndexes = params; - result->setDebugOutput(raw->debugOutput); - if (raw->debugOutput) - dbLogger.debug("MySQLStmt::create: Prepared > " + query); - auto shared = SharedPointer(result); - result->self = shared; - return shared; +SharedPointer MySQLStmt::create(const std::weak_ptr& session, const std::string& sql, bool autoExecute) { + auto s = session.lock(); + if (!s || s->getType() != DBType::MySQL) { + throw std::invalid_argument("MySQLStmt::create: Session is invalid"); + } + auto raw = (MySQLSession*)s.get(); + auto stmt = mysql_stmt_init(raw->conn); + if (!stmt) { + throw std::runtime_error("MySQLStmt::create: " + s->getLastError()); + } + auto query = sql; + auto params = ParseStmtParams(query); + if (raw->debugOutput && !params.empty()) { + dbLogger.debug("MySQLStmt::create: Parsed named parameters in query: "); + dbLogger.debug("MySQLStmt::create: - SQL without named parameters: {}", query); + for (auto& [k, v] : params) { + dbLogger.debug("MySQLStmt::create: - {}: {}", k, v); + } + } + auto res = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + if (res) { + throw std::runtime_error("MySQLStmt::create: " + std::string(mysql_stmt_error(stmt))); + } + auto result = new MySQLStmt(stmt, session, autoExecute); + result->query = sql; + result->paramIndexes = params; + result->setDebugOutput(raw->debugOutput); + if (raw->debugOutput) dbLogger.debug("MySQLStmt::create: Prepared > " + query); + auto shared = SharedPointer(result); + result->self = shared; + return shared; } } // namespace DB diff --git a/src/legacyapi/db/impl/mysql/Stmt.h b/src/legacyapi/db/impl/mysql/Stmt.h index 4f5e3d7c..2e3b7839 100644 --- a/src/legacyapi/db/impl/mysql/Stmt.h +++ b/src/legacyapi/db/impl/mysql/Stmt.h @@ -7,60 +7,58 @@ namespace DB { class MySQLSession; struct Receiver { - MYSQL_FIELD field; - std::shared_ptr buffer; - unsigned long length = 0; - my_bool isNull = false; - bool isUnsigned = false; - my_bool error = false; + MYSQL_FIELD field; + std::shared_ptr buffer; + unsigned long length = 0; + my_bool isNull = false; + bool isUnsigned = false; + my_bool error = false; }; class MySQLStmt : public Stmt { - MYSQL_STMT *stmt = nullptr; - MYSQL_RES *metadata = nullptr; - std::shared_ptr params = nullptr; ///< Parameters to bind - std::shared_ptr result = nullptr; ///< Result of query - std::shared_ptr resultHeader = nullptr; - std::vector boundIndexes; - std::vector paramValues; - std::vector resultValues; - std::unordered_map paramIndexes; - std::string query; - int boundParamsCount = 0; - int totalParamsCount = 0; - int steps = 0; - bool fetched = false; + MYSQL_STMT* stmt = nullptr; + MYSQL_RES* metadata = nullptr; + std::shared_ptr params = nullptr; ///< Parameters to bind + std::shared_ptr result = nullptr; ///< Result of query + std::shared_ptr resultHeader = nullptr; + std::vector boundIndexes; + std::vector paramValues; + std::vector resultValues; + std::unordered_map paramIndexes; + std::string query; + int boundParamsCount = 0; + int totalParamsCount = 0; + int steps = 0; + bool fetched = false; - MySQLStmt(MYSQL_STMT *stmt, const std::weak_ptr &parent, - bool autoExecute = false); - int getNextParamIndex(); - void bindResult(); + MySQLStmt(MYSQL_STMT* stmt, const std::weak_ptr& parent, bool autoExecute = false); + int getNextParamIndex(); + void bindResult(); public: - ~MySQLStmt(); - Stmt &bind(const Any &value, int index); - Stmt &bind(const Any &value, const std::string &name); - Stmt &bind(const Any &value); - Stmt &execute(); - bool step(); - bool next(); - bool done(); - Row _Fetch(); - Stmt &reset(); - Stmt &reexec(); - Stmt &clear(); - void close(); - uint64_t getAffectedRows() const; - uint64_t getInsertId() const; - int getUnboundParams() const; - int getBoundParams() const; - int getParamsCount() const; - DBType getType() const; + ~MySQLStmt(); + Stmt& bind(const Any& value, int index); + Stmt& bind(const Any& value, const std::string& name); + Stmt& bind(const Any& value); + Stmt& execute(); + bool step(); + bool next(); + bool done(); + Row _Fetch(); + Stmt& reset(); + Stmt& reexec(); + Stmt& clear(); + void close(); + uint64_t getAffectedRows() const; + uint64_t getInsertId() const; + int getUnboundParams() const; + int getBoundParams() const; + int getParamsCount() const; + DBType getType() const; - static SharedPointer create(const std::weak_ptr &sess, - const std::string &sql, - bool autoExecute = false); + static SharedPointer + create(const std::weak_ptr& sess, const std::string& sql, bool autoExecute = false); }; } // namespace DB \ No newline at end of file diff --git a/src/legacyapi/db/impl/sqlite/Session.cpp b/src/legacyapi/db/impl/sqlite/Session.cpp index 61f119a0..1b7cfbf1 100644 --- a/src/legacyapi/db/impl/sqlite/Session.cpp +++ b/src/legacyapi/db/impl/sqlite/Session.cpp @@ -4,134 +4,115 @@ namespace DB { -SQLiteSession::SQLiteSession() { - IF_ENDBG dbLogger.debug("SQLiteSession: Constructed! this: {}", (void *)this); -} -SQLiteSession::SQLiteSession(const ConnParams ¶ms) { - IF_ENDBG dbLogger.debug("SQLiteSession: Constructed! this: {}", (void *)this); - open(params); +SQLiteSession::SQLiteSession() { IF_ENDBG dbLogger.debug("SQLiteSession: Constructed! this: {}", (void*)this); } +SQLiteSession::SQLiteSession(const ConnParams& params) { + IF_ENDBG dbLogger.debug("SQLiteSession: Constructed! this: {}", (void*)this); + open(params); } SQLiteSession::~SQLiteSession() { - IF_ENDBG dbLogger.debug("SQLiteSession::~SQLiteSession: Destructor: this: {}", - (void *)this); - close(); + IF_ENDBG dbLogger.debug("SQLiteSession::~SQLiteSession: Destructor: this: {}", (void*)this); + close(); } -void SQLiteSession::open(const ConnParams ¶ms) { - // see https://www.sqlite.org/c3ref/open.html - auto p = params; // Copy to avoid modifying the origin. - auto path = p.getPath(); - if (path.empty()) { - path = ":memory:"; - // throw std::invalid_argument("SQLiteSession::SQLiteSession: No path - // specified!"); - } - auto flags = 0; - if (p.get({"create", "create_if_not_exist", "createifnotexist"}, true, - false)) { - flags |= SQLITE_OPEN_CREATE; - } - if (p.get({"readonly", "readonly_mode", "readonlymode", "r"}, false, - false)) { - flags |= SQLITE_OPEN_READONLY; - } - if (p.get( - {"readwrite", "readwrite_mode", "readwritemode", "read_write", "rw"}, - false, false)) { - flags |= SQLITE_OPEN_READWRITE; - } - if (p.get({"privatecache", "private_cache"}, false, false)) { - flags |= SQLITE_OPEN_PRIVATECACHE; - } - if (p.get({"sharedcache", "shared_cache"}, false, false)) { - flags |= SQLITE_OPEN_SHAREDCACHE; - } - if (p.get({"nomutex", "no_mutex"}, false, false)) { - flags |= SQLITE_OPEN_NOMUTEX; - } - if (p.get({"fullmutex", "full_mutex"}, false, false)) { - flags |= SQLITE_OPEN_FULLMUTEX; - } - if (p.get({"nofollow", "no_follow"}, false, false)) { - flags |= SQLITE_OPEN_NOFOLLOW; - } - if (!params.count("readonly") && !params.count("readwrite")) { - flags |= SQLITE_OPEN_READWRITE; - } - if (!params.count("create")) { - flags |= SQLITE_OPEN_CREATE; - } - auto res = sqlite3_open_v2(path.c_str(), &conn, flags, nullptr); - if (res != SQLITE_OK) { - throw std::runtime_error("SQLiteSession::open: Failed to open database: " + - std::string(sqlite3_errmsg(conn))); - } - IF_ENDBG dbLogger.debug("SQLiteSession::open: Opened database: " + - std::string(path)); +void SQLiteSession::open(const ConnParams& params) { + // see https://www.sqlite.org/c3ref/open.html + auto p = params; // Copy to avoid modifying the origin. + auto path = p.getPath(); + if (path.empty()) { + path = ":memory:"; + // throw std::invalid_argument("SQLiteSession::SQLiteSession: No path + // specified!"); + } + auto flags = 0; + if (p.get({"create", "create_if_not_exist", "createifnotexist"}, true, false)) { + flags |= SQLITE_OPEN_CREATE; + } + if (p.get({"readonly", "readonly_mode", "readonlymode", "r"}, false, false)) { + flags |= SQLITE_OPEN_READONLY; + } + if (p.get({"readwrite", "readwrite_mode", "readwritemode", "read_write", "rw"}, false, false)) { + flags |= SQLITE_OPEN_READWRITE; + } + if (p.get({"privatecache", "private_cache"}, false, false)) { + flags |= SQLITE_OPEN_PRIVATECACHE; + } + if (p.get({"sharedcache", "shared_cache"}, false, false)) { + flags |= SQLITE_OPEN_SHAREDCACHE; + } + if (p.get({"nomutex", "no_mutex"}, false, false)) { + flags |= SQLITE_OPEN_NOMUTEX; + } + if (p.get({"fullmutex", "full_mutex"}, false, false)) { + flags |= SQLITE_OPEN_FULLMUTEX; + } + if (p.get({"nofollow", "no_follow"}, false, false)) { + flags |= SQLITE_OPEN_NOFOLLOW; + } + if (!params.count("readonly") && !params.count("readwrite")) { + flags |= SQLITE_OPEN_READWRITE; + } + if (!params.count("create")) { + flags |= SQLITE_OPEN_CREATE; + } + auto res = sqlite3_open_v2(path.c_str(), &conn, flags, nullptr); + if (res != SQLITE_OK) { + throw std::runtime_error("SQLiteSession::open: Failed to open database: " + std::string(sqlite3_errmsg(conn))); + } + IF_ENDBG dbLogger.debug("SQLiteSession::open: Opened database: " + std::string(path)); } -bool SQLiteSession::execute(const std::string &query) { - IF_ENDBG dbLogger.debug("SQLiteSession::execute: Executing > " + query); - auto res = sqlite3_exec(conn, query.c_str(), nullptr, nullptr, nullptr); - return res == SQLITE_OK; +bool SQLiteSession::execute(const std::string& query) { + IF_ENDBG dbLogger.debug("SQLiteSession::execute: Executing > " + query); + auto res = sqlite3_exec(conn, query.c_str(), nullptr, nullptr, nullptr); + return res == SQLITE_OK; } -Session &SQLiteSession::query(const std::string &query, - std::function callback) { - IF_ENDBG dbLogger.debug("SQLiteSession::query: Querying > " + query); - auto stmt = prepare(query); - stmt->fetchAll(callback); - return *this; +Session& SQLiteSession::query(const std::string& query, std::function callback) { + IF_ENDBG dbLogger.debug("SQLiteSession::query: Querying > " + query); + auto stmt = prepare(query); + stmt->fetchAll(callback); + return *this; } -SharedPointer SQLiteSession::prepare(const std::string &query, - bool autoExecute) { - auto stmt = SQLiteStmt::create(getOrSetSelf(), query, autoExecute); - stmtPool.push_back(stmt); - return stmt; +SharedPointer SQLiteSession::prepare(const std::string& query, bool autoExecute) { + auto stmt = SQLiteStmt::create(getOrSetSelf(), query, autoExecute); + stmtPool.push_back(stmt); + return stmt; } -std::string SQLiteSession::getLastError() const { - return std::string(sqlite3_errmsg(conn)); -} +std::string SQLiteSession::getLastError() const { return std::string(sqlite3_errmsg(conn)); } -uint64_t SQLiteSession::getAffectedRows() const { - return sqlite3_changes(conn); -} +uint64_t SQLiteSession::getAffectedRows() const { return sqlite3_changes(conn); } -uint64_t SQLiteSession::getLastInsertId() const { - return sqlite3_last_insert_rowid(conn); -} +uint64_t SQLiteSession::getLastInsertId() const { return sqlite3_last_insert_rowid(conn); } void SQLiteSession::close() { - while (!stmtPool.empty()) { - // Close all the active statements or it will error when closing - auto &wptr = stmtPool.back(); - auto ptr = wptr.lock(); - if (!wptr.expired() && ptr) { - ptr->close(); + while (!stmtPool.empty()) { + // Close all the active statements or it will error when closing + auto& wptr = stmtPool.back(); + auto ptr = wptr.lock(); + if (!wptr.expired() && ptr) { + ptr->close(); + } + stmtPool.pop_back(); } - stmtPool.pop_back(); - } - if (conn) { - auto res = sqlite3_close(conn); - if (res != SQLITE_OK) { - throw std::runtime_error( - "SQLiteSession::close: Failed to close database: " + - std::string(sqlite3_errmsg(conn))); + if (conn) { + auto res = sqlite3_close(conn); + if (res != SQLITE_OK) { + throw std::runtime_error( + "SQLiteSession::close: Failed to close database: " + std::string(sqlite3_errmsg(conn)) + ); + } + conn = nullptr; + IF_ENDBG dbLogger.debug("SQLiteSession::close: Closed database"); } - conn = nullptr; - IF_ENDBG dbLogger.debug("SQLiteSession::close: Closed database"); - } } bool SQLiteSession::isOpen() { return conn != nullptr; } DBType SQLiteSession::getType() { return DBType::SQLite; } -SharedPointer SQLiteSession::operator<<(const std::string &query) { - return prepare(query, true); -} +SharedPointer SQLiteSession::operator<<(const std::string& query) { return prepare(query, true); } } // namespace DB \ No newline at end of file diff --git a/src/legacyapi/db/impl/sqlite/Session.h b/src/legacyapi/db/impl/sqlite/Session.h index 929b8cb5..dc5e9ed9 100644 --- a/src/legacyapi/db/impl/sqlite/Session.h +++ b/src/legacyapi/db/impl/sqlite/Session.h @@ -6,28 +6,26 @@ namespace DB { class SQLiteSession : public Session { - sqlite3 *conn = nullptr; + sqlite3* conn = nullptr; public: - SQLiteSession(); - SQLiteSession(const ConnParams ¶ms); - ~SQLiteSession(); - void open(const ConnParams ¶ms); - bool execute(const std::string &query); - Session &query(const std::string &query, - std::function callback); - SharedPointer prepare(const std::string &query, - bool autoExecute = false); - std::string getLastError() const; - uint64_t getAffectedRows() const; - uint64_t getLastInsertId() const; - void close(); - bool isOpen(); - DBType getType(); + SQLiteSession(); + SQLiteSession(const ConnParams& params); + ~SQLiteSession(); + void open(const ConnParams& params); + bool execute(const std::string& query); + Session& query(const std::string& query, std::function callback); + SharedPointer prepare(const std::string& query, bool autoExecute = false); + std::string getLastError() const; + uint64_t getAffectedRows() const; + uint64_t getLastInsertId() const; + void close(); + bool isOpen(); + DBType getType(); - SharedPointer operator<<(const std::string &query); + SharedPointer operator<<(const std::string& query); - friend class SQLiteStmt; + friend class SQLiteStmt; }; } // namespace DB \ No newline at end of file diff --git a/src/legacyapi/db/impl/sqlite/Stmt.cpp b/src/legacyapi/db/impl/sqlite/Stmt.cpp index 4be555b9..3d5e28a2 100644 --- a/src/legacyapi/db/impl/sqlite/Stmt.cpp +++ b/src/legacyapi/db/impl/sqlite/Stmt.cpp @@ -5,297 +5,277 @@ namespace DB { -SQLiteStmt::SQLiteStmt(sqlite3_stmt *stmt, const std::weak_ptr parent, - bool autoExecute) - : Stmt(parent, autoExecute), stmt(stmt) { - IF_ENDBG dbLogger.debug("SQLiteStmt::SQLiteStmt: Constructed! this: {}", - (void *)this); - totalParamsCount = sqlite3_bind_parameter_count(stmt); - if (!totalParamsCount && autoExecute) - execute(); // Execute without params +SQLiteStmt::SQLiteStmt(sqlite3_stmt* stmt, const std::weak_ptr parent, bool autoExecute) +: Stmt(parent, autoExecute), + stmt(stmt) { + IF_ENDBG dbLogger.debug("SQLiteStmt::SQLiteStmt: Constructed! this: {}", (void*)this); + totalParamsCount = sqlite3_bind_parameter_count(stmt); + if (!totalParamsCount && autoExecute) execute(); // Execute without params } int SQLiteStmt::getNextParamIndex() { - int result = -1; - for (int i = 0; i < boundIndexes.size() && i < totalParamsCount; i++) { - if (boundIndexes[i] == result + 1) { - result++; + int result = -1; + for (int i = 0; i < boundIndexes.size() && i < totalParamsCount; i++) { + if (boundIndexes[i] == result + 1) { + result++; + } } - } - IF_ENDBG dbLogger.debug( - "SQLiteStmt::getNextParamIndex: The next param index is {}", result + 1); - return result + 1; + IF_ENDBG dbLogger.debug("SQLiteStmt::getNextParamIndex: The next param index is {}", result + 1); + return result + 1; } void SQLiteStmt::fetchResultHeader() { - if (!resultHeader) - resultHeader.reset(new RowHeader); - int colCnt = sqlite3_column_count(stmt); - for (int i = 0; i < colCnt; i++) { - auto name = sqlite3_column_name(stmt, i); - IF_ENDBG dbLogger.debug( - "SQLiteStmt::fetchResultHeader: Column Name[{}]: {}", i, name); - resultHeader->add(name); - } + if (!resultHeader) resultHeader.reset(new RowHeader); + int colCnt = sqlite3_column_count(stmt); + for (int i = 0; i < colCnt; i++) { + auto name = sqlite3_column_name(stmt, i); + IF_ENDBG dbLogger.debug("SQLiteStmt::fetchResultHeader: Column Name[{}]: {}", i, name); + resultHeader->add(name); + } } SQLiteStmt::~SQLiteStmt() { - IF_ENDBG dbLogger.debug("SQLiteStmt::~SQLiteStmt: Destructor: this: {}", - (void *)this); - close(); + IF_ENDBG dbLogger.debug("SQLiteStmt::~SQLiteStmt: Destructor: this: {}", (void*)this); + close(); } -Stmt &SQLiteStmt::bind(const Any &value, int index) { - ++index; // Index starts at 1, but we need to start at 0 - if (index <= 0 || index > totalParamsCount) { - throw std::invalid_argument("SQLiteStmt::bind: Invalid argument `index`"); - } - if (getUnboundParams() == 0) { - throw std::runtime_error( - "SQLiteStmt::bind: All the parameters are already bound"); - } - int res = SQLITE_OK; - auto type = value.type; - switch (type) { - case Any::Type::Null: - res = sqlite3_bind_null(stmt, index); - break; - case Any::Type::Integer: - res = sqlite3_bind_int64(stmt, index, value.get()); - break; - case Any::Type::UInteger: { - uint64_t val = value.get(); - if (val > LLONG_MAX) { - // The conversion of uint64 to double may result in loss of precision, - // so it is recommended to use string/blob for big numbers - res = sqlite3_bind_double(stmt, index, (double)val); - } else { - res = sqlite3_bind_int64(stmt, index, (int64_t)val); +Stmt& SQLiteStmt::bind(const Any& value, int index) { + ++index; // Index starts at 1, but we need to start at 0 + if (index <= 0 || index > totalParamsCount) { + throw std::invalid_argument("SQLiteStmt::bind: Invalid argument `index`"); } - break; - } - case Any::Type::Floating: - res = sqlite3_bind_double(stmt, index, value.get()); - break; - case Any::Type::String: - case Any::Type::Date: - case Any::Type::Time: - case Any::Type::DateTime: - res = sqlite3_bind_text(stmt, index, value.get().c_str(), -1, - SQLITE_TRANSIENT); - break; - case Any::Type::Blob: - res = - sqlite3_bind_blob(stmt, index, value.get().data(), - (int)value.get().size(), SQLITE_TRANSIENT); - break; - default: - throw std::runtime_error("SQLiteStmt::bind: Unsupported type"); - } - if (res != SQLITE_OK) { - std::string e = fmt::format( - "SQLiteStmt::bind: Failed to bind {} to parameter at index {}", - Any::type2str(type), index); - if (auto s = parent.lock()) { - e += ": " + s->getLastError(); + if (getUnboundParams() == 0) { + throw std::runtime_error("SQLiteStmt::bind: All the parameters are already bound"); } - throw std::runtime_error(e); - } - boundParamsCount++; - boundIndexes.push_back(index - 1); - if (!getUnboundParams() && autoExecute) - execute(); // Execute the statement if all the parameters are bound - return *this; -} -Stmt &SQLiteStmt::bind(const Any &value, const std::string &name) { - if (name.empty()) { - throw std::runtime_error("SQLiteStmt::bind: The name is empty"); - } - std::vector start{'?', ':', '@', '$'}; - int index = 0; - for (auto &s : start) { - auto i = sqlite3_bind_parameter_index(stmt, (s + name).c_str()); - if (i != 0) { - if (index != 0) { - throw std::runtime_error( - "SQLiteStmt::bind: Multiple parameters match the name `" + name + - "`"); - } - index = i; + int res = SQLITE_OK; + auto type = value.type; + switch (type) { + case Any::Type::Null: + res = sqlite3_bind_null(stmt, index); + break; + case Any::Type::Integer: + res = sqlite3_bind_int64(stmt, index, value.get()); + break; + case Any::Type::UInteger: { + uint64_t val = value.get(); + if (val > LLONG_MAX) { + // The conversion of uint64 to double may result in loss of precision, + // so it is recommended to use string/blob for big numbers + res = sqlite3_bind_double(stmt, index, (double)val); + } else { + res = sqlite3_bind_int64(stmt, index, (int64_t)val); + } + break; + } + case Any::Type::Floating: + res = sqlite3_bind_double(stmt, index, value.get()); + break; + case Any::Type::String: + case Any::Type::Date: + case Any::Type::Time: + case Any::Type::DateTime: + res = sqlite3_bind_text(stmt, index, value.get().c_str(), -1, SQLITE_TRANSIENT); + break; + case Any::Type::Blob: + res = sqlite3_bind_blob( + stmt, + index, + value.get().data(), + (int)value.get().size(), + SQLITE_TRANSIENT + ); + break; + default: + throw std::runtime_error("SQLiteStmt::bind: Unsupported type"); } - } - if (index == 0) { - // Tips: The first parameter of SQLiteStmt::bind is the value to bind, the - // second is the key! - throw std::invalid_argument( - "SQLiteStmt::bind: There isn't any statement parameter named `" + name + - "`!"); - } - IF_ENDBG dbLogger.debug("SQLiteStmt::bind: Parameter `{}` is at index {}", - name, index); - return bind(value, index - 1); + if (res != SQLITE_OK) { + std::string e = + fmt::format("SQLiteStmt::bind: Failed to bind {} to parameter at index {}", Any::type2str(type), index); + if (auto s = parent.lock()) { + e += ": " + s->getLastError(); + } + throw std::runtime_error(e); + } + boundParamsCount++; + boundIndexes.push_back(index - 1); + if (!getUnboundParams() && autoExecute) execute(); // Execute the statement if all the parameters are bound + return *this; } -Stmt &SQLiteStmt::bind(const Any &value) { - return bind(value, getNextParamIndex()); +Stmt& SQLiteStmt::bind(const Any& value, const std::string& name) { + if (name.empty()) { + throw std::runtime_error("SQLiteStmt::bind: The name is empty"); + } + std::vector start{'?', ':', '@', '$'}; + int index = 0; + for (auto& s : start) { + auto i = sqlite3_bind_parameter_index(stmt, (s + name).c_str()); + if (i != 0) { + if (index != 0) { + throw std::runtime_error("SQLiteStmt::bind: Multiple parameters match the name `" + name + "`"); + } + index = i; + } + } + if (index == 0) { + // Tips: The first parameter of SQLiteStmt::bind is the value to bind, the + // second is the key! + throw std::invalid_argument("SQLiteStmt::bind: There isn't any statement parameter named `" + name + "`!"); + } + IF_ENDBG dbLogger.debug("SQLiteStmt::bind: Parameter `{}` is at index {}", name, index); + return bind(value, index - 1); } +Stmt& SQLiteStmt::bind(const Any& value) { return bind(value, getNextParamIndex()); } -Stmt &SQLiteStmt::execute() { - step(); - return *this; +Stmt& SQLiteStmt::execute() { + step(); + return *this; } bool SQLiteStmt::step() { - int res = sqlite3_step(stmt); - if (res == SQLITE_ROW || res == SQLITE_DONE) { - if (!parent.expired() && !executed) { - auto s = parent.lock(); - affectedRowCount = s->getAffectedRows(); - insertRowId = s->getLastInsertId(); - executed = true; + int res = sqlite3_step(stmt); + if (res == SQLITE_ROW || res == SQLITE_DONE) { + if (!parent.expired() && !executed) { + auto s = parent.lock(); + affectedRowCount = s->getAffectedRows(); + insertRowId = s->getLastInsertId(); + executed = true; + } + ++steps; } - ++steps; - } - if (res == SQLITE_ROW) { - if (!resultHeader || resultHeader->empty()) { - fetchResultHeader(); + if (res == SQLITE_ROW) { + if (!resultHeader || resultHeader->empty()) { + fetchResultHeader(); + } + IF_ENDBG dbLogger.debug("SQLiteStmt::step: Successfully"); + stepped = true; + return true; + } else if (res == SQLITE_DONE) { + IF_ENDBG dbLogger.debug("SQLiteStmt::step: The statment is done"); + stepped = false; + return false; + } else { + throw std::runtime_error("SQLiteStmt::step: Failed to step"); } - IF_ENDBG dbLogger.debug("SQLiteStmt::step: Successfully"); - stepped = true; - return true; - } else if (res == SQLITE_DONE) { - IF_ENDBG dbLogger.debug("SQLiteStmt::step: The statment is done"); - stepped = false; - return false; - } else { - throw std::runtime_error("SQLiteStmt::step: Failed to step"); - } } bool SQLiteStmt::next() { return step(); } bool SQLiteStmt::done() { - if (stepped) - return false; - return !step(); + if (stepped) return false; + return !step(); } Row SQLiteStmt::_Fetch() { - if (done()) - return Row(); - if (!resultHeader || resultHeader->empty()) { - fetchResultHeader(); - } - Row row(resultHeader); - for (int i = 0; i < resultHeader->size(); i++) { - switch (sqlite3_column_type(stmt, i)) { - case SQLITE_INTEGER: - row.push_back(sqlite3_column_int64(stmt, i)); - break; - case SQLITE_FLOAT: - row.push_back(sqlite3_column_double(stmt, i)); - break; - case SQLITE_TEXT: { - std::string text( - reinterpret_cast(sqlite3_column_text(stmt, i))); - IF_ENDBG dbLogger.debug( - "SQLiteStmt::_Fetch: Fetched TEXT type column: {} {}", i, text); - row.push_back(text); - break; + if (done()) return Row(); + if (!resultHeader || resultHeader->empty()) { + fetchResultHeader(); } - case SQLITE_BLOB: { - ByteArray arr( - reinterpret_cast(sqlite3_column_blob(stmt, i)), - reinterpret_cast(sqlite3_column_blob(stmt, i)) + - sqlite3_column_bytes(stmt, i)); - IF_ENDBG { - std::string out = "SQLiteStmt::_Fetch: Fetched BLOB type column: " + - std::to_string(i) + " "; - for (auto &byte : arr) { - out += ll::string_utils::intToHexStr(byte, true, true, false) + ' '; + Row row(resultHeader); + for (int i = 0; i < resultHeader->size(); i++) { + switch (sqlite3_column_type(stmt, i)) { + case SQLITE_INTEGER: + row.push_back(sqlite3_column_int64(stmt, i)); + break; + case SQLITE_FLOAT: + row.push_back(sqlite3_column_double(stmt, i)); + break; + case SQLITE_TEXT: { + std::string text(reinterpret_cast(sqlite3_column_text(stmt, i))); + IF_ENDBG dbLogger.debug("SQLiteStmt::_Fetch: Fetched TEXT type column: {} {}", i, text); + row.push_back(text); + break; + } + case SQLITE_BLOB: { + ByteArray arr( + reinterpret_cast(sqlite3_column_blob(stmt, i)), + reinterpret_cast(sqlite3_column_blob(stmt, i)) + sqlite3_column_bytes(stmt, i) + ); + IF_ENDBG { + std::string out = "SQLiteStmt::_Fetch: Fetched BLOB type column: " + std::to_string(i) + " "; + for (auto& byte : arr) { + out += ll::string_utils::intToHexStr(byte, true, true, false) + ' '; + } + dbLogger.debug(out); + } + row.push_back(arr); + break; + } + case SQLITE_NULL: + row.push_back(Any()); + break; + default: + throw std::runtime_error("SQLiteSession::query: Unknown column type!"); } - dbLogger.debug(out); - } - row.push_back(arr); - break; - } - case SQLITE_NULL: - row.push_back(Any()); - break; - default: - throw std::runtime_error("SQLiteSession::query: Unknown column type!"); } - } - return row; + return row; } -Stmt &SQLiteStmt::reset() { - auto res = sqlite3_reset(stmt); - if (res != SQLITE_OK) { - throw std::runtime_error("SQLiteStmt::reexec: Failed to reset"); - } - IF_ENDBG dbLogger.debug("SQLiteStmt::reexec: Reset successfully"); - resultHeader.reset(); - steps = 0; - stepped = false; - executed = false; - affectedRowCount = -1; - insertRowId = -1; - return *this; +Stmt& SQLiteStmt::reset() { + auto res = sqlite3_reset(stmt); + if (res != SQLITE_OK) { + throw std::runtime_error("SQLiteStmt::reexec: Failed to reset"); + } + IF_ENDBG dbLogger.debug("SQLiteStmt::reexec: Reset successfully"); + resultHeader.reset(); + steps = 0; + stepped = false; + executed = false; + affectedRowCount = -1; + insertRowId = -1; + return *this; } -Stmt &SQLiteStmt::reexec() { - reset(); - step(); // Execute - return *this; +Stmt& SQLiteStmt::reexec() { + reset(); + step(); // Execute + return *this; } -Stmt &SQLiteStmt::clear() { - auto res = sqlite3_reset(stmt); - if (res != SQLITE_OK) { - throw std::runtime_error("SQLiteStmt::clear: Failed to reset"); - } - IF_ENDBG dbLogger.debug("SQLiteStmt::clear: Reset successfully"); - res = sqlite3_clear_bindings(stmt); - if (res != SQLITE_OK) { - throw std::runtime_error("SQLiteStmt::clear: Failed to clear bindings"); - } - IF_ENDBG dbLogger.debug("SQLiteStmt::clear: Cleared bindings successfully"); - boundParamsCount = 0; - boundIndexes = {}; - resultHeader.reset(); - steps = 0; - stepped = false; - executed = false; - affectedRowCount = -1; - insertRowId = -1; - // close(); - //*this = *(SQLiteStmt*)create(session, query).get(); - return *this; +Stmt& SQLiteStmt::clear() { + auto res = sqlite3_reset(stmt); + if (res != SQLITE_OK) { + throw std::runtime_error("SQLiteStmt::clear: Failed to reset"); + } + IF_ENDBG dbLogger.debug("SQLiteStmt::clear: Reset successfully"); + res = sqlite3_clear_bindings(stmt); + if (res != SQLITE_OK) { + throw std::runtime_error("SQLiteStmt::clear: Failed to clear bindings"); + } + IF_ENDBG dbLogger.debug("SQLiteStmt::clear: Cleared bindings successfully"); + boundParamsCount = 0; + boundIndexes = {}; + resultHeader.reset(); + steps = 0; + stepped = false; + executed = false; + affectedRowCount = -1; + insertRowId = -1; + // close(); + //*this = *(SQLiteStmt*)create(session, query).get(); + return *this; } void SQLiteStmt::close() { - if (stmt) { - sqlite3_finalize(stmt); - stmt = nullptr; - } - totalParamsCount = 0; - boundParamsCount = 0; - boundIndexes = {}; - resultHeader.reset(); - steps = 0; - stepped = false; - executed = false; - affectedRowCount = -1; - insertRowId = -1; + if (stmt) { + sqlite3_finalize(stmt); + stmt = nullptr; + } + totalParamsCount = 0; + boundParamsCount = 0; + boundIndexes = {}; + resultHeader.reset(); + steps = 0; + stepped = false; + executed = false; + affectedRowCount = -1; + insertRowId = -1; } uint64_t SQLiteStmt::getAffectedRows() const { return affectedRowCount; } uint64_t SQLiteStmt::getInsertId() const { return insertRowId; } -int SQLiteStmt::getUnboundParams() const { - return totalParamsCount - boundParamsCount; -} +int SQLiteStmt::getUnboundParams() const { return totalParamsCount - boundParamsCount; } int SQLiteStmt::getBoundParams() const { return boundParamsCount; } @@ -303,27 +283,25 @@ int SQLiteStmt::getParamsCount() const { return totalParamsCount; } DBType SQLiteStmt::getType() const { return DBType::SQLite; } -SharedPointer SQLiteStmt::create(const std::weak_ptr &session, - const std::string &sql, - bool autoExecute) { - auto s = session.lock(); - if (!s || s->getType() != DBType::SQLite) { - throw std::invalid_argument("SQLiteStmt::create: Session is invalid"); - } - sqlite3_stmt *stmt = nullptr; - auto raw = (SQLiteSession *)s.get(); - int res = sqlite3_prepare_v2(raw->conn, sql.c_str(), -1, &stmt, nullptr); - if (res != SQLITE_OK) { - throw std::runtime_error("SQLiteStmt::create: " + s->getLastError()); - } - auto result = new SQLiteStmt(stmt, session, autoExecute); - result->parent = session; - result->setDebugOutput(raw->debugOutput); - if (raw->debugOutput) - dbLogger.debug("SQLiteStmt::create: Prepared > " + sql); - auto shared = SharedPointer(result); - result->self = shared; - return shared; +SharedPointer +SQLiteStmt::create(const std::weak_ptr& session, const std::string& sql, bool autoExecute) { + auto s = session.lock(); + if (!s || s->getType() != DBType::SQLite) { + throw std::invalid_argument("SQLiteStmt::create: Session is invalid"); + } + sqlite3_stmt* stmt = nullptr; + auto raw = (SQLiteSession*)s.get(); + int res = sqlite3_prepare_v2(raw->conn, sql.c_str(), -1, &stmt, nullptr); + if (res != SQLITE_OK) { + throw std::runtime_error("SQLiteStmt::create: " + s->getLastError()); + } + auto result = new SQLiteStmt(stmt, session, autoExecute); + result->parent = session; + result->setDebugOutput(raw->debugOutput); + if (raw->debugOutput) dbLogger.debug("SQLiteStmt::create: Prepared > " + sql); + auto shared = SharedPointer(result); + result->self = shared; + return shared; } } // namespace DB \ No newline at end of file diff --git a/src/legacyapi/db/impl/sqlite/Stmt.h b/src/legacyapi/db/impl/sqlite/Stmt.h index 48a65292..52da0bfe 100644 --- a/src/legacyapi/db/impl/sqlite/Stmt.h +++ b/src/legacyapi/db/impl/sqlite/Stmt.h @@ -9,50 +9,48 @@ class SQLiteSession; class SQLiteStmt : public Stmt { - std::shared_ptr resultHeader; - sqlite3_stmt *stmt = nullptr; - int boundParamsCount = 0; - int totalParamsCount = 0; - int steps = 0; - uint64_t affectedRowCount = -1; - uint64_t insertRowId = -1; - bool stepped = false; - bool executed = false; - std::vector boundIndexes; - - SQLiteStmt(sqlite3_stmt *stmt, const std::weak_ptr parent, - bool autoExecute); - int getNextParamIndex(); - void fetchResultHeader(); + std::shared_ptr resultHeader; + sqlite3_stmt* stmt = nullptr; + int boundParamsCount = 0; + int totalParamsCount = 0; + int steps = 0; + uint64_t affectedRowCount = -1; + uint64_t insertRowId = -1; + bool stepped = false; + bool executed = false; + std::vector boundIndexes; + + SQLiteStmt(sqlite3_stmt* stmt, const std::weak_ptr parent, bool autoExecute); + int getNextParamIndex(); + void fetchResultHeader(); public: - ~SQLiteStmt(); - Stmt &bind(const Any &value, int index); - Stmt &bind(const Any &value, const std::string &name); - Stmt &bind(const Any &value); - Stmt &execute(); - bool step(); - bool next(); - bool done(); - Row _Fetch(); - Stmt &reset(); - /** - * @see Stmt::reexec for details - * @see https://www.sqlite.org/c3ref/reexec.html - */ - Stmt &reexec(); - Stmt &clear(); - void close(); - uint64_t getAffectedRows() const; - uint64_t getInsertId() const; - int getUnboundParams() const; - int getBoundParams() const; - int getParamsCount() const; - DBType getType() const; - - static SharedPointer create(const std::weak_ptr &sess, - const std::string &sql, - bool autoExecute = false); + ~SQLiteStmt(); + Stmt& bind(const Any& value, int index); + Stmt& bind(const Any& value, const std::string& name); + Stmt& bind(const Any& value); + Stmt& execute(); + bool step(); + bool next(); + bool done(); + Row _Fetch(); + Stmt& reset(); + /** + * @see Stmt::reexec for details + * @see https://www.sqlite.org/c3ref/reexec.html + */ + Stmt& reexec(); + Stmt& clear(); + void close(); + uint64_t getAffectedRows() const; + uint64_t getInsertId() const; + int getUnboundParams() const; + int getBoundParams() const; + int getParamsCount() const; + DBType getType() const; + + static SharedPointer + create(const std::weak_ptr& sess, const std::string& sql, bool autoExecute = false); }; } // namespace DB \ No newline at end of file diff --git a/src/legacyapi/utils/FileHelper.cpp b/src/legacyapi/utils/FileHelper.cpp index 39203c04..f75777ef 100644 --- a/src/legacyapi/utils/FileHelper.cpp +++ b/src/legacyapi/utils/FileHelper.cpp @@ -9,137 +9,121 @@ extern ll::Logger logger; -std::optional ReadAllFile(const std::string &filePath, - bool isBinary) { - std::ifstream fRead; - - std::ios_base::openmode mode = std::ios_base::in; - if (isBinary) - mode |= std::ios_base::binary; - - fRead.open(ll::string_utils::str2wstr(filePath), mode); - if (!fRead.is_open()) { - return std::nullopt; - } - std::string data((std::istreambuf_iterator(fRead)), - std::istreambuf_iterator()); - fRead.close(); - return data; +std::optional ReadAllFile(const std::string& filePath, bool isBinary) { + std::ifstream fRead; + + std::ios_base::openmode mode = std::ios_base::in; + if (isBinary) mode |= std::ios_base::binary; + + fRead.open(ll::string_utils::str2wstr(filePath), mode); + if (!fRead.is_open()) { + return std::nullopt; + } + std::string data((std::istreambuf_iterator(fRead)), std::istreambuf_iterator()); + fRead.close(); + return data; } -bool WriteAllFile(const std::string &filePath, const std::string &content, - bool isBinary) { - std::ofstream fWrite; - - std::ios_base::openmode mode = std::ios_base::out; - if (isBinary) - mode |= std::ios_base::binary; - - fWrite.open(ll::string_utils::str2wstr(filePath), mode); - if (!fWrite.is_open()) { - return false; - } - fWrite << content; - fWrite.close(); - return true; +bool WriteAllFile(const std::string& filePath, const std::string& content, bool isBinary) { + std::ofstream fWrite; + + std::ios_base::openmode mode = std::ios_base::out; + if (isBinary) mode |= std::ios_base::binary; + + fWrite.open(ll::string_utils::str2wstr(filePath), mode); + if (!fWrite.is_open()) { + return false; + } + fWrite << content; + fWrite.close(); + return true; } -std::vector GetFileNameList(const std::string &dir) { - std::filesystem::directory_entry d(dir); - if (!d.is_directory()) - return {}; - - std::vector list; - std::filesystem::directory_iterator deps(d); - for (auto &i : deps) { - list.push_back(ll::string_utils::u8str2str(i.path().filename().u8string())); - } - return list; +std::vector GetFileNameList(const std::string& dir) { + std::filesystem::directory_entry d(dir); + if (!d.is_directory()) return {}; + + std::vector list; + std::filesystem::directory_iterator deps(d); + for (auto& i : deps) { + list.push_back(ll::string_utils::u8str2str(i.path().filename().u8string())); + } + return list; } bool CreateDirs(const std::string path) { - std::error_code ec; - auto ret = std::filesystem::create_directories( - std::filesystem::path(ll::string_utils::str2wstr(path)), ec); - if (ec.value() != 0) { - logger.error("Fail to create dir, err code: {}", ec.value()); - logger.error(ec.message()); - } - return ret; + std::error_code ec; + auto ret = std::filesystem::create_directories(std::filesystem::path(ll::string_utils::str2wstr(path)), ec); + if (ec.value() != 0) { + logger.error("Fail to create dir, err code: {}", ec.value()); + logger.error(ec.message()); + } + return ret; } // From LiteLoaderBDSv2 llapi/utils/WinHelper.cpp -wchar_t *str2cwstr(const std::string &str) { - auto len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0); - auto *buffer = new wchar_t[len + 1]; - MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, buffer, len + 1); - buffer[len] = L'\0'; - return buffer; +wchar_t* str2cwstr(const std::string& str) { + auto len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0); + auto* buffer = new wchar_t[len + 1]; + MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, buffer, len + 1); + buffer[len] = L'\0'; + return buffer; } -std::pair NewProcessSync(const std::string &process, - int timeLimit = -1, - bool noReadOutput = true) { - SECURITY_ATTRIBUTES sa; - HANDLE hRead, hWrite; - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.lpSecurityDescriptor = nullptr; - sa.bInheritHandle = TRUE; - - if (!CreatePipe(&hRead, &hWrite, &sa, 0)) - return {-1, ""}; - STARTUPINFOW si = {0}; - PROCESS_INFORMATION pi; - - si.cb = sizeof(STARTUPINFO); - GetStartupInfoW(&si); - si.hStdOutput = si.hStdError = hWrite; - si.dwFlags = STARTF_USESTDHANDLES; - - auto wCmd = str2cwstr(process); - if (!CreateProcessW(nullptr, wCmd, nullptr, nullptr, TRUE, 0, nullptr, - nullptr, &si, &pi)) { +std::pair NewProcessSync(const std::string& process, int timeLimit = -1, bool noReadOutput = true) { + SECURITY_ATTRIBUTES sa; + HANDLE hRead, hWrite; + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = nullptr; + sa.bInheritHandle = TRUE; + + if (!CreatePipe(&hRead, &hWrite, &sa, 0)) return {-1, ""}; + STARTUPINFOW si = {0}; + PROCESS_INFORMATION pi; + + si.cb = sizeof(STARTUPINFO); + GetStartupInfoW(&si); + si.hStdOutput = si.hStdError = hWrite; + si.dwFlags = STARTF_USESTDHANDLES; + + auto wCmd = str2cwstr(process); + if (!CreateProcessW(nullptr, wCmd, nullptr, nullptr, TRUE, 0, nullptr, nullptr, &si, &pi)) { + delete[] wCmd; + return {-1, ""}; + } + CloseHandle(hWrite); + CloseHandle(pi.hThread); + + if (timeLimit == -1) WaitForSingleObject(pi.hProcess, INFINITE); + else { + WaitForSingleObject(pi.hProcess, timeLimit); + TerminateProcess(pi.hProcess, -1); + } + char buffer[4096]; + std::string strOutput; + DWORD bytesRead, exitCode; + delete[] wCmd; - return {-1, ""}; - } - CloseHandle(hWrite); - CloseHandle(pi.hThread); - - if (timeLimit == -1) - WaitForSingleObject(pi.hProcess, INFINITE); - else { - WaitForSingleObject(pi.hProcess, timeLimit); - TerminateProcess(pi.hProcess, -1); - } - char buffer[4096]; - std::string strOutput; - DWORD bytesRead, exitCode; - - delete[] wCmd; - GetExitCodeProcess(pi.hProcess, &exitCode); - if (!noReadOutput) { - while (true) { - ZeroMemory(buffer, 4096); - if (!ReadFile(hRead, buffer, 4096, &bytesRead, nullptr)) - break; - strOutput.append(buffer, bytesRead); + GetExitCodeProcess(pi.hProcess, &exitCode); + if (!noReadOutput) { + while (true) { + ZeroMemory(buffer, 4096); + if (!ReadFile(hRead, buffer, 4096, &bytesRead, nullptr)) break; + strOutput.append(buffer, bytesRead); + } } - } - CloseHandle(hRead); - CloseHandle(pi.hProcess); - return {exitCode, strOutput}; + CloseHandle(hRead); + CloseHandle(pi.hProcess); + return {exitCode, strOutput}; } -std::pair UncompressFile(const std::string &filePath, - const std::string &toDir, - int processTimeout) { - std::error_code ec; - std::filesystem::create_directories(toDir, ec); - std::string realToDir = toDir.ends_with('/') ? toDir : toDir + "/"; - auto &&[exitCode, output] = - NewProcessSync(fmt::format(R"({} x "{}" -o"{}" -aoa)", - "./plugins/LegacyScriptEngine/7z/7za.exe", - filePath, realToDir), - processTimeout); - return {exitCode, std::move(output)}; +std::pair UncompressFile(const std::string& filePath, const std::string& toDir, int processTimeout) { + std::error_code ec; + std::filesystem::create_directories(toDir, ec); + std::string realToDir = toDir.ends_with('/') ? toDir : toDir + "/"; + auto&& [exitCode, output] = NewProcessSync( + fmt::format(R"({} x "{}" -o"{}" -aoa)", "./plugins/LegacyScriptEngine/7z/7za.exe", filePath, realToDir), + processTimeout + ); + return {exitCode, std::move(output)}; } diff --git a/src/legacyapi/utils/FileHelper.h b/src/legacyapi/utils/FileHelper.h index 36e2880b..69f5e286 100644 --- a/src/legacyapi/utils/FileHelper.h +++ b/src/legacyapi/utils/FileHelper.h @@ -5,12 +5,8 @@ #include #include -std::vector GetFileNameList(const std::string &dir); -bool CreateDirs(const std::string path); -std::optional ReadAllFile(const std::string &filePath, - bool isBinary = false); -bool WriteAllFile(const std::string &filePath, const std::string &content, - bool isBinary = false); -std::pair UncompressFile(const std::string &filePath, - const std::string &toDir, - int processTimeout); \ No newline at end of file +std::vector GetFileNameList(const std::string& dir); +bool CreateDirs(const std::string path); +std::optional ReadAllFile(const std::string& filePath, bool isBinary = false); +bool WriteAllFile(const std::string& filePath, const std::string& content, bool isBinary = false); +std::pair UncompressFile(const std::string& filePath, const std::string& toDir, int processTimeout); \ No newline at end of file diff --git a/src/legacyapi/utils/STLHelper.h b/src/legacyapi/utils/STLHelper.h index 47a78f6f..7e70a860 100644 --- a/src/legacyapi/utils/STLHelper.h +++ b/src/legacyapi/utils/STLHelper.h @@ -1,6 +1,6 @@ #pragma once -#include #include +#include template void erase_if(ContainerT& items, const PredicateT& predicate) { diff --git a/src/legacyapi/utils/StringReader.cpp b/src/legacyapi/utils/StringReader.cpp index 2abeb029..f94dd4eb 100644 --- a/src/legacyapi/utils/StringReader.cpp +++ b/src/legacyapi/utils/StringReader.cpp @@ -3,14 +3,24 @@ //////////////////////////////// CONSTRUCTOR //////////////////////////////// -StringReader::StringReader(const std::string &str) - : str(str), len(str.length()), begin(str.begin()), end(str.end()), - it(begin) {} -StringReader::StringReader(const char *cstr) - : str(cstr), len(str.length()), begin(str.begin()), end(str.end()), - it(begin) {} -StringReader::StringReader(const char *cstr, size_t len) - : str(cstr, len), len(len), begin(str.begin()), end(str.end()), it(begin) {} +StringReader::StringReader(const std::string& str) +: str(str), + len(str.length()), + begin(str.begin()), + end(str.end()), + it(begin) {} +StringReader::StringReader(const char* cstr) +: str(cstr), + len(str.length()), + begin(str.begin()), + end(str.end()), + it(begin) {} +StringReader::StringReader(const char* cstr, size_t len) +: str(cstr, len), + len(len), + begin(str.begin()), + end(str.end()), + it(begin) {} //////////////////////////////// GET //////////////////////////////// @@ -31,235 +41,216 @@ size_t StringReader::getRemaining() const { return end - it; } //////////////////////////////// READ //////////////////////////////// char StringReader::read() { - if (isEnd()) { - throw std::out_of_range( - "StringReader::read: The end of the string has been reached"); - } - return *it++; + if (isEnd()) { + throw std::out_of_range("StringReader::read: The end of the string has been reached"); + } + return *it++; } -char StringReader::read(char &c) { return c = read(); } +char StringReader::read(char& c) { return c = read(); } std::string StringReader::read(size_t len) { - if (len > getRemaining()) { - throw std::out_of_range( - "StringReader::read: The end of the string has been reached"); - } - std::string result(it, it + len); - it += len; - return result; + if (len > getRemaining()) { + throw std::out_of_range("StringReader::read: The end of the string has been reached"); + } + std::string result(it, it + len); + it += len; + return result; } std::string StringReader::readUntil(char c) { - std::string result; - while (!isEnd() && peek() != c) { - result += read(); - } - return result; + std::string result; + while (!isEnd() && peek() != c) { + result += read(); + } + return result; } -std::string StringReader::readUntil(const std::string &chars) { - std::string result; - while (!isEnd() && chars.find(peek()) == std::string::npos) { - result += read(); - } - return result; +std::string StringReader::readUntil(const std::string& chars) { + std::string result; + while (!isEnd() && chars.find(peek()) == std::string::npos) { + result += read(); + } + return result; } std::string StringReader::readUntilNot(char c) { - std::string result; - while (!isEnd() && peek() != c) { - result += read(); - } - return result; + std::string result; + while (!isEnd() && peek() != c) { + result += read(); + } + return result; } -std::string StringReader::readUntilNot(const std::string &chars) { - std::string result; - while (!isEnd() && chars.find(peek()) != std::string::npos) { - result += read(); - } - return result; +std::string StringReader::readUntilNot(const std::string& chars) { + std::string result; + while (!isEnd() && chars.find(peek()) != std::string::npos) { + result += read(); + } + return result; } std::string StringReader::readLine() { return readUntil('\n'); } -std::string StringReader::readLetters(const std::string &chars) { - std::string result; - while (!isEnd() && - (isalpha(peek()) || chars.find(peek()) != std::string::npos)) { - result += read(); - } - return result; +std::string StringReader::readLetters(const std::string& chars) { + std::string result; + while (!isEnd() && (isalpha(peek()) || chars.find(peek()) != std::string::npos)) { + result += read(); + } + return result; } -std::string StringReader::readLower(const std::string &chars) { - std::string result; - while (!isEnd() && - (islower(peek()) || chars.find(peek()) != std::string::npos)) { - result += read(); - } - return result; +std::string StringReader::readLower(const std::string& chars) { + std::string result; + while (!isEnd() && (islower(peek()) || chars.find(peek()) != std::string::npos)) { + result += read(); + } + return result; } -std::string StringReader::readUpper(const std::string &chars) { - std::string result; - while (!isEnd() && - (isupper(peek()) || chars.find(peek()) != std::string::npos)) { - result += read(); - } - return result; +std::string StringReader::readUpper(const std::string& chars) { + std::string result; + while (!isEnd() && (isupper(peek()) || chars.find(peek()) != std::string::npos)) { + result += read(); + } + return result; } -std::string StringReader::readDigits(const std::string &chars) { - std::string result; - while (!isEnd() && - (isdigit(peek()) || chars.find(peek()) != std::string::npos)) { - result += read(); - } - return result; +std::string StringReader::readDigits(const std::string& chars) { + std::string result; + while (!isEnd() && (isdigit(peek()) || chars.find(peek()) != std::string::npos)) { + result += read(); + } + return result; } -std::string StringReader::readLettersAndDigits(const std::string &chars) { - std::string result; - while (!isEnd() && - (isalnum(peek()) || chars.find(peek()) != std::string::npos)) { - result += read(); - } - return result; +std::string StringReader::readLettersAndDigits(const std::string& chars) { + std::string result; + while (!isEnd() && (isalnum(peek()) || chars.find(peek()) != std::string::npos)) { + result += read(); + } + return result; } std::string StringReader::readVariableName() { - std::string result; - bool first = true; - while (!isEnd() && (isalnum(peek()) || peek() == '_')) { - if (first && isdigit(peek())) { - return result; + std::string result; + bool first = true; + while (!isEnd() && (isalnum(peek()) || peek() == '_')) { + if (first && isdigit(peek())) { + return result; + } + result += read(); } - result += read(); - } - return result; + return result; } std::string StringReader::readToEnd() { - std::string result; - while (isValid()) { - result += read(); - } - return result; + std::string result; + while (isValid()) { + result += read(); + } + return result; } //////////////////////////////// PEEK //////////////////////////////// char StringReader::peek() { - if (isEnd()) { - throw std::out_of_range( - "StringReader::peek: The end of the string has been reached"); - } - return *it; + if (isEnd()) { + throw std::out_of_range("StringReader::peek: The end of the string has been reached"); + } + return *it; } -char StringReader::peek(char &c) { return c = peek(); } +char StringReader::peek(char& c) { return c = peek(); } char StringReader::peek(size_t offset) { - if (isEnd()) { - throw std::out_of_range( - "StringReader::peek: The end of the string has been reached"); - } - if (offset >= getRemaining()) { - throw std::out_of_range( - "StringReader::peek: The offset is greater than the remaining length"); - } - return *(it + offset); + if (isEnd()) { + throw std::out_of_range("StringReader::peek: The end of the string has been reached"); + } + if (offset >= getRemaining()) { + throw std::out_of_range("StringReader::peek: The offset is greater than the remaining length"); + } + return *(it + offset); } std::string StringReader::peek(size_t offset, size_t len) { - if (offset >= getRemaining()) { - throw std::out_of_range( - "StringReader::peek: The offset is greater than the remaining length"); - } - return std::string(it + offset, it + offset + len); + if (offset >= getRemaining()) { + throw std::out_of_range("StringReader::peek: The offset is greater than the remaining length"); + } + return std::string(it + offset, it + offset + len); } //////////////////////////////// SKIP //////////////////////////////// void StringReader::skip() { - if (isEnd()) { - throw std::out_of_range( - "StringReader::skip: The end of the string has been reached"); - } - ++it; + if (isEnd()) { + throw std::out_of_range("StringReader::skip: The end of the string has been reached"); + } + ++it; } void StringReader::skip(size_t len) { - if (isEnd()) { - throw std::out_of_range( - "StringReader::skip: The end of the string has been reached"); - } - if (len > getRemaining()) { - throw std::out_of_range( - "StringReader::skip: The length is greater than the remaining length"); - } - it += len; + if (isEnd()) { + throw std::out_of_range("StringReader::skip: The end of the string has been reached"); + } + if (len > getRemaining()) { + throw std::out_of_range("StringReader::skip: The length is greater than the remaining length"); + } + it += len; } void StringReader::skipUntil(char c) { - while (isValid() && peek() != c) { - skip(); - } + while (isValid() && peek() != c) { + skip(); + } } -void StringReader::skipUntil(const std::string &chars) { - while (isValid() && chars.find(peek()) == std::string::npos) { - skip(); - } +void StringReader::skipUntil(const std::string& chars) { + while (isValid() && chars.find(peek()) == std::string::npos) { + skip(); + } } void StringReader::skipUntilNot(char c) { - while (isValid() && peek() == c) { - skip(); - } + while (isValid() && peek() == c) { + skip(); + } } -void StringReader::skipUntilNot(const std::string &chars) { - while (isValid() && chars.find(peek()) != std::string::npos) { - skip(); - } +void StringReader::skipUntilNot(const std::string& chars) { + while (isValid() && chars.find(peek()) != std::string::npos) { + skip(); + } } -void StringReader::skipLetters(const std::string &chars) { - while (isValid() && - (isalpha(peek()) || chars.find(peek()) != std::string::npos)) { - skip(); - } +void StringReader::skipLetters(const std::string& chars) { + while (isValid() && (isalpha(peek()) || chars.find(peek()) != std::string::npos)) { + skip(); + } } -void StringReader::skipLower(const std::string &chars) { - while (isValid() && - (islower(peek()) || chars.find(peek()) != std::string::npos)) { - skip(); - } +void StringReader::skipLower(const std::string& chars) { + while (isValid() && (islower(peek()) || chars.find(peek()) != std::string::npos)) { + skip(); + } } -void StringReader::skipUpper(const std::string &chars) { - while (isValid() && - (isupper(peek()) || chars.find(peek()) != std::string::npos)) { - skip(); - } +void StringReader::skipUpper(const std::string& chars) { + while (isValid() && (isupper(peek()) || chars.find(peek()) != std::string::npos)) { + skip(); + } } -void StringReader::skipDigits(const std::string &chars) { - while (isValid() && - (isdigit(peek()) || chars.find(peek()) != std::string::npos)) { - skip(); - } +void StringReader::skipDigits(const std::string& chars) { + while (isValid() && (isdigit(peek()) || chars.find(peek()) != std::string::npos)) { + skip(); + } } -void StringReader::skipLettersAndDigits(const std::string &chars) { - while (isValid() && - (isalnum(peek()) || chars.find(peek()) != std::string::npos)) { - skip(); - } +void StringReader::skipLettersAndDigits(const std::string& chars) { + while (isValid() && (isalnum(peek()) || chars.find(peek()) != std::string::npos)) { + skip(); + } } void StringReader::skipWhitespace() { skipUntilNot(" \t\r\n"); } diff --git a/src/legacyapi/utils/StringReader.h b/src/legacyapi/utils/StringReader.h index 4f727d05..74412109 100644 --- a/src/legacyapi/utils/StringReader.h +++ b/src/legacyapi/utils/StringReader.h @@ -3,67 +3,68 @@ class StringReader { - const std::string str; - size_t len = 0; - std::string::const_iterator begin; - std::string::const_iterator end; - std::string::const_iterator it; + const std::string str; + size_t len = 0; + std::string::const_iterator begin; + std::string::const_iterator end; + std::string::const_iterator it; public: - StringReader(const std::string &str); - StringReader(const char *str); - StringReader(const char *str, size_t len); - StringReader(const StringReader &other) = default; - StringReader(StringReader &&other) = default; - StringReader &operator=(const StringReader &other) = default; - StringReader &operator=(StringReader &&other) = default; + StringReader(const std::string& str); + StringReader(const char* str); + StringReader(const char* str, size_t len); + StringReader(const StringReader& other) = default; + StringReader(StringReader&& other) = default; + StringReader& operator=(const StringReader& other) = default; + StringReader& operator=(StringReader&& other) = default; - bool isEmpty() const; - bool isEnd() const; - bool isStart() const; - bool isValid() const; - size_t getPos() const; - size_t getLength() const; - size_t getRemaining() const; + bool isEmpty() const; + bool isEnd() const; + bool isStart() const; + bool isValid() const; + size_t getPos() const; + size_t getLength() const; + size_t getRemaining() const; - char read(); - char read(char &c); - std::string read(size_t len); - std::string readUntil(char c); - std::string readUntil(const std::string &chars); - std::string readUntilNot(const std::string &chars); - std::string readUntilNot(char c); - std::string readLine(); - std::string readLetters(const std::string &chars = ""); - std::string readLower(const std::string &chars = ""); - std::string readUpper(const std::string &chars = ""); - std::string readDigits(const std::string &chars = ""); - std::string readLettersAndDigits(const std::string &chars = ""); - std::string readVariableName(); - std::string readToEnd(); - char peek(); - char peek(char &c); - char peek(size_t offset); - std::string peek(size_t offset, size_t len); - void skip(); - void skip(size_t len); - void skipUntil(char c); - void skipUntil(const std::string &chars); - void skipUntilNot(char c); - void skipUntilNot(const std::string &chars); - void skipWhitespace(); - void skipLine(); - void skipLetters(const std::string &chars = ""); - void skipLower(const std::string &chars = ""); - void skipUpper(const std::string &chars = ""); - void skipDigits(const std::string &chars = ""); - void skipLettersAndDigits(const std::string &chars = ""); + char read(); + char read(char& c); + std::string read(size_t len); + std::string readUntil(char c); + std::string readUntil(const std::string& chars); + std::string readUntilNot(const std::string& chars); + std::string readUntilNot(char c); + std::string readLine(); + std::string readLetters(const std::string& chars = ""); + std::string readLower(const std::string& chars = ""); + std::string readUpper(const std::string& chars = ""); + std::string readDigits(const std::string& chars = ""); + std::string readLettersAndDigits(const std::string& chars = ""); + std::string readVariableName(); + std::string readToEnd(); + char peek(); + char peek(char& c); + char peek(size_t offset); + std::string peek(size_t offset, size_t len); + void skip(); + void skip(size_t len); + void skipUntil(char c); + void skipUntil(const std::string& chars); + void skipUntilNot(char c); + void skipUntilNot(const std::string& chars); + void skipWhitespace(); + void skipLine(); + void skipLetters(const std::string& chars = ""); + void skipLower(const std::string& chars = ""); + void skipUpper(const std::string& chars = ""); + void skipDigits(const std::string& chars = ""); + void skipLettersAndDigits(const std::string& chars = ""); - template inline T readInteger() { - T result = 0; - while (isValid() && isdigit(read())) { - result = result * 10 + (read() - '0'); + template + inline T readInteger() { + T result = 0; + while (isValid() && isdigit(read())) { + result = result * 10 + (read() - '0'); + } + return result; } - return result; - } }; diff --git a/src/main/BindAPIs.cpp b/src/main/BindAPIs.cpp index cba53b0d..ae03925b 100644 --- a/src/main/BindAPIs.cpp +++ b/src/main/BindAPIs.cpp @@ -32,96 +32,96 @@ #include "api/InternationalAPI.h" #include "api/ParticleAPI.h" -void BindAPIs(ScriptEngine *engine) { +void BindAPIs(ScriptEngine* engine) { - //////////////// 全局函数 //////////////// + //////////////// 全局函数 //////////////// - engine->set("log", Function::newFunction(Log)); - engine->set("colorLog", Function::newFunction(ColorLog)); - engine->set("fastLog", Function::newFunction(FastLog)); + engine->set("log", Function::newFunction(Log)); + engine->set("colorLog", Function::newFunction(ColorLog)); + engine->set("fastLog", Function::newFunction(FastLog)); #ifndef LLSE_BACKEND_NODEJS // NodeJs has its own functions below - engine->set("setTimeout", Function::newFunction(SetTimeout)); - engine->set("setInterval", Function::newFunction(SetInterval)); - engine->set("clearInterval", Function::newFunction(ClearInterval)); + engine->set("setTimeout", Function::newFunction(SetTimeout)); + engine->set("setInterval", Function::newFunction(SetInterval)); + engine->set("clearInterval", Function::newFunction(ClearInterval)); #endif - //////////////// 静态类 //////////////// + //////////////// 静态类 //////////////// - engine->registerNativeClass(McClassBuilder); - engine->registerNativeClass(SystemClassBuilder); - engine->registerNativeClass(LoggerClassBuilder); - engine->registerNativeClass(DataClassBuilder); - engine->registerNativeClass(MoneyClassBuilder); - engine->registerNativeClass(NetworkClassBuilder); - engine->registerNativeClass(LlClassBuilder); - engine->registerNativeClass(VersionClassBuilder); - engine->registerNativeClass(NbtStaticBuilder); - engine->registerNativeClass(TextClassBuilder); - engine->registerNativeClass(ParticleColorBuilder); - engine->registerNativeClass(DirectionAngleBuilder); - engine->registerNativeClass(ActorDamageCauseBuilder); + engine->registerNativeClass(McClassBuilder); + engine->registerNativeClass(SystemClassBuilder); + engine->registerNativeClass(LoggerClassBuilder); + engine->registerNativeClass(DataClassBuilder); + engine->registerNativeClass(MoneyClassBuilder); + engine->registerNativeClass(NetworkClassBuilder); + engine->registerNativeClass(LlClassBuilder); + engine->registerNativeClass(VersionClassBuilder); + engine->registerNativeClass(NbtStaticBuilder); + engine->registerNativeClass(TextClassBuilder); + engine->registerNativeClass(ParticleColorBuilder); + engine->registerNativeClass(DirectionAngleBuilder); + engine->registerNativeClass(ActorDamageCauseBuilder); - engine->registerNativeClass(PermissionStaticBuilder); - engine->registerNativeClass(ParamTypeStaticBuilder); - engine->registerNativeClass(ParamOptionStaticBuilder); - engine->registerNativeClass(OriginTypeStaticBuilder); - engine->registerNativeClass(DamageCauseEnumBuilder); + engine->registerNativeClass(PermissionStaticBuilder); + engine->registerNativeClass(ParamTypeStaticBuilder); + engine->registerNativeClass(ParamOptionStaticBuilder); + engine->registerNativeClass(OriginTypeStaticBuilder); + engine->registerNativeClass(DamageCauseEnumBuilder); - // engine->registerNativeClass(PermissionClassBuilder); + // engine->registerNativeClass(PermissionClassBuilder); - engine->registerNativeClass(I18nClassBuilder); + engine->registerNativeClass(I18nClassBuilder); - //////////////// 实例类 //////////////// + //////////////// 实例类 //////////////// - engine->registerNativeClass(IntPosBuilder); - engine->registerNativeClass(FloatPosBuilder); - engine->registerNativeClass(DirectionAngleBuilder); - engine->registerNativeClass(BlockClassBuilder); - engine->registerNativeClass(KVDBClassBuilder); - engine->registerNativeClass(DBSessionClassBuilder); - engine->registerNativeClass(DBStmtClassBuilder); - engine->registerNativeClass(ConfJsonClassBuilder); - engine->registerNativeClass(ConfIniClassBuilder); - engine->registerNativeClass(DeviceClassBuilder); - engine->registerNativeClass(ContainerClassBuilder); - engine->registerNativeClass(EntityClassBuilder); - engine->registerNativeClass(FileClassBuilder); - engine->registerNativeClass(WSClientClassBuilder); - engine->registerNativeClass(BlockEntityClassBuilder); - engine->registerNativeClass(SimpleFormClassBuilder); - engine->registerNativeClass(CustomFormClassBuilder); - engine->registerNativeClass(ItemClassBuilder); - engine->registerNativeClass(PlayerClassBuilder); - engine->registerNativeClass(ObjectiveClassBuilder); - engine->registerNativeClass(PacketClassBuilder); - engine->registerNativeClass(NbtEndClassBuilder); - engine->registerNativeClass(NbtByteClassBuilder); - engine->registerNativeClass(NbtShortClassBuilder); - engine->registerNativeClass(NbtIntClassBuilder); - engine->registerNativeClass(NbtLongClassBuilder); - engine->registerNativeClass(NbtFloatClassBuilder); - engine->registerNativeClass(NbtDoubleClassBuilder); - engine->registerNativeClass(NbtStringClassBuilder); - engine->registerNativeClass(NbtByteArrayClassBuilder); - engine->registerNativeClass(NbtListClassBuilder); - engine->registerNativeClass(NbtCompoundClassBuilder); - engine->registerNativeClass(CommandClassBuilder); - engine->registerNativeClass(CommandOriginClassBuilder); - engine->registerNativeClass(CommandOutputClassBuilder); - engine->registerNativeClass(HttpServerClassBuilder); - engine->registerNativeClass(HttpRequestClassBuilder); - engine->registerNativeClass(HttpResponseClassBuilder); - engine->registerNativeClass(BinaryStreamClassBuilder); - // engine->registerNativeClass(RoleClassBuilder); - engine->registerNativeClass(ParticleSpawnerBuilder); + engine->registerNativeClass(IntPosBuilder); + engine->registerNativeClass(FloatPosBuilder); + engine->registerNativeClass(DirectionAngleBuilder); + engine->registerNativeClass(BlockClassBuilder); + engine->registerNativeClass(KVDBClassBuilder); + engine->registerNativeClass(DBSessionClassBuilder); + engine->registerNativeClass(DBStmtClassBuilder); + engine->registerNativeClass(ConfJsonClassBuilder); + engine->registerNativeClass(ConfIniClassBuilder); + engine->registerNativeClass(DeviceClassBuilder); + engine->registerNativeClass(ContainerClassBuilder); + engine->registerNativeClass(EntityClassBuilder); + engine->registerNativeClass(FileClassBuilder); + engine->registerNativeClass(WSClientClassBuilder); + engine->registerNativeClass(BlockEntityClassBuilder); + engine->registerNativeClass(SimpleFormClassBuilder); + engine->registerNativeClass(CustomFormClassBuilder); + engine->registerNativeClass(ItemClassBuilder); + engine->registerNativeClass(PlayerClassBuilder); + engine->registerNativeClass(ObjectiveClassBuilder); + engine->registerNativeClass(PacketClassBuilder); + engine->registerNativeClass(NbtEndClassBuilder); + engine->registerNativeClass(NbtByteClassBuilder); + engine->registerNativeClass(NbtShortClassBuilder); + engine->registerNativeClass(NbtIntClassBuilder); + engine->registerNativeClass(NbtLongClassBuilder); + engine->registerNativeClass(NbtFloatClassBuilder); + engine->registerNativeClass(NbtDoubleClassBuilder); + engine->registerNativeClass(NbtStringClassBuilder); + engine->registerNativeClass(NbtByteArrayClassBuilder); + engine->registerNativeClass(NbtListClassBuilder); + engine->registerNativeClass(NbtCompoundClassBuilder); + engine->registerNativeClass(CommandClassBuilder); + engine->registerNativeClass(CommandOriginClassBuilder); + engine->registerNativeClass(CommandOutputClassBuilder); + engine->registerNativeClass(HttpServerClassBuilder); + engine->registerNativeClass(HttpRequestClassBuilder); + engine->registerNativeClass(HttpResponseClassBuilder); + engine->registerNativeClass(BinaryStreamClassBuilder); + // engine->registerNativeClass(RoleClassBuilder); + engine->registerNativeClass(ParticleSpawnerBuilder); - //////////////// NativeFFI //////////////// - engine->registerNativeClass(NativeTypeEnumBuilder); - engine->registerNativeClass(NativePointerBuilder); - engine->registerNativeClass(NativeCallBuilder); - engine->registerNativeClass(NativeStdStringBuilder); - engine->registerNativeClass(NativeHookBuilder); - engine->registerNativeClass(NativePatchBuilder); - engine->registerNativeClass(GlobalNativePointerBuilder); + //////////////// NativeFFI //////////////// + engine->registerNativeClass(NativeTypeEnumBuilder); + engine->registerNativeClass(NativePointerBuilder); + engine->registerNativeClass(NativeCallBuilder); + engine->registerNativeClass(NativeStdStringBuilder); + engine->registerNativeClass(NativeHookBuilder); + engine->registerNativeClass(NativePatchBuilder); + engine->registerNativeClass(GlobalNativePointerBuilder); } diff --git a/src/main/BuiltinCommands.cpp b/src/main/BuiltinCommands.cpp index e5aad85d..d1af2167 100644 --- a/src/main/BuiltinCommands.cpp +++ b/src/main/BuiltinCommands.cpp @@ -8,76 +8,75 @@ #include "PythonHelper.h" #endif -extern ll::Logger logger; -extern bool isInConsoleDebugMode; -extern ScriptEngine *debugEngine; +extern ll::Logger logger; +extern bool isInConsoleDebugMode; +extern ScriptEngine* debugEngine; #define OUTPUT_DEBUG_SIGN() std::cout << "> " << std::flush -bool ProcessDebugEngine(const std::string &cmd) { +bool ProcessDebugEngine(const std::string& cmd) { #ifdef LLSE_BACKEND_PYTHON - // process python debug seperately - return PythonHelper::processPythonDebugEngine(cmd); + // process python debug seperately + return PythonHelper::processPythonDebugEngine(cmd); #endif - if (cmd == LLSE_DEBUG_CMD) { - if (isInConsoleDebugMode) { - // EndDebug - logger.info("Debug mode ended"); - isInConsoleDebugMode = false; - } else { - // StartDebug - logger.info("Debug mode begins"); - isInConsoleDebugMode = true; - OUTPUT_DEBUG_SIGN(); + if (cmd == LLSE_DEBUG_CMD) { + if (isInConsoleDebugMode) { + // EndDebug + logger.info("Debug mode ended"); + isInConsoleDebugMode = false; + } else { + // StartDebug + logger.info("Debug mode begins"); + isInConsoleDebugMode = true; + OUTPUT_DEBUG_SIGN(); + } + return false; } - return false; - } - if (isInConsoleDebugMode) { - EngineScope enter(debugEngine); - try { - if (cmd == "stop") { - return true; - } else { - auto result = debugEngine->eval(cmd); - PrintValue(std::cout, result); - std::cout << std::endl; - OUTPUT_DEBUG_SIGN(); - } - } catch (Exception &e) { - PrintException(e); - OUTPUT_DEBUG_SIGN(); + if (isInConsoleDebugMode) { + EngineScope enter(debugEngine); + try { + if (cmd == "stop") { + return true; + } else { + auto result = debugEngine->eval(cmd); + PrintValue(std::cout, result); + std::cout << std::endl; + OUTPUT_DEBUG_SIGN(); + } + } catch (Exception& e) { + PrintException(e); + OUTPUT_DEBUG_SIGN(); + } + return false; } - return false; - } - return true; + return true; } -bool StartsWith(const std::string &str, const std::string &start) { - size_t srcLen = str.size(); - size_t startLen = start.size(); - if (srcLen >= startLen) { - string temp = str.substr(0, startLen); - if (temp == start) - return true; - } +bool StartsWith(const std::string& str, const std::string& start) { + size_t srcLen = str.size(); + size_t startLen = start.size(); + if (srcLen >= startLen) { + string temp = str.substr(0, startLen); + if (temp == start) return true; + } - return false; + return false; } -#define FIX_OLD_COMMAND(OLDCMD, NEWCMD) \ - if (StartsWith(cmd, OLDCMD)) { \ - logger.warn("* Please use command " #NEWCMD " instead."); \ - cmd.replace(0, 3, "ll"); \ - } +#define FIX_OLD_COMMAND(OLDCMD, NEWCMD) \ + if (StartsWith(cmd, OLDCMD)) { \ + logger.warn("* Please use command " #NEWCMD " instead."); \ + cmd.replace(0, 3, "ll"); \ + } -bool ProcessOldHotManageCommand(std::string &cmd) { - FIX_OLD_COMMAND("lxl list", "ll list"); - FIX_OLD_COMMAND("lxl load", "ll load"); - FIX_OLD_COMMAND("lxl unload", "ll unload"); - FIX_OLD_COMMAND("lxl reload", "ll reload"); - FIX_OLD_COMMAND("lxl version", "ll version"); - FIX_OLD_COMMAND("lxl update", "ll upgrade"); +bool ProcessOldHotManageCommand(std::string& cmd) { + FIX_OLD_COMMAND("lxl list", "ll list"); + FIX_OLD_COMMAND("lxl load", "ll load"); + FIX_OLD_COMMAND("lxl unload", "ll unload"); + FIX_OLD_COMMAND("lxl reload", "ll reload"); + FIX_OLD_COMMAND("lxl version", "ll version"); + FIX_OLD_COMMAND("lxl update", "ll upgrade"); - return true; + return true; } \ No newline at end of file diff --git a/src/main/Configs.h b/src/main/Configs.h index 9daf3182..6200fd20 100644 --- a/src/main/Configs.h +++ b/src/main/Configs.h @@ -1,54 +1,54 @@ #pragma once -#include #include +#include ///////////////////////// Configs ///////////////////////// // Plugins & Base libs path -#define LLSE_DEPENDS_DIR "./plugins/lib" +#define LLSE_DEPENDS_DIR "./plugins/lib" #define LLSE_PLUGINS_LOAD_DIR "./plugins" // Plugin package information -#define LLSE_PLUGIN_PACKAGE_EXTENSION ".llplugin" -#define LLSE_PLUGIN_PACKAGE_TEMP_DIR "./plugins/LiteLoader/temp" +#define LLSE_PLUGIN_PACKAGE_EXTENSION ".llplugin" +#define LLSE_PLUGIN_PACKAGE_TEMP_DIR "./plugins/LiteLoader/temp" #define LLSE_PLUGIN_PACKAGE_UNCOMPRESS_TIMEOUT 30000 // Current language information #define LLSE_BACKEND_NODEJS_NAME "NodeJs" -#define LLSE_BACKEND_JS_NAME "Js" -#define LLSE_BACKEND_LUA_NAME "Lua" +#define LLSE_BACKEND_JS_NAME "Js" +#define LLSE_BACKEND_LUA_NAME "Lua" #define LLSE_BACKEND_PYTHON_NAME "Python" #if defined(LLSE_BACKEND_QUICKJS) // QuickJs - #define LLSE_BACKEND_TYPE LLSE_BACKEND_JS_NAME - #define LLSE_SOURCE_FILE_EXTENSION ".js" - #define LLSE_PLUGINS_ROOT_DIR "plugins" - #define LLSE_IS_PLUGIN_PACKAGE 0 +#define LLSE_BACKEND_TYPE LLSE_BACKEND_JS_NAME +#define LLSE_SOURCE_FILE_EXTENSION ".js" +#define LLSE_PLUGINS_ROOT_DIR "plugins" +#define LLSE_IS_PLUGIN_PACKAGE 0 #elif defined(LLSE_BACKEND_LUA) // Lua - #define LLSE_BACKEND_TYPE LLSE_BACKEND_LUA_NAME - #define LLSE_SOURCE_FILE_EXTENSION ".lua" - #define LLSE_PLUGINS_ROOT_DIR "plugins" - #define LLSE_IS_PLUGIN_PACKAGE 0 +#define LLSE_BACKEND_TYPE LLSE_BACKEND_LUA_NAME +#define LLSE_SOURCE_FILE_EXTENSION ".lua" +#define LLSE_PLUGINS_ROOT_DIR "plugins" +#define LLSE_IS_PLUGIN_PACKAGE 0 #elif defined(LLSE_BACKEND_NODEJS) // NodeJs - #define LLSE_BACKEND_TYPE LLSE_BACKEND_NODEJS_NAME - #define LLSE_SOURCE_FILE_EXTENSION ".js" - #define LLSE_PLUGINS_ROOT_DIR "plugins/nodejs" - #define LLSE_IS_PLUGIN_PACKAGE 1 +#define LLSE_BACKEND_TYPE LLSE_BACKEND_NODEJS_NAME +#define LLSE_SOURCE_FILE_EXTENSION ".js" +#define LLSE_PLUGINS_ROOT_DIR "plugins/nodejs" +#define LLSE_IS_PLUGIN_PACKAGE 1 #elif defined(LLSE_BACKEND_PYTHON) // Python - #define LLSE_BACKEND_TYPE LLSE_BACKEND_PYTHON_NAME - #define LLSE_SOURCE_FILE_EXTENSION ".py" - #define LLSE_PLUGINS_ROOT_DIR "plugins/python" - #define LLSE_IS_PLUGIN_PACKAGE 1 +#define LLSE_BACKEND_TYPE LLSE_BACKEND_PYTHON_NAME +#define LLSE_SOURCE_FILE_EXTENSION ".py" +#define LLSE_PLUGINS_ROOT_DIR "plugins/python" +#define LLSE_IS_PLUGIN_PACKAGE 1 #endif @@ -58,46 +58,45 @@ // All backends information -#define LLSE_MODULE_TYPE LLSE_BACKEND_TYPE -#define LLSE_VALID_BACKENDS std::vector({"Js", "Lua", "NodeJs", "Python"}) -#define LLSE_VALID_PLUGIN_EXTENSIONS std::vector({".js", ".lua", "", ".py"}) -#define LLSE_VALID_PLUGIN_PACKAGE_IDENTIFIER \ - std::vector({"", "", "package.json", "pyproject.toml"}) -#define LLSE_VALID_BACKENDS_COUNT LLSE_VALID_BACKENDS.size() +#define LLSE_MODULE_TYPE LLSE_BACKEND_TYPE +#define LLSE_VALID_BACKENDS std::vector({"Js", "Lua", "NodeJs", "Python"}) +#define LLSE_VALID_PLUGIN_EXTENSIONS std::vector({".js", ".lua", "", ".py"}) +#define LLSE_VALID_PLUGIN_PACKAGE_IDENTIFIER std::vector({"", "", "package.json", "pyproject.toml"}) +#define LLSE_VALID_BACKENDS_COUNT LLSE_VALID_BACKENDS.size() // Loader information #if defined(LLSE_BACKEND_NODEJS) - #define LLSE_LOADER_NAME "ScriptEngine-NodeJs" - #define LLSE_LOADER_DESCRIPTION "Node.js ScriptEngine for LiteLoaderBDS" +#define LLSE_LOADER_NAME "ScriptEngine-NodeJs" +#define LLSE_LOADER_DESCRIPTION "Node.js ScriptEngine for LiteLoaderBDS" #elif defined(LLSE_BACKEND_QUICKJS) - #define LLSE_LOADER_NAME "ScriptEngine-QuickJs" - #define LLSE_LOADER_DESCRIPTION "Javascript ScriptEngine for LiteLoaderBDS" +#define LLSE_LOADER_NAME "ScriptEngine-QuickJs" +#define LLSE_LOADER_DESCRIPTION "Javascript ScriptEngine for LiteLoaderBDS" #elif defined(LLSE_BACKEND_LUA) - #define LLSE_LOADER_NAME "ScriptEngine-Lua" - #define LLSE_LOADER_DESCRIPTION "Lua ScriptEngine for LiteLoaderBDS" +#define LLSE_LOADER_NAME "ScriptEngine-Lua" +#define LLSE_LOADER_DESCRIPTION "Lua ScriptEngine for LiteLoaderBDS" #elif defined(LLSE_BACKEND_PYTHON) - #define LLSE_LOADER_NAME "ScriptEngine-Python" - #define LLSE_LOADER_DESCRIPTION "Python ScriptEngine for LiteLoaderBDS" +#define LLSE_LOADER_NAME "ScriptEngine-Python" +#define LLSE_LOADER_DESCRIPTION "Python ScriptEngine for LiteLoaderBDS" #endif // Debug engine information #if defined(LLSE_BACKEND_NODEJS) - #define LLSE_DEBUG_CMD "nodejsdebug" +#define LLSE_DEBUG_CMD "nodejsdebug" #elif defined(LLSE_BACKEND_QUICKJS) - #define LLSE_DEBUG_CMD "jsdebug" +#define LLSE_DEBUG_CMD "jsdebug" #elif defined(LLSE_BACKEND_LUA) - #define LLSE_DEBUG_CMD "luadebug" +#define LLSE_DEBUG_CMD "luadebug" #elif defined(LLSE_BACKEND_PYTHON) - #define LLSE_DEBUG_CMD "pydebug" +#define LLSE_DEBUG_CMD "pydebug" #endif #define LLSE_DEBUG_ENGINE_NAME "__LLSE_DEBUG_ENGINE__" // Global communication -#define LLSE_GLOBAL_DATA_NAME L"LLSE_GLOBAL_DATA_SECTION" -#define LLSE_REMOTE_CALL_EVENT_NAME L"LLSE_REMOTE_CALL_EVENT" +#define LLSE_GLOBAL_DATA_NAME L"LLSE_GLOBAL_DATA_SECTION" +#define LLSE_REMOTE_CALL_EVENT_NAME L"LLSE_REMOTE_CALL_EVENT" #define LLSE_MESSAGE_SYSTEM_WAIT_CHECK_INTERVAL 5 diff --git a/src/main/EconomicSystem.h b/src/main/EconomicSystem.h index 68f5c979..b3a4e1f1 100644 --- a/src/main/EconomicSystem.h +++ b/src/main/EconomicSystem.h @@ -4,19 +4,18 @@ using std::string; -typedef long long money_t; +typedef long long money_t; typedef std::string xuid_t; class EconomySystem { public: - static bool init(); + static bool init(); - static money_t getMoney(xuid_t player); - static bool setMoney(xuid_t player, money_t money); - static bool addMoney(xuid_t player, money_t money); - static bool reduceMoney(xuid_t player, money_t money); - static bool transMoney(xuid_t player1, xuid_t player2, money_t money, - string const ¬es); - static std::string getMoneyHist(xuid_t player, int time); - static void clearMoneyHist(int time); + static money_t getMoney(xuid_t player); + static bool setMoney(xuid_t player, money_t money); + static bool addMoney(xuid_t player, money_t money); + static bool reduceMoney(xuid_t player, money_t money); + static bool transMoney(xuid_t player1, xuid_t player2, money_t money, string const& notes); + static std::string getMoneyHist(xuid_t player, int time); + static void clearMoneyHist(int time); }; \ No newline at end of file diff --git a/src/main/EconomySystem.cpp b/src/main/EconomySystem.cpp index f9e76025..773cd4a0 100644 --- a/src/main/EconomySystem.cpp +++ b/src/main/EconomySystem.cpp @@ -10,32 +10,23 @@ ll::Logger economicLogger("EconomicSystem"); ////////////// Helper ////////////// bool EconomySystem::init() { - LLMoney_ListenBeforeEvent(MoneyBeforeEventCallback); - LLMoney_ListenAfterEvent(MoneyEventCallback); - return true; + LLMoney_ListenBeforeEvent(MoneyBeforeEventCallback); + LLMoney_ListenAfterEvent(MoneyEventCallback); + return true; } money_t EconomySystem::getMoney(xuid_t player) { return LLMoney_Get(player); } -bool EconomySystem::setMoney(xuid_t player, money_t money) { - return LLMoney_Set(player, money); -} +bool EconomySystem::setMoney(xuid_t player, money_t money) { return LLMoney_Set(player, money); } -bool EconomySystem::addMoney(xuid_t player, money_t money) { - return LLMoney_Set(player, LLMoney_Get(player) + money); -} +bool EconomySystem::addMoney(xuid_t player, money_t money) { return LLMoney_Set(player, LLMoney_Get(player) + money); } -bool EconomySystem::reduceMoney(xuid_t player, money_t money) { - return LLMoney_Reduce(player, money); -} +bool EconomySystem::reduceMoney(xuid_t player, money_t money) { return LLMoney_Reduce(player, money); } -bool EconomySystem::transMoney(xuid_t player1, xuid_t player2, money_t money, - string const ¬es) { - return LLMoney_Trans(player1, player2, money, notes); +bool EconomySystem::transMoney(xuid_t player1, xuid_t player2, money_t money, string const& notes) { + return LLMoney_Trans(player1, player2, money, notes); } -std::string EconomySystem::getMoneyHist(xuid_t player, int time) { - return LLMoney_GetHist(player, time); -} +std::string EconomySystem::getMoneyHist(xuid_t player, int time) { return LLMoney_GetHist(player, time); } void EconomySystem::clearMoneyHist(int time) { LLMoney_ClearHist(time); } diff --git a/src/main/Global.cpp b/src/main/Global.cpp index 732c1560..1491e890 100644 --- a/src/main/Global.cpp +++ b/src/main/Global.cpp @@ -1,7 +1,7 @@ -#include "main/Global.hpp" +#include "main/Global.h" // 声明 class Scoreboard; // 全局变量 -bool isCmdRegisterEnabled = false; \ No newline at end of file +bool isCmdRegisterEnabled = false; diff --git a/src/main/Global.h b/src/main/Global.h new file mode 100644 index 00000000..df308565 --- /dev/null +++ b/src/main/Global.h @@ -0,0 +1,83 @@ +#pragma once + +#include "ll/api/i18n/I18nAPI.h" +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#ifndef CPPHTTPLIB_OPENSSL_SUPPORT +#define CPPHTTPLIB_OPENSSL_SUPPORT +#endif + +#include "main/Configs.h" +#include "utils/JsonHelper.h" +#include +#include + +#include "ll/api/Logger.h" +#include "ll/api/service/Bedrock.h" +#include "mc/math/Vec3.h" +#include "mc/world/level/BlockPos.h" + +using std::string; +using std::vector; + +// 全局工具 +extern ll::Logger logger; +extern ordered_json globalConfig; + +typedef unsigned long long QWORD; + +class IntVec4 { +public: + int x, y, z; + int dim; + + inline BlockPos getBlockPos() { return {x, y, z}; } + + inline int getDimensionId() { return dim; } +}; + +class FloatVec4 { +public: + float x, y, z; + int dim; + + inline Vec3 getVec3() { return {x, y, z}; } + + inline int getDimensionId() { return dim; } + + inline IntVec4 toIntVec4() { + auto px = (int)x; + auto py = (int)y; + auto pz = (int)z; + if (px < 0 && px != x) px = px - 1; + if (py < 0 && py != y) py = py - 1; + if (pz < 0 && pz != z) pz = pz - 1; + return {px, py, pz, dim}; + } +}; + +using ll::i18n::detail::tr; +using ll::i18n_literals::operator""_tr; + +inline std::string DimId2Name(int dimid) { + std::string name; + switch (dimid) { + case 0: + name = tr("base.getDimName.0"); + break; + case 1: + name = tr("base.getDimName.1"); + break; + case 2: + name = tr("base.getDimName.2"); + break; + default: + name = tr("base.getDimName.unknown"); + break; + } + return name; +} + +// 全局变量 +extern bool isCmdRegisterEnabled; \ No newline at end of file diff --git a/src/main/Global.hpp b/src/main/Global.hpp deleted file mode 100644 index de283b71..00000000 --- a/src/main/Global.hpp +++ /dev/null @@ -1,86 +0,0 @@ -#pragma once - -#include "ll/api/i18n/I18nAPI.h" -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#ifndef CPPHTTPLIB_OPENSSL_SUPPORT -#define CPPHTTPLIB_OPENSSL_SUPPORT -#endif - -#include "main/Configs.h" -#include "utils/JsonHelper.h" -#include -#include - -#include "ll/api/Logger.h" -#include "ll/api/service/Bedrock.h" -#include "mc/math/Vec3.h" -#include "mc/world/level/BlockPos.h" - -using std::string; -using std::vector; - -// 全局工具 -extern ll::Logger logger; -extern ordered_json globalConfig; - -typedef unsigned long long QWORD; - -class IntVec4 { -public: - int x, y, z; - int dim; - - inline BlockPos getBlockPos() { return {x, y, z}; } - - inline int getDimensionId() { return dim; } -}; - -class FloatVec4 { -public: - float x, y, z; - int dim; - - inline Vec3 getVec3() { return {x, y, z}; } - - inline int getDimensionId() { return dim; } - - inline IntVec4 toIntVec4() { - auto px = (int)x; - auto py = (int)y; - auto pz = (int)z; - if (px < 0 && px != x) - px = px - 1; - if (py < 0 && py != y) - py = py - 1; - if (pz < 0 && pz != z) - pz = pz - 1; - return {px, py, pz, dim}; - } -}; - -using ll::i18n::detail::tr; -using ll::i18n_literals::operator""_tr; - -inline std::string DimId2Name(int dimid) { - std::string name; - switch (dimid) { - case 0: - name = tr("base.getDimName.0"); - break; - case 1: - name = tr("base.getDimName.1"); - break; - case 2: - name = tr("base.getDimName.2"); - break; - default: - name = tr("base.getDimName.unknown"); - break; - } - return name; -} - -// 全局变量 -extern bool isCmdRegisterEnabled; \ No newline at end of file diff --git a/src/main/Loader.cpp b/src/main/Loader.cpp index bc87e46b..e304138b 100644 --- a/src/main/Loader.cpp +++ b/src/main/Loader.cpp @@ -21,70 +21,64 @@ extern ll::Logger logger; std::unordered_map depends; // Debug engine -ScriptEngine *debugEngine; -bool isInConsoleDebugMode = false; +ScriptEngine* debugEngine; +bool isInConsoleDebugMode = false; // Pre-declared -extern void BindAPIs(ScriptEngine *engine); +extern void BindAPIs(ScriptEngine* engine); // Pre-load dependency void LoadDepends() { #ifdef LLSE_BACKEND_NODEJS - return; // NodeJs backend load depends code in another place + return; // NodeJs backend load depends code in another place #endif - std::filesystem::directory_iterator deps(LLSE_DEPENDS_DIR); - for (auto &i : deps) { - if (i.is_regular_file() && - i.path().filename() == string("BaseLib") + LLSE_SOURCE_FILE_EXTENSION) { - try { - auto path = ll::string_utils::u8str2str(i.path().generic_u8string()); - auto content = ReadAllFile(path); - if (!content) - throw("Fail to open plugin file!"); - depends.emplace(path, *content); - logger.info( - "llse.loader.loadDepends.success"_tr(i.path().filename().string())); - } catch (std::exception e) { - logger.warn( - "llse.loader.loadDepends.fail"_tr(i.path().filename().string())); - logger.warn(ll::string_utils::tou8str(e.what())); - } catch (...) { - logger.warn( - "llse.loader.loadDepends.fail"_tr(i.path().filename().string())); - } + std::filesystem::directory_iterator deps(LLSE_DEPENDS_DIR); + for (auto& i : deps) { + if (i.is_regular_file() && i.path().filename() == string("BaseLib") + LLSE_SOURCE_FILE_EXTENSION) { + try { + auto path = ll::string_utils::u8str2str(i.path().generic_u8string()); + auto content = ReadAllFile(path); + if (!content) throw("Fail to open plugin file!"); + depends.emplace(path, *content); + logger.info("llse.loader.loadDepends.success"_tr(i.path().filename().string())); + } catch (std::exception e) { + logger.warn("llse.loader.loadDepends.fail"_tr(i.path().filename().string())); + logger.warn(ll::string_utils::tou8str(e.what())); + } catch (...) { + logger.warn("llse.loader.loadDepends.fail"_tr(i.path().filename().string())); + } + } } - } } // Load debug engine void LoadDebugEngine() { #ifdef LLSE_BACKEND_NODEJS - return; // NodeJs backend didn't enable debug engine now + return; // NodeJs backend didn't enable debug engine now #endif - // Create engine - debugEngine = EngineManager::newEngine(LLSE_DEBUG_ENGINE_NAME); - EngineScope enter(debugEngine); + // Create engine + debugEngine = EngineManager::newEngine(LLSE_DEBUG_ENGINE_NAME); + EngineScope enter(debugEngine); - // Bind APIs - try { - BindAPIs(debugEngine); - } catch (const Exception &e) { - logger.error("Fail in binding Debug Engine!\n"); - throw; - } + // Bind APIs + try { + BindAPIs(debugEngine); + } catch (const Exception& e) { + logger.error("Fail in binding Debug Engine!\n"); + throw; + } - // Load baselibs - try { - for (auto &[path, content] : depends) { - if (!content.empty()) - debugEngine->eval(content, path); + // Load baselibs + try { + for (auto& [path, content] : depends) { + if (!content.empty()) debugEngine->eval(content, path); + } + } catch (const Exception& e) { + logger.error("Fail in Loading Dependence Lib!\n"); + throw; } - } catch (const Exception &e) { - logger.error("Fail in Loading Dependence Lib!\n"); - throw; - } } // Main load procedure @@ -92,174 +86,149 @@ void LoadMain_Package(); void LoadMain() { #if LLSE_IS_PLUGIN_PACKAGE - // Load plugin package - LoadMain_Package(); + // Load plugin package + LoadMain_Package(); #else - // Load simple file plugin - logger.info( - "llse.loader.loadMain.start"_tr(fmt::arg("type", LLSE_MODULE_TYPE))); - int count = 0; - std::filesystem::directory_iterator files(LLSE_PLUGINS_LOAD_DIR); - for (auto &i : files) { - if (i.is_regular_file() && - i.path().extension() == LLSE_SOURCE_FILE_EXTENSION) { - try { - // Todo - // if (PluginManager::loadPlugin( - // ll::string_utils::u8str2str(i.path().generic_u8string()), - // false, true)) - ++count; - } catch (...) { - } + // Load simple file plugin + logger.info("llse.loader.loadMain.start"_tr(fmt::arg("type", LLSE_MODULE_TYPE))); + int count = 0; + std::filesystem::directory_iterator files(LLSE_PLUGINS_LOAD_DIR); + for (auto& i : files) { + if (i.is_regular_file() && i.path().extension() == LLSE_SOURCE_FILE_EXTENSION) { + try { + // Todo + // if (PluginManager::loadPlugin( + // ll::string_utils::u8str2str(i.path().generic_u8string()), + // false, true)) + ++count; + } catch (...) {} + } } - } - logger.info("llse.loader.loadMain.done"_tr( - fmt::arg("count", count), fmt::arg("type", LLSE_MODULE_TYPE))); + logger.info("llse.loader.loadMain.done"_tr(fmt::arg("count", count), fmt::arg("type", LLSE_MODULE_TYPE))); #endif } #ifdef LLSE_BACKEND_NODEJS // NodeJs后端 - 主加载 void LoadMain_NodeJs() { - logger.info(tr("llse.loader.loadMain.start", fmt::arg("type", "Node.js"))); - int installCount = 0; - int count = 0; - - // Load plugins in NODEJS_ROOT_DIR - std::filesystem::directory_iterator files(LLSE_PLUGINS_ROOT_DIR); - for (auto &i : files) { - std::filesystem::path pth = i.path(); - std::string targetDirStr = - ll::string_utils::u8str2str(pth.make_preferred().u8string()); - if (i.is_directory() && pth.filename() != "node_modules") { - if (std::filesystem::exists(pth / "package.json")) { - try { - if (PluginManager::loadPlugin(targetDirStr, false, true)) { - ++count; - } - } catch (...) { + logger.info(tr("llse.loader.loadMain.start", fmt::arg("type", "Node.js"))); + int installCount = 0; + int count = 0; + + // Load plugins in NODEJS_ROOT_DIR + std::filesystem::directory_iterator files(LLSE_PLUGINS_ROOT_DIR); + for (auto& i : files) { + std::filesystem::path pth = i.path(); + std::string targetDirStr = ll::string_utils::u8str2str(pth.make_preferred().u8string()); + if (i.is_directory() && pth.filename() != "node_modules") { + if (std::filesystem::exists(pth / "package.json")) { + try { + if (PluginManager::loadPlugin(targetDirStr, false, true)) { + ++count; + } + } catch (...) {} + } else { + logger.warn(tr("llse.loader.loadMain.nodejs.ignored", fmt::arg("path", targetDirStr))); + } } - } else { - logger.warn(tr("llse.loader.loadMain.nodejs.ignored", - fmt::arg("path", targetDirStr))); - } } - } - // Unpack .llplugin & install - // Tips: Must after plugins loaded in NODEJS_ROOT_DIR - files = std::filesystem::directory_iterator(LLSE_PLUGINS_LOAD_DIR); - for (auto &i : files) { - std::filesystem::path pth = i.path(); - std::string packFilePathStr = - ll::string_utils::u8str2str(pth.make_preferred().u8string()); - if (i.is_regular_file() && - packFilePathStr.ends_with(LLSE_PLUGIN_PACKAGE_EXTENSION)) { - logger.info(tr("llse.loader.loadMain.nodejs.installPack.start", - fmt::arg("path", packFilePathStr))); - try { - if (!PluginManager::loadPlugin(packFilePathStr, false, true)) { - logger.error(tr("llse.loader.loadMain.nodejs.installPack.fail", - packFilePathStr)); + // Unpack .llplugin & install + // Tips: Must after plugins loaded in NODEJS_ROOT_DIR + files = std::filesystem::directory_iterator(LLSE_PLUGINS_LOAD_DIR); + for (auto& i : files) { + std::filesystem::path pth = i.path(); + std::string packFilePathStr = ll::string_utils::u8str2str(pth.make_preferred().u8string()); + if (i.is_regular_file() && packFilePathStr.ends_with(LLSE_PLUGIN_PACKAGE_EXTENSION)) { + logger.info(tr("llse.loader.loadMain.nodejs.installPack.start", fmt::arg("path", packFilePathStr))); + try { + if (!PluginManager::loadPlugin(packFilePathStr, false, true)) { + logger.error(tr("llse.loader.loadMain.nodejs.installPack.fail", packFilePathStr)); + } + ++count; + ++installCount; + } catch (...) { + // not matched backend type + logger.warn(tr("llse.loader.loadMain.nodejs.ignored", fmt::arg("path", packFilePathStr))); + } } - ++count; - ++installCount; - } catch (...) { - // not matched backend type - logger.warn(tr("llse.loader.loadMain.nodejs.ignored", - fmt::arg("path", packFilePathStr))); - } } - } - logger.info(tr("llse.loader.loadMain.done", fmt::arg("count", count), - fmt::arg("type", "Node.js"))); + logger.info(tr("llse.loader.loadMain.done", fmt::arg("count", count), fmt::arg("type", "Node.js"))); } #endif #ifdef LLSE_BACKEND_PYTHON // Python后端 - 主加载 void LoadMain_Python() { - logger.info(tr("llse.loader.loadMain.start", fmt::arg("type", "Python"))); - int installCount = 0; - int count = 0; - - // Load plugins in PYTHON_ROOT_DIR - std::filesystem::directory_iterator files(LLSE_PLUGINS_ROOT_DIR); - for (auto &i : files) { - std::filesystem::path pth = i.path(); - std::string targetDirStr = - ll::string_utils::u8str2str(pth.make_preferred().u8string()); - if (i.is_directory() && pth.filename() != "site-packages") { - if (std::filesystem::exists(pth / "pyproject.toml")) { - try { - if (PluginManager::loadPlugin(targetDirStr, false, true)) { - ++count; - } - } catch (...) { + logger.info(tr("llse.loader.loadMain.start", fmt::arg("type", "Python"))); + int installCount = 0; + int count = 0; + + // Load plugins in PYTHON_ROOT_DIR + std::filesystem::directory_iterator files(LLSE_PLUGINS_ROOT_DIR); + for (auto& i : files) { + std::filesystem::path pth = i.path(); + std::string targetDirStr = ll::string_utils::u8str2str(pth.make_preferred().u8string()); + if (i.is_directory() && pth.filename() != "site-packages") { + if (std::filesystem::exists(pth / "pyproject.toml")) { + try { + if (PluginManager::loadPlugin(targetDirStr, false, true)) { + ++count; + } + } catch (...) {} + } else { + logger.warn(tr("llse.loader.loadMain.python.ignored", fmt::arg("path", targetDirStr))); + } } - } else { - logger.warn(tr("llse.loader.loadMain.python.ignored", - fmt::arg("path", targetDirStr))); - } } - } - // Unpack .llplugin & install - // Tips: Must after plugins loaded in PYTHON_ROOT_DIR - files = std::filesystem::directory_iterator(LLSE_PLUGINS_LOAD_DIR); - for (auto &i : files) { - std::filesystem::path pth = i.path(); - std::string packFilePathStr = - ll::string_utils::u8str2str(pth.make_preferred().u8string()); - if (i.is_regular_file() && - packFilePathStr.ends_with(LLSE_PLUGIN_PACKAGE_EXTENSION)) { - logger.info(tr("llse.loader.loadMain.python.installPack.start", - fmt::arg("path", packFilePathStr))); - try { - if (!PluginManager::loadPlugin(packFilePathStr, false, true)) { - logger.error(tr("llse.loader.loadMain.python.installPack.fail", - packFilePathStr)); + // Unpack .llplugin & install + // Tips: Must after plugins loaded in PYTHON_ROOT_DIR + files = std::filesystem::directory_iterator(LLSE_PLUGINS_LOAD_DIR); + for (auto& i : files) { + std::filesystem::path pth = i.path(); + std::string packFilePathStr = ll::string_utils::u8str2str(pth.make_preferred().u8string()); + if (i.is_regular_file() && packFilePathStr.ends_with(LLSE_PLUGIN_PACKAGE_EXTENSION)) { + logger.info(tr("llse.loader.loadMain.python.installPack.start", fmt::arg("path", packFilePathStr))); + try { + if (!PluginManager::loadPlugin(packFilePathStr, false, true)) { + logger.error(tr("llse.loader.loadMain.python.installPack.fail", packFilePathStr)); + } + ++count; + ++installCount; + } catch (...) { + // not matched backend type + logger.warn(tr("llse.loader.loadMain.python.ignored", packFilePathStr)); + } } - ++count; - ++installCount; - } catch (...) { - // not matched backend type - logger.warn(tr("llse.loader.loadMain.python.ignored", packFilePathStr)); - } } - } - // Load single-file plugin - files = std::filesystem::directory_iterator(LLSE_PLUGINS_LOAD_DIR); - for (auto &i : files) { - if (i.is_regular_file() && - i.path().extension() == LLSE_SOURCE_FILE_EXTENSION) { - try { - if (PluginManager::loadPlugin( - ll::string_utils::u8str2str(i.path().generic_u8string()), false, - true)) - ++count; - } catch (...) { - } + // Load single-file plugin + files = std::filesystem::directory_iterator(LLSE_PLUGINS_LOAD_DIR); + for (auto& i : files) { + if (i.is_regular_file() && i.path().extension() == LLSE_SOURCE_FILE_EXTENSION) { + try { + if (PluginManager::loadPlugin(ll::string_utils::u8str2str(i.path().generic_u8string()), false, true)) + ++count; + } catch (...) {} + } } - } - logger.info(tr("llse.loader.loadMain.done", fmt::arg("count", count), - fmt::arg("type", "Python"))); + logger.info(tr("llse.loader.loadMain.done", fmt::arg("count", count), fmt::arg("type", "Python"))); } #endif void LoadMain_Package() { #ifdef LLSE_BACKEND_NODEJS - // Process NodeJs backend's plugin load separately - LoadMain_NodeJs(); - return; + // Process NodeJs backend's plugin load separately + LoadMain_NodeJs(); + return; #elif defined(LLSE_BACKEND_PYTHON) - // Process Python backend's plugin load separately - LoadMain_Python(); - return; + // Process Python backend's plugin load separately + LoadMain_Python(); + return; #endif } \ No newline at end of file diff --git a/src/main/Loader.h b/src/main/Loader.h index 0c00d9b2..ab1e3c93 100644 --- a/src/main/Loader.h +++ b/src/main/Loader.h @@ -4,8 +4,8 @@ #include -// Baselibs dependency +// Baselibs dependency extern std::unordered_map depends; // Pre-declared -extern void BindAPIs(ScriptEngine *engine); \ No newline at end of file +extern void BindAPIs(ScriptEngine* engine); \ No newline at end of file diff --git a/src/main/NodeJsHelper.cpp b/src/main/NodeJsHelper.cpp index 46dd1b3b..ee365c7e 100644 --- a/src/main/NodeJsHelper.cpp +++ b/src/main/NodeJsHelper.cpp @@ -7,7 +7,7 @@ #include "engine/EngineManager.h" #include "engine/EngineOwnData.h" #include "engine/RemoteCall.h" -#include "main/Global.hpp" +#include "main/Global.h" #include "main/NodeJsHelper.h" #include #include @@ -17,525 +17,481 @@ // pre-declare -extern void BindAPIs(ScriptEngine *engine); +extern void BindAPIs(ScriptEngine* engine); namespace NodeJsHelper { -bool nodeJsInited = false; +bool nodeJsInited = false; std::vector args; std::vector exec_args; -std::unique_ptr platform = nullptr; -std::unordered_map environments; -std::unordered_map> *setups = - new std::unordered_map>(); -std::unordered_map isRunning; -std::unordered_map uvLoopTask; +std::unique_ptr platform = nullptr; +std::unordered_map environments; +std::unordered_map>* setups = + new std::unordered_map>(); +std::unordered_map isRunning; +std::unordered_map uvLoopTask; bool initNodeJs() { - // Init NodeJs - WCHAR buf[MAX_PATH]; - GetCurrentDirectory(MAX_PATH, buf); - auto path = wstr2str(buf) + "\\bedrock_server_mod.exe"; - char *cPath = (char *)path.c_str(); - uv_setup_args(1, &cPath); - args = {path}; - std::vector errors; - auto exitCode = node::InitializeNodeWithArgs(&args, &exec_args, &errors); - if (exitCode != 0) { - logger.error("Failed to initialize node! NodeJs plugins won't be loaded"); - return false; - } + // Init NodeJs + WCHAR buf[MAX_PATH]; + GetCurrentDirectory(MAX_PATH, buf); + auto path = wstr2str(buf) + "\\bedrock_server_mod.exe"; + char* cPath = (char*)path.c_str(); + uv_setup_args(1, &cPath); + args = {path}; + std::vector errors; + auto exitCode = node::InitializeNodeWithArgs(&args, &exec_args, &errors); + if (exitCode != 0) { + logger.error("Failed to initialize node! NodeJs plugins won't be loaded"); + return false; + } - // Init V8 - using namespace v8; - platform = - node::MultiIsolatePlatform::Create(std::thread::hardware_concurrency()); - V8::InitializePlatform(platform.get()); - V8::Initialize(); + // Init V8 + using namespace v8; + platform = node::MultiIsolatePlatform::Create(std::thread::hardware_concurrency()); + V8::InitializePlatform(platform.get()); + V8::Initialize(); - nodeJsInited = true; - return true; + nodeJsInited = true; + return true; } void shutdownNodeJs() { - v8::V8::Dispose(); - v8::V8::ShutdownPlatform(); + v8::V8::Dispose(); + v8::V8::ShutdownPlatform(); } -script::ScriptEngine *newEngine() { - if (!nodeJsInited && !initNodeJs()) { - return nullptr; - } - std::vector errors; - std::unique_ptr setup = - node::CommonEnvironmentSetup::Create( - platform.get(), &errors, args, exec_args, - node::EnvironmentFlags::kOwnsProcessState); - // if kOwnsInspector set, inspector_agent.cc:681 - // CHECK_EQ(start_io_thread_async_initialized.exchange(true), false) fail! - - if (!setup) { - for (const std::string &err : errors) - logger.error("CommonEnvironmentSetup Error: {}", err.c_str()); - return nullptr; - } - v8::Isolate *isolate = setup->isolate(); - node::Environment *env = setup->env(); - - v8::Locker locker(isolate); - v8::Isolate::Scope isolate_scope(isolate); - v8::HandleScope handle_scope(isolate); - v8::Context::Scope context_scope(setup->context()); - - script::ScriptEngine *engine = - new script::ScriptEngineImpl({}, isolate, setup->context(), false); - - logger.debug("Initialize ScriptEngine for node.js [{}]", (void *)engine); - environments[engine] = env; - (*setups)[engine] = std::move(setup); - isRunning[env] = true; - - node::AddEnvironmentCleanupHook( - isolate, - [](void *arg) { - static_cast(arg)->destroy(); - logger.debug("Destory ScriptEngine for node.js [{}]", arg); - logger.debug("Destroy EnvironmentCleanupHook"); - }, - engine); - return engine; -} +script::ScriptEngine* newEngine() { + if (!nodeJsInited && !initNodeJs()) { + return nullptr; + } + std::vector errors; + std::unique_ptr setup = node::CommonEnvironmentSetup::Create( + platform.get(), + &errors, + args, + exec_args, + node::EnvironmentFlags::kOwnsProcessState + ); + // if kOwnsInspector set, inspector_agent.cc:681 + // CHECK_EQ(start_io_thread_async_initialized.exchange(true), false) fail! + + if (!setup) { + for (const std::string& err : errors) logger.error("CommonEnvironmentSetup Error: {}", err.c_str()); + return nullptr; + } + v8::Isolate* isolate = setup->isolate(); + node::Environment* env = setup->env(); -bool loadPluginCode(script::ScriptEngine *engine, std::string entryScriptPath, - std::string pluginDirPath) { - auto mainScripts = ReadAllFile(entryScriptPath); - if (!mainScripts) { - return false; - } + v8::Locker locker(isolate); + v8::Isolate::Scope isolate_scope(isolate); + v8::HandleScope handle_scope(isolate); + v8::Context::Scope context_scope(setup->context()); - // Process requireDir - if (!pluginDirPath.ends_with('/')) - pluginDirPath += "/"; - pluginDirPath = ReplaceStr(pluginDirPath, "\\", "/"); - entryScriptPath = ReplaceStr(entryScriptPath, "\\", "/"); + script::ScriptEngine* engine = new script::ScriptEngineImpl({}, isolate, setup->context(), false); - // Find setup - auto it = setups->find(engine); - if (it == setups->end()) - return false; + logger.debug("Initialize ScriptEngine for node.js [{}]", (void*)engine); + environments[engine] = env; + (*setups)[engine] = std::move(setup); + isRunning[env] = true; - auto isolate = it->second->isolate(); - auto env = it->second->env(); + node::AddEnvironmentCleanupHook( + isolate, + [](void* arg) { + static_cast(arg)->destroy(); + logger.debug("Destory ScriptEngine for node.js [{}]", arg); + logger.debug("Destroy EnvironmentCleanupHook"); + }, + engine + ); + return engine; +} - try { - using namespace v8; - EngineScope enter(engine); - - string executeJs = - "const __LLSE_PublicRequire = " - "require('module').createRequire(process.cwd() + '/" + - pluginDirPath + "');" + - "const __LLSE_PublicModule = require('module'); " - "__LLSE_PublicModule.exports = {};" + - "ll.export = ll.exports; ll.import = ll.imports; " - - + "(function (exports, require, module, __filename, __dirname) { " + - *mainScripts + "\n})({}, __LLSE_PublicRequire, __LLSE_PublicModule, '" + - entryScriptPath + "', '" + pluginDirPath + - "'); "; // TODO __filename & __dirname need to be reviewed - // TODO: ESM Support - - // Set exit handler - node::SetProcessExitHandler(env, - [](node::Environment *env_, int exit_code) { - stopEngine(getEngine(env_)); - }); - - // Load code - MaybeLocal loadenv_ret = - node::LoadEnvironment(env, executeJs.c_str()); - if (loadenv_ret.IsEmpty()) // There has been a JS exception. - { - node::Stop(env); - uv_stop(it->second->event_loop()); - return false; +bool loadPluginCode(script::ScriptEngine* engine, std::string entryScriptPath, std::string pluginDirPath) { + auto mainScripts = ReadAllFile(entryScriptPath); + if (!mainScripts) { + return false; } - // Start libuv event loop - uvLoopTask[env] = Schedule::repeat( - [engine, env, isRunningMap{&isRunning}, - eventLoop{it->second->event_loop()}]() { - if (!(ll::getServerStatus() != ll::ServerStatus::Running) && (*isRunningMap)[env]) { - EngineScope enter(engine); - uv_run(eventLoop, UV_RUN_NOWAIT); - } - if ((ll::getServerStatus() != ll::ServerStatus::Running)) { - uv_stop(eventLoop); - logger.debug("Destroy ServerStopping"); - } - }, - 2); + // Process requireDir + if (!pluginDirPath.ends_with('/')) pluginDirPath += "/"; + pluginDirPath = ReplaceStr(pluginDirPath, "\\", "/"); + entryScriptPath = ReplaceStr(entryScriptPath, "\\", "/"); - return true; - } catch (...) { - return false; - } + // Find setup + auto it = setups->find(engine); + if (it == setups->end()) return false; + + auto isolate = it->second->isolate(); + auto env = it->second->env(); + + try { + using namespace v8; + EngineScope enter(engine); + + string executeJs = "const __LLSE_PublicRequire = " + "require('module').createRequire(process.cwd() + '/" + + pluginDirPath + "');" + + "const __LLSE_PublicModule = require('module'); " + "__LLSE_PublicModule.exports = {};" + + "ll.export = ll.exports; ll.import = ll.imports; " + + + "(function (exports, require, module, __filename, __dirname) { " + *mainScripts + + "\n})({}, __LLSE_PublicRequire, __LLSE_PublicModule, '" + entryScriptPath + "', '" + + pluginDirPath + "'); "; // TODO __filename & __dirname need to be reviewed + // TODO: ESM Support + + // Set exit handler + node::SetProcessExitHandler(env, [](node::Environment* env_, int exit_code) { stopEngine(getEngine(env_)); }); + + // Load code + MaybeLocal loadenv_ret = node::LoadEnvironment(env, executeJs.c_str()); + if (loadenv_ret.IsEmpty()) // There has been a JS exception. + { + node::Stop(env); + uv_stop(it->second->event_loop()); + return false; + } + + // Start libuv event loop + uvLoopTask[env] = Schedule::repeat( + [engine, env, isRunningMap{&isRunning}, eventLoop{it->second->event_loop()}]() { + if (!(ll::getServerStatus() != ll::ServerStatus::Running) && (*isRunningMap)[env]) { + EngineScope enter(engine); + uv_run(eventLoop, UV_RUN_NOWAIT); + } + if ((ll::getServerStatus() != ll::ServerStatus::Running)) { + uv_stop(eventLoop); + logger.debug("Destroy ServerStopping"); + } + }, + 2 + ); + + return true; + } catch (...) { + return false; + } } -node::Environment *getEnvironmentOf(script::ScriptEngine *engine) { - auto it = environments.find(engine); - if (it == environments.end()) - return nullptr; - return it->second; +node::Environment* getEnvironmentOf(script::ScriptEngine* engine) { + auto it = environments.find(engine); + if (it == environments.end()) return nullptr; + return it->second; } -v8::Isolate *getIsolateOf(script::ScriptEngine *engine) { - auto it = setups->find(engine); - if (it == setups->end()) - return nullptr; - return it->second->isolate(); +v8::Isolate* getIsolateOf(script::ScriptEngine* engine) { + auto it = setups->find(engine); + if (it == setups->end()) return nullptr; + return it->second->isolate(); } -bool stopEngine(node::Environment *env) { - if (!env) - return false; - try { - // Set flag - isRunning[env] = false; +bool stopEngine(node::Environment* env) { + if (!env) return false; + try { + // Set flag + isRunning[env] = false; - // Stop code executing - node::Stop(env); + // Stop code executing + node::Stop(env); - // Stop libuv event loop - auto it = uvLoopTask.find(env); - if (it != uvLoopTask.end()) { - it->second.cancel(); - } + // Stop libuv event loop + auto it = uvLoopTask.find(env); + if (it != uvLoopTask.end()) { + it->second.cancel(); + } - return true; - } catch (...) { - logger.error("Fail to stop engine {}", (void *)env); - return false; - } + return true; + } catch (...) { + logger.error("Fail to stop engine {}", (void*)env); + return false; + } } -bool stopEngine(script::ScriptEngine *engine) { - logger.info("NodeJs plugin {} exited.", ENGINE_GET_DATA(engine)->pluginName); - auto env = NodeJsHelper::getEnvironmentOf(engine); - return stopEngine(env); +bool stopEngine(script::ScriptEngine* engine) { + logger.info("NodeJs plugin {} exited.", ENGINE_GET_DATA(engine)->pluginName); + auto env = NodeJsHelper::getEnvironmentOf(engine); + return stopEngine(env); } -script::ScriptEngine *getEngine(node::Environment *env) { - for (auto &[engine, environment] : environments) - if (env == environment) - return engine; - return nullptr; +script::ScriptEngine* getEngine(node::Environment* env) { + for (auto& [engine, environment] : environments) + if (env == environment) return engine; + return nullptr; } // Load NodeJs plugin // This function must be called in correct backend -bool loadNodeJsPlugin(std::string dirPath, const std::string &packagePath, - bool isHotLoad) { - // "dirPath" is always public temp dir (LLSE_PLUGIN_PACKAGE_TEMP_DIR) - if (dirPath == LLSE_PLUGIN_PACKAGE_TEMP_DIR) { - // Need to copy from temp dir to installed dir - if (std::filesystem::exists(LLSE_PLUGIN_PACKAGE_TEMP_DIR "/package.json")) { - auto pluginName = - NodeJsHelper::getPluginPackageName(LLSE_PLUGIN_PACKAGE_TEMP_DIR); - if (pluginName.empty()) { - pluginName = UTF82String(filesystem::path(packagePath) - .filename() - .replace_extension("") - .u8string()); - } - auto dest = - std::filesystem::path(LLSE_PLUGINS_ROOT_DIR).append(pluginName); - - // copy files - std::error_code ec; - // if (filesystem::exists(dest)) - // filesystem::remove_all(dest, ec); - std::filesystem::copy(LLSE_PLUGIN_PACKAGE_TEMP_DIR "/", dest, - filesystem::copy_options::overwrite_existing | - filesystem::copy_options::recursive, - ec); - - // reset dirPath - dirPath = UTF82String(dest.u8string()); +bool loadNodeJsPlugin(std::string dirPath, const std::string& packagePath, bool isHotLoad) { + // "dirPath" is always public temp dir (LLSE_PLUGIN_PACKAGE_TEMP_DIR) + if (dirPath == LLSE_PLUGIN_PACKAGE_TEMP_DIR) { + // Need to copy from temp dir to installed dir + if (std::filesystem::exists(LLSE_PLUGIN_PACKAGE_TEMP_DIR "/package.json")) { + auto pluginName = NodeJsHelper::getPluginPackageName(LLSE_PLUGIN_PACKAGE_TEMP_DIR); + if (pluginName.empty()) { + pluginName = UTF82String(filesystem::path(packagePath).filename().replace_extension("").u8string()); + } + auto dest = std::filesystem::path(LLSE_PLUGINS_ROOT_DIR).append(pluginName); + + // copy files + std::error_code ec; + // if (filesystem::exists(dest)) + // filesystem::remove_all(dest, ec); + std::filesystem::copy( + LLSE_PLUGIN_PACKAGE_TEMP_DIR "/", + dest, + filesystem::copy_options::overwrite_existing | filesystem::copy_options::recursive, + ec + ); + + // reset dirPath + dirPath = UTF82String(dest.u8string()); + } + // remove temp dir + std::error_code ec; + std::filesystem::remove_all(LLSE_PLUGIN_PACKAGE_TEMP_DIR, ec); } - // remove temp dir - std::error_code ec; - std::filesystem::remove_all(LLSE_PLUGIN_PACKAGE_TEMP_DIR, ec); - } - std::string entryPath = NodeJsHelper::findEntryScript(dirPath); - if (entryPath.empty()) - return false; - std::string pluginName = NodeJsHelper::getPluginPackageName(dirPath); - - // Run "npm install" if needed - if (NodeJsHelper::doesPluginPackHasDependency(dirPath) && - !filesystem::exists(filesystem::path(dirPath) / "node_modules")) { - int exitCode = 0; - logger.info( - tr("llse.loader.nodejs.executeNpmInstall.start", - fmt::arg( - "name", - UTF82String(filesystem::path(dirPath).filename().u8string())))); - if ((exitCode = NodeJsHelper::executeNpmCommand("npm install", dirPath)) == - 0) - logger.info(tr("llse.loader.nodejs.executeNpmInstall.success")); - else - logger.error(tr("llse.loader.nodejs.executeNpmInstall.fail", - fmt::arg("code", exitCode))); - } - - // Create engine & Load plugin - ScriptEngine *engine = nullptr; - node::Environment *env = nullptr; - try { - engine = EngineManager::newEngine(); - { - EngineScope enter(engine); - // setData - ENGINE_OWN_DATA()->pluginName = pluginName; - ENGINE_OWN_DATA()->pluginFileOrDirPath = dirPath; - ENGINE_OWN_DATA()->logger.title = pluginName; - // bindAPIs - BindAPIs(engine); + std::string entryPath = NodeJsHelper::findEntryScript(dirPath); + if (entryPath.empty()) return false; + std::string pluginName = NodeJsHelper::getPluginPackageName(dirPath); + + // Run "npm install" if needed + if (NodeJsHelper::doesPluginPackHasDependency(dirPath) + && !filesystem::exists(filesystem::path(dirPath) / "node_modules")) { + int exitCode = 0; + logger.info( + tr("llse.loader.nodejs.executeNpmInstall.start", + fmt::arg("name", UTF82String(filesystem::path(dirPath).filename().u8string()))) + ); + if ((exitCode = NodeJsHelper::executeNpmCommand("npm install", dirPath)) == 0) + logger.info(tr("llse.loader.nodejs.executeNpmInstall.success")); + else logger.error(tr("llse.loader.nodejs.executeNpmInstall.fail", fmt::arg("code", exitCode))); } - if (!NodeJsHelper::loadPluginCode(engine, entryPath, dirPath)) - throw "Uncaught exception thrown in code"; - - if (!PluginManager::getPlugin(pluginName)) { - // Plugin did't register itself. Help to register it - string description = pluginName; - ll::Version ver(1, 0, 0); - std::map others = {}; - - // Read information from package.json - try { - std::filesystem::path packageFilePath = - std::filesystem::path(dirPath) / "package.json"; - std::ifstream file( - UTF82String(packageFilePath.make_preferred().u8string())); - nlohmann::json j; - file >> j; - file.close(); - // description - if (j.contains("description")) { - description = j["description"].get(); + // Create engine & Load plugin + ScriptEngine* engine = nullptr; + node::Environment* env = nullptr; + try { + engine = EngineManager::newEngine(); + { + EngineScope enter(engine); + // setData + ENGINE_OWN_DATA()->pluginName = pluginName; + ENGINE_OWN_DATA()->pluginFileOrDirPath = dirPath; + ENGINE_OWN_DATA()->logger.title = pluginName; + // bindAPIs + BindAPIs(engine); } - // version - if (j.contains("version") && j["version"].is_string()) { - ver = ll::Version::parse(j["version"].get()); + if (!NodeJsHelper::loadPluginCode(engine, entryPath, dirPath)) throw "Uncaught exception thrown in code"; + + if (!PluginManager::getPlugin(pluginName)) { + // Plugin did't register itself. Help to register it + string description = pluginName; + ll::Version ver(1, 0, 0); + std::map others = {}; + + // Read information from package.json + try { + std::filesystem::path packageFilePath = std::filesystem::path(dirPath) / "package.json"; + std::ifstream file(UTF82String(packageFilePath.make_preferred().u8string())); + nlohmann::json j; + file >> j; + file.close(); + + // description + if (j.contains("description")) { + description = j["description"].get(); + } + // version + if (j.contains("version") && j["version"].is_string()) { + ver = ll::Version::parse(j["version"].get()); + } + // license + if (j.contains("license") && j["license"].is_string()) { + others["License"] = j["license"].get(); + } else if (j["license"].is_object() && j["license"].contains("url")) { + others["License"] = j["license"]["url"].get(); + } + // repository + if (j.contains("repository") && j["repository"].is_string()) { + others["Repository"] = j["repository"].get(); + } else if (j["repository"].is_object() && j["repository"].contains("url")) { + others["Repository"] = j["repository"]["url"].get(); + } + } catch (...) { + logger.warn(tr("llse.loader.nodejs.register.fail", fmt::arg("name", pluginName))); + } + + // register + PluginManager::registerPlugin(dirPath, pluginName, description, ver, others); } - // license - if (j.contains("license") && j["license"].is_string()) { - others["License"] = j["license"].get(); - } else if (j["license"].is_object() && j["license"].contains("url")) { - others["License"] = j["license"]["url"].get(); + + // Call necessary events when at hot load + if (isHotLoad) LLSECallEventsOnHotLoad(engine); + + // Success + logger.info(tr("llse.loader.loadMain.loadedPlugin", fmt::arg("type", "Node.js"), fmt::arg("name", pluginName))); + return true; + } catch (const Exception& e) { + logger.error("Fail to load " + dirPath + "!"); + if (engine) { + EngineScope enter(engine); + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); + PrintException(e); + ExitEngineScope exit; + + // NodeJs use his own setTimeout, so no need to remove + // LLSERemoveTimeTaskData(engine); + + LLSERemoveAllEventListeners(engine); + LLSERemoveCmdRegister(engine); + LLSERemoveCmdCallback(engine); + LLSERemoveAllExportedFuncs(engine); + + engine->getData().reset(); + EngineManager::unRegisterEngine(engine); } - // repository - if (j.contains("repository") && j["repository"].is_string()) { - others["Repository"] = j["repository"].get(); - } else if (j["repository"].is_object() && - j["repository"].contains("url")) { - others["Repository"] = j["repository"]["url"].get(); + if (engine) { + NodeJsHelper::stopEngine(engine); } - } catch (...) { - logger.warn(tr("llse.loader.nodejs.register.fail", - fmt::arg("name", pluginName))); - } - - // register - PluginManager::registerPlugin(dirPath, pluginName, description, ver, - others); + } catch (const std::exception& e) { + logger.error("Fail to load " + dirPath + "!"); + logger.error(ll::string_utils::tou8str(e.what())); + } catch (...) { + logger.error("Fail to load " + dirPath + "!"); } + return false; +} - // Call necessary events when at hot load - if (isHotLoad) - LLSECallEventsOnHotLoad(engine); +std::string findEntryScript(const std::string& dirPath) { + auto dirPath_obj = std::filesystem::path(dirPath); - // Success - logger.info(tr("llse.loader.loadMain.loadedPlugin", - fmt::arg("type", "Node.js"), fmt::arg("name", pluginName))); - return true; - } catch (const Exception &e) { - logger.error("Fail to load " + dirPath + "!"); - if (engine) { - EngineScope enter(engine); - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); - PrintException(e); - ExitEngineScope exit; - - // NodeJs use his own setTimeout, so no need to remove - // LLSERemoveTimeTaskData(engine); - - LLSERemoveAllEventListeners(engine); - LLSERemoveCmdRegister(engine); - LLSERemoveCmdCallback(engine); - LLSERemoveAllExportedFuncs(engine); - - engine->getData().reset(); - EngineManager::unRegisterEngine(engine); - } - if (engine) { - NodeJsHelper::stopEngine(engine); - } - } catch (const std::exception &e) { - logger.error("Fail to load " + dirPath + "!"); - logger.error(ll::string_utils::tou8str(e.what())); - } catch (...) { - logger.error("Fail to load " + dirPath + "!"); - } - return false; -} + std::filesystem::path packageFilePath = dirPath_obj / "package.json"; + if (!std::filesystem::exists(packageFilePath)) return ""; -std::string findEntryScript(const std::string &dirPath) { - auto dirPath_obj = std::filesystem::path(dirPath); - - std::filesystem::path packageFilePath = dirPath_obj / "package.json"; - if (!std::filesystem::exists(packageFilePath)) - return ""; - - try { - std::ifstream file( - UTF82String(packageFilePath.make_preferred().u8string())); - nlohmann::json j; - file >> j; - std::string entryFile = "index.js"; - if (j.contains("main")) { - entryFile = j["main"].get(); + try { + std::ifstream file(UTF82String(packageFilePath.make_preferred().u8string())); + nlohmann::json j; + file >> j; + std::string entryFile = "index.js"; + if (j.contains("main")) { + entryFile = j["main"].get(); + } + auto entryPath = std::filesystem::canonical(dirPath_obj / std::filesystem::path(entryFile)); + if (!std::filesystem::exists(entryPath)) return ""; + else return UTF82String(entryPath.u8string()); + } catch (...) { + return ""; } - auto entryPath = std::filesystem::canonical( - dirPath_obj / std::filesystem::path(entryFile)); - if (!std::filesystem::exists(entryPath)) - return ""; - else - return UTF82String(entryPath.u8string()); - } catch (...) { - return ""; - } } -std::string getPluginPackageName(const std::string &dirPath) { - auto dirPath_obj = std::filesystem::path(dirPath); - - std::filesystem::path packageFilePath = - dirPath_obj / std::filesystem::path("package.json"); - if (!std::filesystem::exists(packageFilePath)) - return ""; - - try { - std::ifstream file( - UTF82String(packageFilePath.make_preferred().u8string())); - nlohmann::json j; - file >> j; - std::string packageName = ""; - if (j.contains("name")) { - packageName = j["name"].get(); +std::string getPluginPackageName(const std::string& dirPath) { + auto dirPath_obj = std::filesystem::path(dirPath); + + std::filesystem::path packageFilePath = dirPath_obj / std::filesystem::path("package.json"); + if (!std::filesystem::exists(packageFilePath)) return ""; + + try { + std::ifstream file(UTF82String(packageFilePath.make_preferred().u8string())); + nlohmann::json j; + file >> j; + std::string packageName = ""; + if (j.contains("name")) { + packageName = j["name"].get(); + } + return packageName; + } catch (...) { + return ""; } - return packageName; - } catch (...) { - return ""; - } } -bool doesPluginPackHasDependency(const std::string &dirPath) { - auto dirPath_obj = std::filesystem::path(dirPath); +bool doesPluginPackHasDependency(const std::string& dirPath) { + auto dirPath_obj = std::filesystem::path(dirPath); - std::filesystem::path packageFilePath = - dirPath_obj / std::filesystem::path("package.json"); - if (!std::filesystem::exists(packageFilePath)) - return false; + std::filesystem::path packageFilePath = dirPath_obj / std::filesystem::path("package.json"); + if (!std::filesystem::exists(packageFilePath)) return false; - try { - std::ifstream file( - UTF82String(packageFilePath.make_preferred().u8string())); - nlohmann::json j; - file >> j; - if (j.contains("dependencies")) { - return true; + try { + std::ifstream file(UTF82String(packageFilePath.make_preferred().u8string())); + nlohmann::json j; + file >> j; + if (j.contains("dependencies")) { + return true; + } + return false; + } catch (...) { + return false; } - return false; - } catch (...) { - return false; - } } -bool processConsoleNpmCmd(const std::string &cmd) { +bool processConsoleNpmCmd(const std::string& cmd) { #ifdef LLSE_BACKEND_NODEJS - if (StartsWith(cmd, "npm ")) { - executeNpmCommand(cmd); - return false; - } else - return true; + if (StartsWith(cmd, "npm ")) { + executeNpmCommand(cmd); + return false; + } else return true; #else - return true; + return true; #endif } int executeNpmCommand(std::string cmd, std::string workingDir) { - if (!nodeJsInited && !initNodeJs()) { - return -1; - } - std::vector errors; - std::unique_ptr setup = - node::CommonEnvironmentSetup::Create( - platform.get(), &errors, args, exec_args, - node::EnvironmentFlags::kOwnsProcessState); - // if kOwnsInspector set, inspector_agent.cc:681 - // CHECK_EQ(start_io_thread_async_initialized.exchange(true), false) fail! - - if (!setup) { - for (const std::string &err : errors) - logger.error("CommonEnvironmentSetup Error: {}", err.c_str()); - return -1; - } - v8::Isolate *isolate = setup->isolate(); - node::Environment *env = setup->env(); - int exit_code = 0; - - // Process workingDir - workingDir = ReplaceStr(workingDir, "\\", "/"); - - { - using namespace v8; - v8::Locker locker(isolate); - v8::Isolate::Scope isolate_scope(isolate); - v8::HandleScope handle_scope(isolate); - v8::Context::Scope context_scope(setup->context()); + if (!nodeJsInited && !initNodeJs()) { + return -1; + } + std::vector errors; + std::unique_ptr setup = node::CommonEnvironmentSetup::Create( + platform.get(), + &errors, + args, + exec_args, + node::EnvironmentFlags::kOwnsProcessState + ); + // if kOwnsInspector set, inspector_agent.cc:681 + // CHECK_EQ(start_io_thread_async_initialized.exchange(true), false) fail! + + if (!setup) { + for (const std::string& err : errors) logger.error("CommonEnvironmentSetup Error: {}", err.c_str()); + return -1; + } + v8::Isolate* isolate = setup->isolate(); + node::Environment* env = setup->env(); + int exit_code = 0; - string executeJs = - "const oldCwd = process.cwd();" - "const publicRequire = require('module').createRequire(oldCwd + " - "'/plugins/lib/');" - "require('process').chdir('" + - workingDir + "');" + "publicRequire('npm-js-interface')('" + cmd + - "');" + "require('process').chdir(oldCwd);"; + // Process workingDir + workingDir = ReplaceStr(workingDir, "\\", "/"); - try { - node::SetProcessExitHandler(env, [&](node::Environment *env_, - int exit_code) { node::Stop(env); }); - MaybeLocal loadenv_ret = - node::LoadEnvironment(env, executeJs.c_str()); - if (loadenv_ret.IsEmpty()) // There has been a JS exception. - throw "error"; - exit_code = node::SpinEventLoop(env).FromMaybe(1); - } catch (...) { - logger.error("Fail to execute NPM command. Error occurs"); + { + using namespace v8; + v8::Locker locker(isolate); + v8::Isolate::Scope isolate_scope(isolate); + v8::HandleScope handle_scope(isolate); + v8::Context::Scope context_scope(setup->context()); + + string executeJs = "const oldCwd = process.cwd();" + "const publicRequire = require('module').createRequire(oldCwd + " + "'/plugins/lib/');" + "require('process').chdir('" + + workingDir + "');" + "publicRequire('npm-js-interface')('" + cmd + "');" + + "require('process').chdir(oldCwd);"; + + try { + node::SetProcessExitHandler(env, [&](node::Environment* env_, int exit_code) { node::Stop(env); }); + MaybeLocal loadenv_ret = node::LoadEnvironment(env, executeJs.c_str()); + if (loadenv_ret.IsEmpty()) // There has been a JS exception. + throw "error"; + exit_code = node::SpinEventLoop(env).FromMaybe(1); + } catch (...) { + logger.error("Fail to execute NPM command. Error occurs"); + } } - } - node::Stop(env); - return exit_code; + node::Stop(env); + return exit_code; } } // namespace NodeJsHelper -#endif \ No newline at end of file +#endif diff --git a/src/main/NodeJsHelper.h b/src/main/NodeJsHelper.h index 8788af7a..f5520062 100644 --- a/src/main/NodeJsHelper.h +++ b/src/main/NodeJsHelper.h @@ -2,9 +2,9 @@ #if defined(LLSE_BACKEND_NODEJS) #pragma warning(disable : 4251) #include "main/Configs.h" +#include #include #include -#include #include namespace NodeJsHelper { @@ -12,23 +12,21 @@ namespace NodeJsHelper { bool initNodeJs(); void shutdownNodeJs(); -script::ScriptEngine *newEngine(); -bool stopEngine(script::ScriptEngine *engine); -bool stopEngine(node::Environment *env); -script::ScriptEngine *getEngine(node::Environment *env); +script::ScriptEngine* newEngine(); +bool stopEngine(script::ScriptEngine* engine); +bool stopEngine(node::Environment* env); +script::ScriptEngine* getEngine(node::Environment* env); -bool loadPluginCode(script::ScriptEngine *engine, std::string entryScriptPath, +bool loadPluginCode(script::ScriptEngine* engine, std::string entryScriptPath, std::string pluginDirPath); // raw -bool loadNodeJsPlugin(std::string dirPath, const std::string &packagePath, - bool isHotLoad = false); +bool loadNodeJsPlugin(std::string dirPath, const std::string& packagePath, bool isHotLoad = false); -std::string findEntryScript(const std::string &dirPath); -std::string getPluginPackageName(const std::string &dirPath); -bool doesPluginPackHasDependency(const std::string &dirPath); +std::string findEntryScript(const std::string& dirPath); +std::string getPluginPackageName(const std::string& dirPath); +bool doesPluginPackHasDependency(const std::string& dirPath); -bool processConsoleNpmCmd(const std::string &cmd); -int executeNpmCommand(std::string cmd, - std::string workingDir = LLSE_PLUGINS_ROOT_DIR); +bool processConsoleNpmCmd(const std::string& cmd); +int executeNpmCommand(std::string cmd, std::string workingDir = LLSE_PLUGINS_ROOT_DIR); } // namespace NodeJsHelper diff --git a/src/main/PluginManager.cpp b/src/main/PluginManager.cpp index 976d0266..6fc967df 100644 --- a/src/main/PluginManager.cpp +++ b/src/main/PluginManager.cpp @@ -13,7 +13,7 @@ #include "ll/api/utils/CryptoUtils.h" #include "ll/api/utils/StringUtils.h" #include "main/Configs.h" -#include "main/Global.hpp" +#include "main/Global.h" #include "main/Loader.h" #include #include @@ -27,15 +27,13 @@ #define H(x) do_hash(x) -extern void BindAPIs(ScriptEngine *engine); +extern void BindAPIs(ScriptEngine* engine); // Helper string RemoveRealAllExtension(string fileName) { - int pos = fileName.find("."); - if (pos == string::npos) - return fileName; - else - return fileName.substr(0, pos); + int pos = fileName.find("."); + if (pos == string::npos) return fileName; + else return fileName.substr(0, pos); } // Load plugin @@ -46,376 +44,355 @@ string RemoveRealAllExtension(string fileName) { // will throw exception using ll::string_utils::str2wstr; -bool PluginManager::loadPlugin(const std::string &fileOrDirPath, bool isHotLoad, - bool mustBeCurrentModule) { - if (fileOrDirPath == LLSE_DEBUG_ENGINE_NAME) - return true; - - if (!std::filesystem::exists(ll::string_utils::str2wstr(fileOrDirPath))) { - logger.error("Plugin not found! Check the path you input again."); - return false; - } +bool PluginManager::loadPlugin(const std::string& fileOrDirPath, bool isHotLoad, bool mustBeCurrentModule) { + if (fileOrDirPath == LLSE_DEBUG_ENGINE_NAME) return true; - // Get bacis information - bool isPluginPackage = std::filesystem::is_directory(fileOrDirPath); - string backendType = getPluginBackendType(fileOrDirPath); - if (backendType.empty()) { - logger.error(fileOrDirPath + " is not a valid plugin path!"); - return false; - } - std::filesystem::path p(ll::string_utils::str2wstr(fileOrDirPath)); - string pluginFileName = RemoveRealAllExtension( - ll::string_utils::u8str2str(p.filename().stem().u8string())); - - // Uncompress plugin package if needed - string realPath = fileOrDirPath; - if (backendType == "PluginPackage") { - // Get plugin package - // Clean temp dir first - std::error_code ec; - std::filesystem::remove_all(LLSE_PLUGIN_PACKAGE_TEMP_DIR, ec); - - // Uncompress package to temp dir - string uncompressToDir = LLSE_PLUGIN_PACKAGE_TEMP_DIR; - auto [exitCode, output] = UncompressFile( - fileOrDirPath, uncompressToDir, LLSE_PLUGIN_PACKAGE_UNCOMPRESS_TIMEOUT); - if (exitCode != 0) { - logger.error("Fail to uncompress plugin package at " + fileOrDirPath + - "!"); - logger.debug(output); - return false; + if (!std::filesystem::exists(ll::string_utils::str2wstr(fileOrDirPath))) { + logger.error("Plugin not found! Check the path you input again."); + return false; } - // Re-get backendType - isPluginPackage = true; - realPath = uncompressToDir; - backendType = getPluginBackendType(realPath); - } - - // Re-check backendType - if (backendType.empty() || backendType == "PluginPackage") { - logger.error(pluginFileName + " is not a valid plugin!"); - return false; - } else if (backendType != LLSE_BACKEND_TYPE) { - // Unmatched backend - if (mustBeCurrentModule) - throw Exception("Plugin of not matched backend given!"); - return false; - } - - // Plugin package - if (isPluginPackage) { - bool isUncompressedFirstTime = (realPath != fileOrDirPath); - return loadPluginPackage(realPath, fileOrDirPath, isHotLoad, - isUncompressedFirstTime); - } - - // Single file plugin - // Check duplicated - if (PluginManager::getPlugin(pluginFileName)) { - // logger.error("This plugin has been loaded by LiteLoader. You cannot load - // it twice."); - return false; - } + // Get bacis information + bool isPluginPackage = std::filesystem::is_directory(fileOrDirPath); + string backendType = getPluginBackendType(fileOrDirPath); + if (backendType.empty()) { + logger.error(fileOrDirPath + " is not a valid plugin path!"); + return false; + } + std::filesystem::path p(ll::string_utils::str2wstr(fileOrDirPath)); + string pluginFileName = RemoveRealAllExtension(ll::string_utils::u8str2str(p.filename().stem().u8string())); + + // Uncompress plugin package if needed + string realPath = fileOrDirPath; + if (backendType == "PluginPackage") { + // Get plugin package + // Clean temp dir first + std::error_code ec; + std::filesystem::remove_all(LLSE_PLUGIN_PACKAGE_TEMP_DIR, ec); + + // Uncompress package to temp dir + string uncompressToDir = LLSE_PLUGIN_PACKAGE_TEMP_DIR; + auto [exitCode, output] = + UncompressFile(fileOrDirPath, uncompressToDir, LLSE_PLUGIN_PACKAGE_UNCOMPRESS_TIMEOUT); + if (exitCode != 0) { + logger.error("Fail to uncompress plugin package at " + fileOrDirPath + "!"); + logger.debug(output); + return false; + } - ScriptEngine *engine = nullptr; - try { - // Create script engine - engine = EngineManager::newEngine("", isHotLoad); - EngineScope enter(engine); + // Re-get backendType + isPluginPackage = true; + realPath = uncompressToDir; + backendType = getPluginBackendType(realPath); + } - // setData - ENGINE_OWN_DATA()->pluginName = pluginFileName; - ENGINE_OWN_DATA()->pluginFileOrDirPath = realPath; - ENGINE_OWN_DATA()->logger.title = pluginFileName; + // Re-check backendType + if (backendType.empty() || backendType == "PluginPackage") { + logger.error(pluginFileName + " is not a valid plugin!"); + return false; + } else if (backendType != LLSE_BACKEND_TYPE) { + // Unmatched backend + if (mustBeCurrentModule) throw Exception("Plugin of not matched backend given!"); + return false; + } - // Bind APIs - try { - BindAPIs(engine); - } catch (const Exception &e) { - logger.error("Fail in Binding APIs!\n"); - throw; + // Plugin package + if (isPluginPackage) { + bool isUncompressedFirstTime = (realPath != fileOrDirPath); + return loadPluginPackage(realPath, fileOrDirPath, isHotLoad, isUncompressedFirstTime); } - // Load depend libs - try { - for (auto &[path, content] : depends) { - if (!content.empty()) - engine->eval(content, path); - } - } catch (const Exception &e) { - logger.error("Fail in Loading Dependence Lib!\n"); - throw; + + // Single file plugin + // Check duplicated + if (PluginManager::getPlugin(pluginFileName)) { + // logger.error("This plugin has been loaded by LiteLoader. You cannot load + // it twice."); + return false; } - // Load script + ScriptEngine* engine = nullptr; try { - // Try use loadFile - engine->loadFile(realPath); - } catch (const Exception &e1) { - try { - // loadFile failed. Try use eval instead - auto scripts = ReadAllFile(realPath); - if (!scripts) { - throw std::runtime_error("Fail to open plugin file!"); + // Create script engine + engine = EngineManager::newEngine("", isHotLoad); + EngineScope enter(engine); + + // setData + ENGINE_OWN_DATA()->pluginName = pluginFileName; + ENGINE_OWN_DATA()->pluginFileOrDirPath = realPath; + ENGINE_OWN_DATA()->logger.title = pluginFileName; + + // Bind APIs + try { + BindAPIs(engine); + } catch (const Exception& e) { + logger.error("Fail in Binding APIs!\n"); + throw; + } + // Load depend libs + try { + for (auto& [path, content] : depends) { + if (!content.empty()) engine->eval(content, path); + } + } catch (const Exception& e) { + logger.error("Fail in Loading Dependence Lib!\n"); + throw; } - engine->eval(*scripts, ENGINE_OWN_DATA()->pluginFileOrDirPath); - } catch (const Exception &e2) { - // Fail - logger.error("Fail in Loading Script Plugin!\n"); - throw e1; // throw the original exception out - } - } - std::string const &pluginName = ENGINE_OWN_DATA()->pluginName; - ExitEngineScope exit; - - // If plugin itself doesn't register, help it to do so - if (!PluginManager::getPlugin(pluginName)) - PluginManager::registerPlugin(realPath, pluginName, pluginName, - ll::Version(1, 0, 0), {}); - - // Call necessary events when at hot load - if (isHotLoad) - LLSECallEventsOnHotLoad(engine); - // Success - logger.info("llse.loader.loadMain.loadedPlugin"_tr( - fmt::arg("type", backendType), fmt::arg("name", pluginName))); - return true; - } catch (const Exception &e) { - logger.error("Fail to load " + realPath + "!"); - if (engine) { - EngineScope enter(engine); - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); - PrintException(e); - ExitEngineScope exit; - - LLSERemoveTimeTaskData(engine); - LLSERemoveAllEventListeners(engine); - LLSERemoveCmdRegister(engine); - LLSERemoveCmdCallback(engine); - LLSERemoveAllExportedFuncs(engine); - - engine->getData().reset(); - EngineManager::unRegisterEngine(engine); - } - if (engine) { - engine->destroy(); + // Load script + try { + // Try use loadFile + engine->loadFile(realPath); + } catch (const Exception& e1) { + try { + // loadFile failed. Try use eval instead + auto scripts = ReadAllFile(realPath); + if (!scripts) { + throw std::runtime_error("Fail to open plugin file!"); + } + engine->eval(*scripts, ENGINE_OWN_DATA()->pluginFileOrDirPath); + } catch (const Exception& e2) { + // Fail + logger.error("Fail in Loading Script Plugin!\n"); + throw e1; // throw the original exception out + } + } + std::string const& pluginName = ENGINE_OWN_DATA()->pluginName; + ExitEngineScope exit; + + // If plugin itself doesn't register, help it to do so + if (!PluginManager::getPlugin(pluginName)) + PluginManager::registerPlugin(realPath, pluginName, pluginName, ll::Version(1, 0, 0), {}); + + // Call necessary events when at hot load + if (isHotLoad) LLSECallEventsOnHotLoad(engine); + + // Success + logger.info("llse.loader.loadMain.loadedPlugin"_tr(fmt::arg("type", backendType), fmt::arg("name", pluginName)) + ); + return true; + } catch (const Exception& e) { + logger.error("Fail to load " + realPath + "!"); + if (engine) { + EngineScope enter(engine); + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); + PrintException(e); + ExitEngineScope exit; + + LLSERemoveTimeTaskData(engine); + LLSERemoveAllEventListeners(engine); + LLSERemoveCmdRegister(engine); + LLSERemoveCmdCallback(engine); + LLSERemoveAllExportedFuncs(engine); + + engine->getData().reset(); + EngineManager::unRegisterEngine(engine); + } + if (engine) { + engine->destroy(); + } + } catch (const std::exception& e) { + logger.error("Fail to load " + realPath + "!"); + logger.error(ll::string_utils::tou8str(e.what())); + } catch (...) { + logger.error("Fail to load " + realPath + "!"); } - } catch (const std::exception &e) { - logger.error("Fail to load " + realPath + "!"); - logger.error(ll::string_utils::tou8str(e.what())); - } catch (...) { - logger.error("Fail to load " + realPath + "!"); - } - return false; + return false; } // Load plugin package // This function must be called in correct backend -bool PluginManager::loadPluginPackage(const std::string &dirPath, - const std::string &packagePath, - bool isHotLoad, - bool isUncompressedFirstTime) { - // "dirPath" is public temp dir (LLSE_PLUGIN_PACKAGE_TEMP_DIR) or normal - // plugin dir "packagePath" will point to plugin package path if - // isUncompressedFirstTime == true - if (!std::filesystem::is_directory(dirPath)) - return false; - bool result = false; +bool PluginManager::loadPluginPackage( + const std::string& dirPath, + const std::string& packagePath, + bool isHotLoad, + bool isUncompressedFirstTime +) { + // "dirPath" is public temp dir (LLSE_PLUGIN_PACKAGE_TEMP_DIR) or normal + // plugin dir "packagePath" will point to plugin package path if + // isUncompressedFirstTime == true + if (!std::filesystem::is_directory(dirPath)) return false; + bool result = false; #ifdef LLSE_BACKEND_NODEJS - result = NodeJsHelper::loadNodeJsPlugin(dirPath, packagePath, isHotLoad); + result = NodeJsHelper::loadNodeJsPlugin(dirPath, packagePath, isHotLoad); #elif defined(LLSE_BACKEND_PYTHON) - result = PythonHelper::loadPythonPlugin(dirPath, packagePath, isHotLoad); + result = PythonHelper::loadPythonPlugin(dirPath, packagePath, isHotLoad); #endif - if (result && isUncompressedFirstTime) { - // OK now. Delete installed plugin package - std::error_code ec; - std::filesystem::remove(packagePath, ec); - } - return result; + if (result && isUncompressedFirstTime) { + // OK now. Delete installed plugin package + std::error_code ec; + std::filesystem::remove(packagePath, ec); + } + return result; } // Unload plugin -bool PluginManager::unloadPlugin(const std::string &name) { - if (name == LLSE_DEBUG_ENGINE_NAME) - return false; +bool PluginManager::unloadPlugin(const std::string& name) { + if (name == LLSE_DEBUG_ENGINE_NAME) return false; - auto engine = EngineManager::getEngine(name, true); - if (!engine) - return false; - string pluginName = ENGINE_GET_DATA(engine)->pluginName; + auto engine = EngineManager::getEngine(name, true); + if (!engine) return false; + string pluginName = ENGINE_GET_DATA(engine)->pluginName; - // NodeJs use his own setTimeout, so no need to remove + // NodeJs use his own setTimeout, so no need to remove #ifndef LLSE_BACKEND_NODEJS - LLSERemoveTimeTaskData(engine); + LLSERemoveTimeTaskData(engine); #endif - LLSECallEventsOnHotUnload(engine); - LLSERemoveAllEventListeners(engine); - LLSERemoveCmdRegister(engine); - LLSERemoveCmdCallback(engine); - LLSERemoveAllExportedFuncs(engine); + LLSECallEventsOnHotUnload(engine); + LLSERemoveAllEventListeners(engine); + LLSERemoveCmdRegister(engine); + LLSERemoveCmdCallback(engine); + LLSERemoveAllExportedFuncs(engine); - EngineManager::unRegisterEngine(engine); - engine->getData().reset(); + EngineManager::unRegisterEngine(engine); + engine->getData().reset(); - PluginManager::unRegisterPlugin(name); - ll::schedule::DelayTask task( - ll::chrono::ticks(1), [engine]() { + PluginManager::unRegisterPlugin(name); + ll::schedule::DelayTask task(ll::chrono::ticks(1), [engine]() { #ifdef LLSE_BACKEND_NODEJS NodeJsHelper::stopEngine(engine); #else engine->destroy(); #endif - }); + }); - logger.info(pluginName + " unloaded."); - return true; + logger.info(pluginName + " unloaded."); + return true; } // Reload plugin -bool PluginManager::reloadPlugin(const std::string &name) { - if (name == LLSE_DEBUG_ENGINE_NAME) - return true; +bool PluginManager::reloadPlugin(const std::string& name) { + if (name == LLSE_DEBUG_ENGINE_NAME) return true; - auto plugin = PluginManager::getPlugin(name); - if (!plugin) - return false; + auto plugin = PluginManager::getPlugin(name); + if (!plugin) return false; - std::string filePath = plugin->getManifest().entry; - if (!PluginManager::unloadPlugin(name)) - return false; - try { - return PluginManager::loadPlugin(filePath, true, true); - } catch (...) { - return false; - } + std::string filePath = plugin->getManifest().entry; + if (!PluginManager::unloadPlugin(name)) return false; + try { + return PluginManager::loadPlugin(filePath, true, true); + } catch (...) { + return false; + } } // Reload all plugins bool PluginManager::reloadAllPlugins() { - auto pluginsList = PluginManager::getLocalPlugins(); - for (auto &plugin : pluginsList) - reloadPlugin(plugin.second->getManifest().name); - return true; + auto pluginsList = PluginManager::getLocalPlugins(); + for (auto& plugin : pluginsList) reloadPlugin(plugin.second->getManifest().name); + return true; } -ll::plugin::Plugin *PluginManager::getPlugin(std::string name) { - return PluginManager::getPlugin(std::move(name)); -} +ll::plugin::Plugin* PluginManager::getPlugin(std::string name) { return PluginManager::getPlugin(std::move(name)); } // Get all plugins of current language -std::unordered_map -PluginManager::getLocalPlugins() { - std::unordered_map res; - - auto engines = EngineManager::getLocalEngines(); - for (auto &engine : engines) { - string name = ENGINE_GET_DATA(engine)->pluginName; - if (name != LLSE_DEBUG_ENGINE_NAME) { - ll::plugin::Plugin *plugin = PluginManager::getPlugin(name); - if (plugin) - res[plugin->getManifest().entry] = plugin; +std::unordered_map PluginManager::getLocalPlugins() { + std::unordered_map res; + + auto engines = EngineManager::getLocalEngines(); + for (auto& engine : engines) { + string name = ENGINE_GET_DATA(engine)->pluginName; + if (name != LLSE_DEBUG_ENGINE_NAME) { + ll::plugin::Plugin* plugin = PluginManager::getPlugin(name); + if (plugin) res[plugin->getManifest().entry] = plugin; + } } - } - return res; + return res; } -std::unordered_map -PluginManager::getAllScriptPlugins() { - // Todo - // auto res = getAllPlugins(); - // erase_if(res, [](auto &item) { - // return item.second->type != ll::plugin::ScriptPlugin; - // }); - // return res; - return {}; +std::unordered_map PluginManager::getAllScriptPlugins() { + // Todo + // auto res = getAllPlugins(); + // erase_if(res, [](auto &item) { + // return item.second->type != ll::plugin::ScriptPlugin; + // }); + // return res; + return {}; } // Get all plugins -std::unordered_map -PluginManager::getAllPlugins() { - // Todo - // return ll::PluginManager::getAllPlugins(); - return {}; +std::unordered_map PluginManager::getAllPlugins() { + // Todo + // return ll::PluginManager::getAllPlugins(); + return {}; } -bool PluginManager::registerPlugin(std::string filePath, std::string name, - std::string desc, ll::Version version, - std::map others) { - others["PluginType"] = "Script Plugin"; - others["PluginFilePath"] = std::move(filePath); - // Todo - // return ll::PluginManager::registerPlugin(nullptr, std::move(name), - // std::move(desc), version, others); - return true; +bool PluginManager::registerPlugin( + std::string filePath, + std::string name, + std::string desc, + ll::Version version, + std::map others +) { + others["PluginType"] = "Script Plugin"; + others["PluginFilePath"] = std::move(filePath); + // Todo + // return ll::PluginManager::registerPlugin(nullptr, std::move(name), + // std::move(desc), version, others); + return true; } bool PluginManager::unRegisterPlugin(std::string name) { - // Todo - // return ll::PluginManager::unRegisterPlugin(std::move(name)); - return true; + // Todo + // return ll::PluginManager::unRegisterPlugin(std::move(name)); + return true; } // Get plugin backend type from its file path (single file plugin) // or its unpressed dir path (plugin package) -std::string PluginManager::getPluginBackendType(const std::string &path) { - std::filesystem::path filePath(ll::string_utils::str2wstr(path)); - if (!std::filesystem::exists(filePath)) - return ""; - - if (std::filesystem::is_directory(filePath)) { - // Uncompressed plugin package - auto identifiers = LLSE_VALID_PLUGIN_PACKAGE_IDENTIFIER; - vector filesExts = {}; - for (int i = 0; i < identifiers.size(); ++i) - if (!identifiers.empty()) { - string id = identifiers[i]; - if (id.empty()) - continue; - - if (id.find('*') != std::string::npos) { - // match identifier like "*.py" - if (filesExts.empty()) { - // build filesExts list - std::filesystem::directory_iterator files(filePath); - for (auto &item : files) { - if (item.is_regular_file()) - filesExts.emplace_back(ll::string_utils::u8str2str( - item.path().extension().u8string())); +std::string PluginManager::getPluginBackendType(const std::string& path) { + std::filesystem::path filePath(ll::string_utils::str2wstr(path)); + if (!std::filesystem::exists(filePath)) return ""; + + if (std::filesystem::is_directory(filePath)) { + // Uncompressed plugin package + auto identifiers = LLSE_VALID_PLUGIN_PACKAGE_IDENTIFIER; + vector filesExts = {}; + for (int i = 0; i < identifiers.size(); ++i) + if (!identifiers.empty()) { + string id = identifiers[i]; + if (id.empty()) continue; + + if (id.find('*') != std::string::npos) { + // match identifier like "*.py" + if (filesExts.empty()) { + // build filesExts list + std::filesystem::directory_iterator files(filePath); + for (auto& item : files) { + if (item.is_regular_file()) + filesExts.emplace_back(ll::string_utils::u8str2str(item.path().extension().u8string())); + } + } + string compareExt = id.substr(id.find_last_of('.')); + if (std::find(filesExts.begin(), filesExts.end(), compareExt) != filesExts.end()) { + // match + return LLSE_VALID_BACKENDS[i]; + } + } else { + // match identifier like "package.json" + if (std::filesystem::exists(filePath / id)) { + // match + return LLSE_VALID_BACKENDS[i]; + } + } } - } - string compareExt = id.substr(id.find_last_of('.')); - if (std::find(filesExts.begin(), filesExts.end(), compareExt) != - filesExts.end()) { - // match - return LLSE_VALID_BACKENDS[i]; - } - } else { - // match identifier like "package.json" - if (std::filesystem::exists(filePath / id)) { - // match - return LLSE_VALID_BACKENDS[i]; - } + } else { + // Common plugin file + string ext = ll::string_utils::u8str2str(filePath.extension().u8string()); + if (ext == LLSE_PLUGIN_PACKAGE_EXTENSION) { + // Never consider .llplugin + // Just uncompress it and then come to check + return "PluginPackage"; } - } - } else { - // Common plugin file - string ext = ll::string_utils::u8str2str(filePath.extension().u8string()); - if (ext == LLSE_PLUGIN_PACKAGE_EXTENSION) { - // Never consider .llplugin - // Just uncompress it and then come to check - return "PluginPackage"; + auto validExts = LLSE_VALID_PLUGIN_EXTENSIONS; + for (int i = 0; i < validExts.size(); ++i) + if (!validExts[i].empty() && validExts[i] == ext) { + // match + return LLSE_VALID_BACKENDS[i]; + } } - auto validExts = LLSE_VALID_PLUGIN_EXTENSIONS; - for (int i = 0; i < validExts.size(); ++i) - if (!validExts[i].empty() && validExts[i] == ext) { - // match - return LLSE_VALID_BACKENDS[i]; - } - } - // none backend matched - return ""; -} \ No newline at end of file + // none backend matched + return ""; +} diff --git a/src/main/PluginManager.h b/src/main/PluginManager.h index 1d0e4f58..95c2fd3e 100644 --- a/src/main/PluginManager.h +++ b/src/main/PluginManager.h @@ -7,31 +7,34 @@ class PluginManager { private: - static bool unRegisterPlugin(std::string name); - static bool loadPluginPackage(const std::string &dirPath, - const std::string &packagePath, bool isHotLoad, - bool isUncompressedFirstTime); + static bool unRegisterPlugin(std::string name); + static bool loadPluginPackage( + const std::string& dirPath, + const std::string& packagePath, + bool isHotLoad, + bool isUncompressedFirstTime + ); public: - // if mustBeCurrectModule == true and not-current-module plugin is found, will - // throw exception - static bool loadPlugin(const std::string &fileOrDirPath, - bool isHotLoad = false, - bool mustBeCurrectModule = false); - static bool unloadPlugin(const std::string &name); - static bool reloadPlugin(const std::string &name); - static bool reloadAllPlugins(); + // if mustBeCurrectModule == true and not-current-module plugin is found, will + // throw exception + static bool loadPlugin(const std::string& fileOrDirPath, bool isHotLoad = false, bool mustBeCurrectModule = false); + static bool unloadPlugin(const std::string& name); + static bool reloadPlugin(const std::string& name); + static bool reloadAllPlugins(); - static ll::plugin::Plugin *getPlugin(std::string name); - static std::unordered_map - getLocalPlugins(); - static std::unordered_map - getAllScriptPlugins(); - static std::unordered_map getAllPlugins(); + static ll::plugin::Plugin* getPlugin(std::string name); + static std::unordered_map getLocalPlugins(); + static std::unordered_map getAllScriptPlugins(); + static std::unordered_map getAllPlugins(); - static std::string getPluginBackendType(const std::string &path); + static std::string getPluginBackendType(const std::string& path); - static bool registerPlugin(std::string filePath, std::string name, - std::string desc, ll::Version version, - std::map others); + static bool registerPlugin( + std::string filePath, + std::string name, + std::string desc, + ll::Version version, + std::map others + ); }; \ No newline at end of file diff --git a/src/main/PythonHelper.cpp b/src/main/PythonHelper.cpp index bf574b55..cabf2dcf 100644 --- a/src/main/PythonHelper.cpp +++ b/src/main/PythonHelper.cpp @@ -1,7 +1,7 @@ #pragma warning(disable : 4251) #include "Configs.h" #if defined(LLSE_BACKEND_PYTHON) -#include "Global.hpp" +#include "Global.h" #include "Loader.h" #include "PythonHelper.h" #include "api/CommandAPI.h" @@ -24,434 +24,391 @@ #define PIP_EXECUTE_TIMEOUT 1800 * 1000 // pre-declare -extern void BindAPIs(ScriptEngine *engine); +extern void BindAPIs(ScriptEngine* engine); extern ll::Logger logger; -extern bool isInConsoleDebugMode; -extern ScriptEngine *debugEngine; +extern bool isInConsoleDebugMode; +extern ScriptEngine* debugEngine; struct PyConfig; -typedef PyObject *(*create_stdio_func_type)(const PyConfig *config, - PyObject *io, int fd, - int write_mode, const char *name, - const wchar_t *encoding, - const wchar_t *errors); +typedef PyObject* (*create_stdio_func_type)( + const PyConfig* config, + PyObject* io, + int fd, + int write_mode, + const char* name, + const wchar_t* encoding, + const wchar_t* errors +); namespace PythonHelper { bool pythonInited = false; bool initPythonRuntime() { - if (!pythonInited) { - script::py_interop::setPythonHomePath(L".\\plugins\\lib\\python-env"); - script::py_interop::setModuleSearchPaths({ - L".\\plugins\\lib\\python-env\\python310.zip", - L".\\plugins\\lib\\python-env\\DLLs", - L".\\plugins\\lib\\python-env\\Lib", - L".\\plugins\\lib\\python-env\\Lib\\site-packages", - }); - pythonInited = true; - } - return true; + if (!pythonInited) { + script::py_interop::setPythonHomePath(L".\\plugins\\lib\\python-env"); + script::py_interop::setModuleSearchPaths({ + L".\\plugins\\lib\\python-env\\python310.zip", + L".\\plugins\\lib\\python-env\\DLLs", + L".\\plugins\\lib\\python-env\\Lib", + L".\\plugins\\lib\\python-env\\Lib\\site-packages", + }); + pythonInited = true; + } + return true; } -bool loadPluginCode(script::ScriptEngine *engine, std::string entryScriptPath, - std::string pluginDirPath) { - // TODO: add import path to sys.path - try { - engine->loadFile(entryScriptPath); - } catch (const Exception &e1) { - // Fail - logger.error("Fail in Loading Script Plugin!\n"); - throw e1; - } - return true; +bool loadPluginCode(script::ScriptEngine* engine, std::string entryScriptPath, std::string pluginDirPath) { + // TODO: add import path to sys.path + try { + engine->loadFile(entryScriptPath); + } catch (const Exception& e1) { + // Fail + logger.error("Fail in Loading Script Plugin!\n"); + throw e1; + } + return true; } // Load Python plugin // This function must be called in correct backend -bool loadPythonPlugin(std::string dirPath, const std::string &packagePath, - bool isHotLoad) { - // "dirPath" is public temp dir (LLSE_PLUGIN_PACKAGE_TEMP_DIR) or normal - // plugin dir "packagePath" will point to plugin package path if - // isUncompressedFirstTime == true - if (dirPath == LLSE_PLUGIN_PACKAGE_TEMP_DIR) { - // Need to copy from temp dir to installed dir - if (std::filesystem::exists(LLSE_PLUGIN_PACKAGE_TEMP_DIR - "/pyproject.toml")) { - auto pluginName = - PythonHelper::getPluginPackageName(LLSE_PLUGIN_PACKAGE_TEMP_DIR); - if (pluginName.empty()) { - pluginName = UTF82String(filesystem::path(packagePath) - .filename() - .replace_extension("") - .u8string()); - } - auto dest = - std::filesystem::path(LLSE_PLUGINS_ROOT_DIR).append(pluginName); - - // copy files - std::error_code ec; - // if (filesystem::exists(dest)) - // filesystem::remove_all(dest, ec); - std::filesystem::copy(LLSE_PLUGIN_PACKAGE_TEMP_DIR "/", dest, - filesystem::copy_options::overwrite_existing | - filesystem::copy_options::recursive, - ec); - - // reset dirPath - dirPath = UTF82String(dest.u8string()); +bool loadPythonPlugin(std::string dirPath, const std::string& packagePath, bool isHotLoad) { + // "dirPath" is public temp dir (LLSE_PLUGIN_PACKAGE_TEMP_DIR) or normal + // plugin dir "packagePath" will point to plugin package path if + // isUncompressedFirstTime == true + if (dirPath == LLSE_PLUGIN_PACKAGE_TEMP_DIR) { + // Need to copy from temp dir to installed dir + if (std::filesystem::exists(LLSE_PLUGIN_PACKAGE_TEMP_DIR "/pyproject.toml")) { + auto pluginName = PythonHelper::getPluginPackageName(LLSE_PLUGIN_PACKAGE_TEMP_DIR); + if (pluginName.empty()) { + pluginName = UTF82String(filesystem::path(packagePath).filename().replace_extension("").u8string()); + } + auto dest = std::filesystem::path(LLSE_PLUGINS_ROOT_DIR).append(pluginName); + + // copy files + std::error_code ec; + // if (filesystem::exists(dest)) + // filesystem::remove_all(dest, ec); + std::filesystem::copy( + LLSE_PLUGIN_PACKAGE_TEMP_DIR "/", + dest, + filesystem::copy_options::overwrite_existing | filesystem::copy_options::recursive, + ec + ); + + // reset dirPath + dirPath = UTF82String(dest.u8string()); + } + // remove temp dir + std::error_code ec; + std::filesystem::remove_all(LLSE_PLUGIN_PACKAGE_TEMP_DIR, ec); } - // remove temp dir - std::error_code ec; - std::filesystem::remove_all(LLSE_PLUGIN_PACKAGE_TEMP_DIR, ec); - } - std::string entryPath = PythonHelper::findEntryScript(dirPath); - if (entryPath.empty()) - return false; - std::string pluginName = PythonHelper::getPluginPackageName(dirPath); - - // Run "pip install" if needed - auto realPackageInstallDir = - (filesystem::path(dirPath) / "site-packages").make_preferred(); - if (!filesystem::exists(realPackageInstallDir)) { - std::string dependTmpFilePath = - PythonHelper::getPluginPackDependencyFilePath(dirPath); - if (!dependTmpFilePath.empty()) { - int exitCode = 0; - logger.info( - tr("llse.loader.python.executePipInstall.start", - fmt::arg("name", - UTF82String( - filesystem::path(dirPath).filename().u8string())))); - - if ((exitCode = PythonHelper::executePipCommand( - "pip install -r \"" + dependTmpFilePath + "\" -t \"" + - UTF82String(realPackageInstallDir.u8string()) + - "\" --disable-pip-version-check")) == 0) { - logger.info(tr("llse.loader.python.executePipInstall.success")); - } else - logger.error(tr("llse.loader.python.executePipInstall.fail", - fmt::arg("code", exitCode))); - - // remove temp dependency file after installation - std::error_code ec; - std::filesystem::remove(std::filesystem::path(dependTmpFilePath), ec); + std::string entryPath = PythonHelper::findEntryScript(dirPath); + if (entryPath.empty()) return false; + std::string pluginName = PythonHelper::getPluginPackageName(dirPath); + + // Run "pip install" if needed + auto realPackageInstallDir = (filesystem::path(dirPath) / "site-packages").make_preferred(); + if (!filesystem::exists(realPackageInstallDir)) { + std::string dependTmpFilePath = PythonHelper::getPluginPackDependencyFilePath(dirPath); + if (!dependTmpFilePath.empty()) { + int exitCode = 0; + logger.info( + tr("llse.loader.python.executePipInstall.start", + fmt::arg("name", UTF82String(filesystem::path(dirPath).filename().u8string()))) + ); + + if ((exitCode = PythonHelper::executePipCommand( + "pip install -r \"" + dependTmpFilePath + "\" -t \"" + + UTF82String(realPackageInstallDir.u8string()) + "\" --disable-pip-version-check" + )) + == 0) { + logger.info(tr("llse.loader.python.executePipInstall.success")); + } else logger.error(tr("llse.loader.python.executePipInstall.fail", fmt::arg("code", exitCode))); + + // remove temp dependency file after installation + std::error_code ec; + std::filesystem::remove(std::filesystem::path(dependTmpFilePath), ec); + } } - } - // Create engine & Load plugin - ScriptEngine *engine = nullptr; - try { - engine = EngineManager::newEngine(); - EngineScope enter(engine); + // Create engine & Load plugin + ScriptEngine* engine = nullptr; + try { + engine = EngineManager::newEngine(); + EngineScope enter(engine); + + // setData + ENGINE_OWN_DATA()->pluginName = pluginName; + ENGINE_OWN_DATA()->pluginFileOrDirPath = dirPath; + ENGINE_OWN_DATA()->logger.title = pluginName; + + try { + engine->eval("import sys as _llse_py_sys_module"); + std::error_code ec; + + // add plugin-own site-packages to sys.path + string pluginSitePackageFormatted = + UTF82String(std::filesystem::canonical(realPackageInstallDir.make_preferred(), ec).u8string()); + if (!ec) { + engine->eval("_llse_py_sys_module.path.insert(0, r'" + pluginSitePackageFormatted + "')"); + } + // add plugin source dir to sys.path + string sourceDirFormatted = + UTF82String(std::filesystem::canonical(filesystem::path(dirPath).make_preferred()).u8string()); + engine->eval("_llse_py_sys_module.path.insert(0, r'" + sourceDirFormatted + "')"); + + // set __file__ and __name__ + string entryPathFormatted = + UTF82String(std::filesystem::canonical(filesystem::path(entryPath).make_preferred()).u8string()); + engine->set("__file__", entryPathFormatted); + // engine->set("__name__", String::newString("__main__")); + } catch (const Exception& e) { + logger.error("Fail in setting sys.path!\n"); + throw; + } - // setData - ENGINE_OWN_DATA()->pluginName = pluginName; - ENGINE_OWN_DATA()->pluginFileOrDirPath = dirPath; - ENGINE_OWN_DATA()->logger.title = pluginName; + // bindAPIs + try { + BindAPIs(engine); + } catch (const Exception& e) { + logger.error("Fail in Binding APIs!\n"); + throw; + } - try { - engine->eval("import sys as _llse_py_sys_module"); - std::error_code ec; - - // add plugin-own site-packages to sys.path - string pluginSitePackageFormatted = UTF82String( - std::filesystem::canonical(realPackageInstallDir.make_preferred(), ec) - .u8string()); - if (!ec) { - engine->eval("_llse_py_sys_module.path.insert(0, r'" + - pluginSitePackageFormatted + "')"); - } - // add plugin source dir to sys.path - string sourceDirFormatted = UTF82String( - std::filesystem::canonical(filesystem::path(dirPath).make_preferred()) - .u8string()); - engine->eval("_llse_py_sys_module.path.insert(0, r'" + - sourceDirFormatted + "')"); - - // set __file__ and __name__ - string entryPathFormatted = - UTF82String(std::filesystem::canonical( - filesystem::path(entryPath).make_preferred()) - .u8string()); - engine->set("__file__", entryPathFormatted); - // engine->set("__name__", String::newString("__main__")); - } catch (const Exception &e) { - logger.error("Fail in setting sys.path!\n"); - throw; - } + // Load depend libs + try { + for (auto& [path, content] : depends) { + if (!content.empty()) engine->eval(content, path); + } + } catch (const Exception& e) { + logger.error("Fail in Loading Dependence Lib!\n"); + throw; + } - // bindAPIs - try { - BindAPIs(engine); - } catch (const Exception &e) { - logger.error("Fail in Binding APIs!\n"); - throw; - } + // Load script + if (!PythonHelper::loadPluginCode(engine, entryPath, dirPath)) throw "Uncaught exception thrown in code"; - // Load depend libs - try { - for (auto &[path, content] : depends) { - if (!content.empty()) - engine->eval(content, path); - } - } catch (const Exception &e) { - logger.error("Fail in Loading Dependence Lib!\n"); - throw; - } + if (!PluginManager::getPlugin(pluginName)) { + // Plugin did't register itself. Help to register it + string description = pluginName; + ll::Version ver(1, 0, 0); + std::map others = {}; - // Load script - if (!PythonHelper::loadPluginCode(engine, entryPath, dirPath)) - throw "Uncaught exception thrown in code"; - - if (!PluginManager::getPlugin(pluginName)) { - // Plugin did't register itself. Help to register it - string description = pluginName; - ll::Version ver(1, 0, 0); - std::map others = {}; - - // Read information from pyproject.toml - try { - std::filesystem::path packageFilePath = - std::filesystem::path(dirPath) / "pyproject.toml"; - string packageFilePathStr = - UTF82String(packageFilePath.make_preferred().u8string()); - - toml::table configData = toml::parse_file(packageFilePathStr); - auto projectNode = configData["project"]; - - // description - if (projectNode["description"]) { - description = *(projectNode["description"].value()); - } + // Read information from pyproject.toml + try { + std::filesystem::path packageFilePath = std::filesystem::path(dirPath) / "pyproject.toml"; + string packageFilePathStr = UTF82String(packageFilePath.make_preferred().u8string()); - // version - if (projectNode["version"]) { - ver = ll::Version::parse( - *(projectNode["version"].value())); - } + toml::table configData = toml::parse_file(packageFilePathStr); + auto projectNode = configData["project"]; - // TODO: more information to read - } catch (...) { - } + // description + if (projectNode["description"]) { + description = *(projectNode["description"].value()); + } - // register - PluginManager::registerPlugin(dirPath, pluginName, description, ver, - others); - } + // version + if (projectNode["version"]) { + ver = ll::Version::parse(*(projectNode["version"].value())); + } - // Call necessary events when at hot load - if (isHotLoad) - LLSECallEventsOnHotLoad(engine); + // TODO: more information to read + } catch (...) {} - // Success - logger.info(tr("llse.loader.loadMain.loadedPlugin", - fmt::arg("type", "Python"), fmt::arg("name", pluginName))); - return true; - } catch (const Exception &e) { - logger.error("Fail to load " + dirPath + "!"); - if (engine) { - EngineScope enter(engine); - logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); - PrintException(e); - ExitEngineScope exit; - - LLSERemoveTimeTaskData(engine); - LLSERemoveAllEventListeners(engine); - LLSERemoveCmdRegister(engine); - LLSERemoveCmdCallback(engine); - LLSERemoveAllExportedFuncs(engine); - - engine->getData().reset(); - EngineManager::unRegisterEngine(engine); - } - if (engine) { - engine->destroy(); + // register + PluginManager::registerPlugin(dirPath, pluginName, description, ver, others); + } + + // Call necessary events when at hot load + if (isHotLoad) LLSECallEventsOnHotLoad(engine); + + // Success + logger.info(tr("llse.loader.loadMain.loadedPlugin", fmt::arg("type", "Python"), fmt::arg("name", pluginName))); + return true; + } catch (const Exception& e) { + logger.error("Fail to load " + dirPath + "!"); + if (engine) { + EngineScope enter(engine); + logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); + PrintException(e); + ExitEngineScope exit; + + LLSERemoveTimeTaskData(engine); + LLSERemoveAllEventListeners(engine); + LLSERemoveCmdRegister(engine); + LLSERemoveCmdCallback(engine); + LLSERemoveAllExportedFuncs(engine); + + engine->getData().reset(); + EngineManager::unRegisterEngine(engine); + } + if (engine) { + engine->destroy(); + } + } catch (const std::exception& e) { + logger.error("Fail to load " + dirPath + "!"); + logger.error(ll::string_utils::tou8str(e.what())); + } catch (...) { + logger.error("Fail to load " + dirPath + "!"); } - } catch (const std::exception &e) { - logger.error("Fail to load " + dirPath + "!"); - logger.error(ll::string_utils::tou8str(e.what())); - } catch (...) { - logger.error("Fail to load " + dirPath + "!"); - } - return false; + return false; } -std::string findEntryScript(const std::string &dirPath) { - auto dirPath_obj = std::filesystem::path(dirPath); +std::string findEntryScript(const std::string& dirPath) { + auto dirPath_obj = std::filesystem::path(dirPath); - std::filesystem::path entryFilePath = dirPath_obj / "__init__.py"; - if (!std::filesystem::exists(entryFilePath)) - return ""; - else - return UTF82String(entryFilePath.u8string()); + std::filesystem::path entryFilePath = dirPath_obj / "__init__.py"; + if (!std::filesystem::exists(entryFilePath)) return ""; + else return UTF82String(entryFilePath.u8string()); } -std::string getPluginPackageName(const std::string &dirPath) { - auto dirPath_obj = std::filesystem::path(dirPath); - std::string defaultReturnName = - UTF82String(filesystem::path(dirPath).filename().u8string()); - - std::filesystem::path packageFilePath = - dirPath_obj / std::filesystem::path("pyproject.toml"); - if (!std::filesystem::exists(packageFilePath)) - return defaultReturnName; - - try { - string packageFilePathStr = - UTF82String(packageFilePath.make_preferred().u8string()); - toml::table configData = toml::parse_file(packageFilePathStr); - auto projectNode = configData["project"]; - if (!projectNode["name"]) - return defaultReturnName; - std::optional packageName = - projectNode["name"].value(); - if (packageName && !packageName->empty()) - return *packageName; - else - return defaultReturnName; - } catch (...) { - return defaultReturnName; - } -} +std::string getPluginPackageName(const std::string& dirPath) { + auto dirPath_obj = std::filesystem::path(dirPath); + std::string defaultReturnName = UTF82String(filesystem::path(dirPath).filename().u8string()); + + std::filesystem::path packageFilePath = dirPath_obj / std::filesystem::path("pyproject.toml"); + if (!std::filesystem::exists(packageFilePath)) return defaultReturnName; -std::string getPluginPackDependencyFilePath(const std::string &dirPath) { - auto dirPath_obj = std::filesystem::path(dirPath); - std::filesystem::path packageFilePath = - dirPath_obj / std::filesystem::path("pyproject.toml"); - std::filesystem::path requirementsFilePath = - dirPath_obj / std::filesystem::path("requirements.txt"); - std::filesystem::path requirementsTmpFilePath = - dirPath_obj / std::filesystem::path("_requirements_llse_temp.txt"); - - // if requirements.txt exists, copy a temp version - if (std::filesystem::exists(requirementsFilePath)) { - std::error_code ec; - std::filesystem::copy_file(requirementsFilePath, requirementsTmpFilePath, - ec); - } - - if (std::filesystem::exists(packageFilePath)) { - // copy dependencies from pyproject.toml to _requirements_llse_temp.txt - std::string dependsAdded = ""; try { - string packageFilePathStr = - UTF82String(packageFilePath.make_preferred().u8string()); - toml::table configData = toml::parse_file(packageFilePathStr); - auto projectNode = configData["project"]; - if (projectNode["dependencies"]) { - toml::array *arr = projectNode["dependencies"].as_array(); - arr->for_each([&dependsAdded](toml::value &elem) { - std::optional depend = *elem; - dependsAdded += "\n" + *depend; - }); - } + string packageFilePathStr = UTF82String(packageFilePath.make_preferred().u8string()); + toml::table configData = toml::parse_file(packageFilePathStr); + auto projectNode = configData["project"]; + if (!projectNode["name"]) return defaultReturnName; + std::optional packageName = projectNode["name"].value(); + if (packageName && !packageName->empty()) return *packageName; + else return defaultReturnName; } catch (...) { + return defaultReturnName; } +} + +std::string getPluginPackDependencyFilePath(const std::string& dirPath) { + auto dirPath_obj = std::filesystem::path(dirPath); + std::filesystem::path packageFilePath = dirPath_obj / std::filesystem::path("pyproject.toml"); + std::filesystem::path requirementsFilePath = dirPath_obj / std::filesystem::path("requirements.txt"); + std::filesystem::path requirementsTmpFilePath = dirPath_obj / std::filesystem::path("_requirements_llse_temp.txt"); - if (!dependsAdded.empty()) { - std::ofstream fout( - UTF82String(requirementsTmpFilePath.make_preferred().u8string()), - std::ios::app); - fout << dependsAdded; - fout.close(); + // if requirements.txt exists, copy a temp version + if (std::filesystem::exists(requirementsFilePath)) { + std::error_code ec; + std::filesystem::copy_file(requirementsFilePath, requirementsTmpFilePath, ec); } - } - if (std::filesystem::exists(requirementsTmpFilePath)) - return UTF82String(requirementsTmpFilePath.make_preferred().u8string()); - else - return ""; + if (std::filesystem::exists(packageFilePath)) { + // copy dependencies from pyproject.toml to _requirements_llse_temp.txt + std::string dependsAdded = ""; + try { + string packageFilePathStr = UTF82String(packageFilePath.make_preferred().u8string()); + toml::table configData = toml::parse_file(packageFilePathStr); + auto projectNode = configData["project"]; + if (projectNode["dependencies"]) { + toml::array* arr = projectNode["dependencies"].as_array(); + arr->for_each([&dependsAdded](toml::value& elem) { + std::optional depend = *elem; + dependsAdded += "\n" + *depend; + }); + } + } catch (...) {} + + if (!dependsAdded.empty()) { + std::ofstream fout(UTF82String(requirementsTmpFilePath.make_preferred().u8string()), std::ios::app); + fout << dependsAdded; + fout.close(); + } + } + + if (std::filesystem::exists(requirementsTmpFilePath)) + return UTF82String(requirementsTmpFilePath.make_preferred().u8string()); + else return ""; } -#define OUTPUT_DEBUG_SIGN() std::cout << ">>> " << std::flush +#define OUTPUT_DEBUG_SIGN() std::cout << ">>> " << std::flush #define OUTPUT_DEBUG_NEED_MORE_CODE_SIGN() std::cout << "... " << std::flush -std::string codeBuffer = ""; -bool isInsideCodeBlock = false; - -static PyObject *getPyGlobalDict() { - PyObject *m = PyImport_AddModule("__main__"); - if (m == nullptr) { - throw Exception("can't find __main__ module"); - } - return PyModule_GetDict(m); -} +std::string codeBuffer = ""; +bool isInsideCodeBlock = false; -bool processPythonDebugEngine(const std::string &cmd) { - if (cmd == LLSE_DEBUG_CMD) { - if (isInConsoleDebugMode) { - // EndDebug - logger.info("Debug mode ended"); - isInConsoleDebugMode = false; - } else { - // StartDebug - logger.info("Debug mode begins"); - codeBuffer.clear(); - isInsideCodeBlock = false; - isInConsoleDebugMode = true; - OUTPUT_DEBUG_SIGN(); +static PyObject* getPyGlobalDict() { + PyObject* m = PyImport_AddModule("__main__"); + if (m == nullptr) { + throw Exception("can't find __main__ module"); } - return false; - } - if (isInConsoleDebugMode) { - EngineScope enter(debugEngine); - if (cmd == "stop") { - return true; - } else { - try { - if (isInsideCodeBlock) { - // is in code block mode - if (cmd.empty()) { - // exit code block - isInsideCodeBlock = false; - } else { - // add a new line to buffer - codeBuffer += cmd + "\n"; - OUTPUT_DEBUG_NEED_MORE_CODE_SIGN(); - return false; - } + return PyModule_GetDict(m); +} + +bool processPythonDebugEngine(const std::string& cmd) { + if (cmd == LLSE_DEBUG_CMD) { + if (isInConsoleDebugMode) { + // EndDebug + logger.info("Debug mode ended"); + isInConsoleDebugMode = false; } else { - // not in code block mode - if (cmd.ends_with(':')) { - // begin code block mode - isInsideCodeBlock = true; - codeBuffer = cmd + "\n"; - OUTPUT_DEBUG_NEED_MORE_CODE_SIGN(); - return false; - } else { - codeBuffer = cmd; - } + // StartDebug + logger.info("Debug mode begins"); + codeBuffer.clear(); + isInsideCodeBlock = false; + isInConsoleDebugMode = true; + OUTPUT_DEBUG_SIGN(); } - - PyRun_StringFlags(codeBuffer.c_str(), Py_single_input, - getPyGlobalDict(), nullptr, nullptr); - codeBuffer.clear(); - if (script::py_interop::hasException()) { - auto exp = script::py_interop::getAndClearLastException(); - throw exp; + return false; + } + if (isInConsoleDebugMode) { + EngineScope enter(debugEngine); + if (cmd == "stop") { + return true; + } else { + try { + if (isInsideCodeBlock) { + // is in code block mode + if (cmd.empty()) { + // exit code block + isInsideCodeBlock = false; + } else { + // add a new line to buffer + codeBuffer += cmd + "\n"; + OUTPUT_DEBUG_NEED_MORE_CODE_SIGN(); + return false; + } + } else { + // not in code block mode + if (cmd.ends_with(':')) { + // begin code block mode + isInsideCodeBlock = true; + codeBuffer = cmd + "\n"; + OUTPUT_DEBUG_NEED_MORE_CODE_SIGN(); + return false; + } else { + codeBuffer = cmd; + } + } + + PyRun_StringFlags(codeBuffer.c_str(), Py_single_input, getPyGlobalDict(), nullptr, nullptr); + codeBuffer.clear(); + if (script::py_interop::hasException()) { + auto exp = script::py_interop::getAndClearLastException(); + throw exp; + } + } catch (const Exception& e) { + isInsideCodeBlock = false; + codeBuffer.clear(); + logger.error("Exception:\n" + e.stacktrace() + "\n" + e.message()); + } } - } catch (const Exception &e) { - isInsideCodeBlock = false; - codeBuffer.clear(); - logger.error("Exception:\n" + e.stacktrace() + "\n" + e.message()); - } + OUTPUT_DEBUG_SIGN(); + return false; } - OUTPUT_DEBUG_SIGN(); - return false; - } - return true; + return true; } -bool processConsolePipCmd(const std::string &cmd) { +bool processConsolePipCmd(const std::string& cmd) { #ifdef LLSE_BACKEND_PYTHON - if (StartsWith(cmd, "pip ")) { - PythonHelper::executePipCommand(cmd); - return false; - } else - return true; + if (StartsWith(cmd, "pip ")) { + PythonHelper::executePipCommand(cmd); + return false; + } else return true; #else - return true; + return true; #endif } @@ -459,36 +416,33 @@ bool processConsolePipCmd(const std::string &cmd) { // site-package dir // (./plugins/lib/python-env/Lib/site-packages) int executePipCommand(std::string cmd) { - if (cmd.find("--disable-pip-version-check") == std::string::npos) - cmd += " --disable-pip-version-check"; - cmd = ".\\plugins\\lib\\python-env\\python.exe -m " + cmd; - - SECURITY_ATTRIBUTES sa; - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.lpSecurityDescriptor = nullptr; - sa.bInheritHandle = TRUE; - - STARTUPINFOW si = {0}; - PROCESS_INFORMATION pi; - si.cb = sizeof(STARTUPINFO); - GetStartupInfoW(&si); - - auto wCmd = str2cwstr(cmd); - if (!CreateProcessW(nullptr, wCmd, nullptr, nullptr, TRUE, 0, nullptr, - nullptr, &si, &pi)) { + if (cmd.find("--disable-pip-version-check") == std::string::npos) cmd += " --disable-pip-version-check"; + cmd = ".\\plugins\\lib\\python-env\\python.exe -m " + cmd; + + SECURITY_ATTRIBUTES sa; + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = nullptr; + sa.bInheritHandle = TRUE; + + STARTUPINFOW si = {0}; + PROCESS_INFORMATION pi; + si.cb = sizeof(STARTUPINFO); + GetStartupInfoW(&si); + + auto wCmd = str2cwstr(cmd); + if (!CreateProcessW(nullptr, wCmd, nullptr, nullptr, TRUE, 0, nullptr, nullptr, &si, &pi)) { + delete[] wCmd; + return -1; + } + CloseHandle(pi.hThread); + + if (WaitForSingleObject(pi.hProcess, PIP_EXECUTE_TIMEOUT) == WAIT_TIMEOUT) TerminateProcess(pi.hProcess, -1); + + DWORD exitCode = 0; + GetExitCodeProcess(pi.hProcess, &exitCode); + CloseHandle(pi.hProcess); delete[] wCmd; - return -1; - } - CloseHandle(pi.hThread); - - if (WaitForSingleObject(pi.hProcess, PIP_EXECUTE_TIMEOUT) == WAIT_TIMEOUT) - TerminateProcess(pi.hProcess, -1); - - DWORD exitCode = 0; - GetExitCodeProcess(pi.hProcess, &exitCode); - CloseHandle(pi.hProcess); - delete[] wCmd; - return exitCode; + return exitCode; } // This fix is used for Python3.10's bug: @@ -504,54 +458,46 @@ const uintptr_t create_stdio_func_base_offset = 0xCE0F4; create_stdio_func_type create_stdio_original = nullptr; -PyObject *create_stdio_hooked(const PyConfig *config, PyObject *io, int fd, - int write_mode, const char *name, - const wchar_t *encoding, const wchar_t *errors) { - if (fd == 0) { - Py_RETURN_NONE; - } - return create_stdio_original(config, io, fd, write_mode, name, encoding, - errors); +PyObject* create_stdio_hooked( + const PyConfig* config, + PyObject* io, + int fd, + int write_mode, + const char* name, + const wchar_t* encoding, + const wchar_t* errors +) { + if (fd == 0) { + Py_RETURN_NONE; + } + return create_stdio_original(config, io, fd, write_mode, name, encoding, errors); } bool patchPython310CreateStdio() { - if (create_stdio_original == nullptr) { - HMODULE hModule = GetModuleHandleW(L"python310.dll"); - if (hModule == NULL) - return false; - create_stdio_original = - (create_stdio_func_type)(void *)(((uintptr_t)hModule) + - create_stdio_func_base_offset); - } - - DetourRestoreAfterWith(); - if (DetourTransactionBegin() != NO_ERROR) - return false; - else if (DetourUpdateThread(GetCurrentThread()) != NO_ERROR) - return false; - else if (DetourAttach((PVOID *)&create_stdio_original, create_stdio_hooked) != - NO_ERROR) - return false; - else if (DetourTransactionCommit() != NO_ERROR) - return false; - return true; + if (create_stdio_original == nullptr) { + HMODULE hModule = GetModuleHandleW(L"python310.dll"); + if (hModule == NULL) return false; + create_stdio_original = (create_stdio_func_type)(void*)(((uintptr_t)hModule) + create_stdio_func_base_offset); + } + + DetourRestoreAfterWith(); + if (DetourTransactionBegin() != NO_ERROR) return false; + else if (DetourUpdateThread(GetCurrentThread()) != NO_ERROR) return false; + else if (DetourAttach((PVOID*)&create_stdio_original, create_stdio_hooked) != NO_ERROR) return false; + else if (DetourTransactionCommit() != NO_ERROR) return false; + return true; } bool unpatchPython310CreateStdio() { - if (DetourTransactionBegin() != NO_ERROR) - return false; - else if (DetourUpdateThread(GetCurrentThread()) != NO_ERROR) - return false; - else if (DetourDetach((PVOID *)&create_stdio_original, create_stdio_hooked) != - NO_ERROR) - return false; - else if (DetourTransactionCommit() != NO_ERROR) - return false; - return true; + if (DetourTransactionBegin() != NO_ERROR) return false; + else if (DetourUpdateThread(GetCurrentThread()) != NO_ERROR) return false; + else if (DetourDetach((PVOID*)&create_stdio_original, create_stdio_hooked) != NO_ERROR) return false; + else if (DetourTransactionCommit() != NO_ERROR) return false; + return true; } } // namespace FixPython310Stdin } // namespace PythonHelper -#endif \ No newline at end of file +#endif diff --git a/src/main/PythonHelper.h b/src/main/PythonHelper.h index 874c5956..eb72ab81 100644 --- a/src/main/PythonHelper.h +++ b/src/main/PythonHelper.h @@ -1,9 +1,9 @@ #pragma once #if defined(LLSE_BACKEND_PYTHON) #include "Configs.h" +#include #include #include -#include #include namespace PythonHelper { @@ -11,19 +11,17 @@ namespace PythonHelper { bool initPythonRuntime(); // raw, will throw exception if fail -bool loadPluginCode(script::ScriptEngine *engine, std::string entryScriptPath, - std::string pluginDirPath); -bool loadPythonPlugin(std::string dirPath, const std::string &packagePath, - bool isHotLoad = false); +bool loadPluginCode(script::ScriptEngine* engine, std::string entryScriptPath, std::string pluginDirPath); +bool loadPythonPlugin(std::string dirPath, const std::string& packagePath, bool isHotLoad = false); -std::string findEntryScript(const std::string &dirPath); -std::string getPluginPackageName(const std::string &dirPath); -std::string getPluginPackDependencyFilePath(const std::string &dirPath); +std::string findEntryScript(const std::string& dirPath); +std::string getPluginPackageName(const std::string& dirPath); +std::string getPluginPackDependencyFilePath(const std::string& dirPath); -bool processPythonDebugEngine(const std::string &cmd); +bool processPythonDebugEngine(const std::string& cmd); -bool processConsolePipCmd(const std::string &cmd); -int executePipCommand(std::string cmd); +bool processConsolePipCmd(const std::string& cmd); +int executePipCommand(std::string cmd); // This fix is used for Python3.10's bug: // The thread will freeze when creating a new engine while another thread is diff --git a/src/main/SafeGuardRecord.cpp b/src/main/SafeGuardRecord.cpp index 6d64b2e0..1245ad48 100644 --- a/src/main/SafeGuardRecord.cpp +++ b/src/main/SafeGuardRecord.cpp @@ -1,20 +1,18 @@ #include "main/Configs.h" +#include #include #include -#include std::ofstream record; void InitSafeGuardRecord() { - std::filesystem::create_directories("logs/LiteLoader"); - record.open(std::string("logs/LiteLoader/Sensitive_Operation_Records-") + - LLSE_BACKEND_TYPE + ".log", - std::ios::app); + std::filesystem::create_directories("logs/LiteLoader"); + record.open( + std::string("logs/LiteLoader/Sensitive_Operation_Records-") + LLSE_BACKEND_TYPE + ".log", + std::ios::app + ); } -void RecordOperation(const std::string &pluginName, - const std::string &operation, const std::string &content) { - if (record.is_open()) - record << "[" << operation << "]<" << pluginName << "> " << content - << std::endl; +void RecordOperation(const std::string& pluginName, const std::string& operation, const std::string& content) { + if (record.is_open()) record << "[" << operation << "]<" << pluginName << "> " << content << std::endl; } diff --git a/src/main/SafeGuardRecord.h b/src/main/SafeGuardRecord.h index 56184abd..783b9042 100644 --- a/src/main/SafeGuardRecord.h +++ b/src/main/SafeGuardRecord.h @@ -2,4 +2,4 @@ #include void InitSafeGuardRecord(); -void RecordOperation(const std::string& pluginName, const std::string &operation, const std::string& content); \ No newline at end of file +void RecordOperation(const std::string& pluginName, const std::string& operation, const std::string& content); \ No newline at end of file diff --git a/src/main/ScriptEngine.cpp b/src/main/ScriptEngine.cpp index c1e89616..87c791a4 100644 --- a/src/main/ScriptEngine.cpp +++ b/src/main/ScriptEngine.cpp @@ -28,58 +28,58 @@ ll::Logger logger("LegacyScript"); extern void LoadDepends(); extern void LoadMain(); -extern void BindAPIs(ScriptEngine *engine); +extern void BindAPIs(ScriptEngine* engine); extern void LoadDebugEngine(); void entry() { - // Register myself - // ll::registerPlugin(LLSE_LOADER_NAME, LLSE_LOADER_DESCRIPTION, - // LITELOADER_VERSION, - // {{"GitHub", "github.com/LiteLDev/LiteLoaderBDS"}}); + // Register myself + // ll::registerPlugin(LLSE_LOADER_NAME, LLSE_LOADER_DESCRIPTION, + // LITELOADER_VERSION, + // {{"GitHub", "github.com/LiteLDev/LiteLoaderBDS"}}); - // Load i18n files - // Translation::loadFromImpl(GetCurrentModule(), ll::getLoaderHandle()); + // Load i18n files + // Translation::loadFromImpl(GetCurrentModule(), ll::getLoaderHandle()); - // Init global share data - InitLocalShareData(); - InitGlobalShareData(); - InitSafeGuardRecord(); + // Init global share data + InitLocalShareData(); + InitGlobalShareData(); + InitSafeGuardRecord(); - // Welcome - if (localShareData->isFirstInstance) { - logger.info("ScriptEngine initializing..."); - } + // Welcome + if (localShareData->isFirstInstance) { + logger.info("ScriptEngine initializing..."); + } - EconomySystem::init(); + EconomySystem::init(); #ifdef LLSE_BACKEND_PYTHON - // This fix is used for Python3.10's bug: - // The thread will freeze when creating a new engine while another thread is - // blocking to read stdin Side effects: sys.stdin cannot be used after this - // patch. More info to see: https://github.com/python/cpython/issues/83526 - // - // Attention! When CPython is upgraded, this fix must be re-adapted or - // removed!! - // - PythonHelper::FixPython310Stdin::patchPython310CreateStdio(); - - PythonHelper::initPythonRuntime(); + // This fix is used for Python3.10's bug: + // The thread will freeze when creating a new engine while another thread is + // blocking to read stdin Side effects: sys.stdin cannot be used after this + // patch. More info to see: https://github.com/python/cpython/issues/83526 + // + // Attention! When CPython is upgraded, this fix must be re-adapted or + // removed!! + // + PythonHelper::FixPython310Stdin::patchPython310CreateStdio(); + + PythonHelper::initPythonRuntime(); #endif - // Pre-load depending libs - LoadDepends(); + // Pre-load depending libs + LoadDepends(); - // Load plugins - LoadMain(); + // Load plugins + LoadMain(); - // Register real-time debug - LoadDebugEngine(); + // Register real-time debug + LoadDebugEngine(); - // Register basic event listeners - InitBasicEventListeners(); + // Register basic event listeners + InitBasicEventListeners(); - // Init message system - InitMessageSystem(); + // Init message system + InitMessageSystem(); - MoreGlobal::Init(); + MoreGlobal::Init(); } \ No newline at end of file diff --git a/src/main/dllmain.cpp b/src/main/dllmain.cpp index ac266215..20c69c07 100644 --- a/src/main/dllmain.cpp +++ b/src/main/dllmain.cpp @@ -1,19 +1,17 @@ -#include #include +#include extern void entry(); extern "C" { - _declspec(dllexport) void onPostInit() { - std::ios::sync_with_stdio(false); - entry(); - } +_declspec(dllexport) void onPostInit() { + std::ios::sync_with_stdio(false); + entry(); +} } -BOOL APIENTRY DllMain(HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved) -{ - switch (ul_reason_for_call) - { +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { + switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: @@ -22,4 +20,3 @@ BOOL APIENTRY DllMain(HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserve } return TRUE; } - diff --git a/src/res/resource.h b/src/res/resource.h index 136f81e0..27cfe80d 100644 --- a/src/res/resource.h +++ b/src/res/resource.h @@ -5,9 +5,8 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 #endif #endif - diff --git a/src/utils/IniHelper.cpp b/src/utils/IniHelper.cpp index 9df6d62a..1d38ee0a 100644 --- a/src/utils/IniHelper.cpp +++ b/src/utils/IniHelper.cpp @@ -5,78 +5,73 @@ extern ll::Logger logger; -SimpleIni *SimpleIni::create(const std::string &path, - const std::string &defContent) { - if (!std::filesystem::exists(ll::string_utils::str2wstr(path))) { - // 创建新的 - std::filesystem::create_directories( - std::filesystem::path(ll::string_utils::str2wstr(path)) - .remove_filename() - .u8string()); +SimpleIni* SimpleIni::create(const std::string& path, const std::string& defContent) { + if (!std::filesystem::exists(ll::string_utils::str2wstr(path))) { + // 创建新的 + std::filesystem::create_directories( + std::filesystem::path(ll::string_utils::str2wstr(path)).remove_filename().u8string() + ); - std::ofstream iniFile(path); - if (iniFile.is_open() && defContent != "") - iniFile << defContent; - iniFile.close(); - } + std::ofstream iniFile(path); + if (iniFile.is_open() && defContent != "") iniFile << defContent; + iniFile.close(); + } - // 已存在 - auto root = new SimpleIni; - root->SetUnicode(true); - auto res = root->LoadFile(path.c_str()); - if (res < 0) { - logger.error("Failed in loading ini file"); - logger.error(string("Error Code:") + std::to_string((int)res)); - delete root; - return nullptr; - } else { - root->filePath = path; - return root; - } + // 已存在 + auto root = new SimpleIni; + root->SetUnicode(true); + auto res = root->LoadFile(path.c_str()); + if (res < 0) { + logger.error("Failed in loading ini file"); + logger.error(string("Error Code:") + std::to_string((int)res)); + delete root; + return nullptr; + } else { + root->filePath = path; + return root; + } } -bool SimpleIni::setInt(const string &sec, const string &key, int value) { - bool isOk = SetLongValue(sec.c_str(), key.c_str(), value) >= 0; - SaveFile(filePath.c_str()); - return isOk; +bool SimpleIni::setInt(const string& sec, const string& key, int value) { + bool isOk = SetLongValue(sec.c_str(), key.c_str(), value) >= 0; + SaveFile(filePath.c_str()); + return isOk; } -bool SimpleIni::setFloat(const string &sec, const string &key, float value) { - bool isOk = SetDoubleValue(sec.c_str(), key.c_str(), value) >= 0; - SaveFile(filePath.c_str()); - return isOk; +bool SimpleIni::setFloat(const string& sec, const string& key, float value) { + bool isOk = SetDoubleValue(sec.c_str(), key.c_str(), value) >= 0; + SaveFile(filePath.c_str()); + return isOk; } -bool SimpleIni::setString(const string &sec, const string &key, - const string &value) { - bool isOk = SetValue(sec.c_str(), key.c_str(), value.c_str()) >= 0; - SaveFile(filePath.c_str()); - return isOk; +bool SimpleIni::setString(const string& sec, const string& key, const string& value) { + bool isOk = SetValue(sec.c_str(), key.c_str(), value.c_str()) >= 0; + SaveFile(filePath.c_str()); + return isOk; } -bool SimpleIni::setBool(const string &sec, const string &key, bool value) { - bool isOk = SetBoolValue(sec.c_str(), key.c_str(), value) >= 0; - SaveFile(filePath.c_str()); - return isOk; +bool SimpleIni::setBool(const string& sec, const string& key, bool value) { + bool isOk = SetBoolValue(sec.c_str(), key.c_str(), value) >= 0; + SaveFile(filePath.c_str()); + return isOk; } -int SimpleIni::getInt(const string &sec, const string &key, int def) { - return GetLongValue(sec.c_str(), key.c_str(), def); +int SimpleIni::getInt(const string& sec, const string& key, int def) { + return GetLongValue(sec.c_str(), key.c_str(), def); } -float SimpleIni::getFloat(const string &sec, const string &key, float def) { - return (float)GetDoubleValue(sec.c_str(), key.c_str(), def); +float SimpleIni::getFloat(const string& sec, const string& key, float def) { + return (float)GetDoubleValue(sec.c_str(), key.c_str(), def); } -string SimpleIni::getString(const string &sec, const string &key, - const string &def) { - return GetValue(sec.c_str(), key.c_str(), def.c_str()); +string SimpleIni::getString(const string& sec, const string& key, const string& def) { + return GetValue(sec.c_str(), key.c_str(), def.c_str()); } -bool SimpleIni::getBool(const string &sec, const string &key, bool def) { - return GetBoolValue(sec.c_str(), key.c_str(), def); +bool SimpleIni::getBool(const string& sec, const string& key, bool def) { + return GetBoolValue(sec.c_str(), key.c_str(), def); } -bool SimpleIni::deleteKey(const std::string &sec, const std::string &key) { - return Delete(sec.c_str(), key.c_str(), true); +bool SimpleIni::deleteKey(const std::string& sec, const std::string& key) { + return Delete(sec.c_str(), key.c_str(), true); } \ No newline at end of file diff --git a/src/utils/IniHelper.h b/src/utils/IniHelper.h index e5e0a2e8..33c1f887 100644 --- a/src/utils/IniHelper.h +++ b/src/utils/IniHelper.h @@ -6,21 +6,18 @@ using std::string; class SimpleIni : public CSimpleIniA { public: - std::string filePath; + std::string filePath; - static inline SimpleIni *create(const std::string &path) { - return create(path, ""); - } - static SimpleIni *create(const std::string &path, - const std::string &defContent); + static inline SimpleIni* create(const std::string& path) { return create(path, ""); } + static SimpleIni* create(const std::string& path, const std::string& defContent); - bool setInt(const string &sec, const string &key, int value); - bool setFloat(const string &sec, const string &key, float value); - bool setString(const string &sec, const string &key, const string &value); - bool setBool(const string &sec, const string &key, bool value); - int getInt(const string &sec, const string &key, int def); - float getFloat(const string &sec, const string &key, float def); - string getString(const string &sec, const string &key, const string &def); - bool getBool(const string &sec, const string &key, bool def); - bool deleteKey(const std::string &sec, const std::string &key); + bool setInt(const string& sec, const string& key, int value); + bool setFloat(const string& sec, const string& key, float value); + bool setString(const string& sec, const string& key, const string& value); + bool setBool(const string& sec, const string& key, bool value); + int getInt(const string& sec, const string& key, int def); + float getFloat(const string& sec, const string& key, float def); + string getString(const string& sec, const string& key, const string& def); + bool getBool(const string& sec, const string& key, bool def); + bool deleteKey(const std::string& sec, const std::string& key); }; \ No newline at end of file diff --git a/src/utils/JsonHelper.h b/src/utils/JsonHelper.h index e5680de4..47163f1b 100644 --- a/src/utils/JsonHelper.h +++ b/src/utils/JsonHelper.h @@ -11,61 +11,56 @@ using namespace nlohmann; extern ll::Logger logger; -inline ordered_json CreateJson(const std::string &path, - const std::string &defContent, - bool allowComment = true) { - ordered_json jsonConf; - if (!std::filesystem::exists(ll::string_utils::str2wstr(path))) { - if (path.find('/') != - std::string::npos) { // e.g. plugins/LiteLoader/LiteLoader.json - std::size_t pos = path.find_last_of('/'); - if (pos != std::string::npos) { - std::string dirPath = path.substr(0, pos); - CreateDirs(dirPath); - } - } else if (path.find('\\') != - std::string::npos) { // e.g. plugins\\LiteLoader\\LiteLoader.json - std::size_t pos = path.find_last_of('\\'); - if (pos != std::string::npos) { - std::string dirPath = path.substr(0, pos); - CreateDirs(dirPath); - } - } else { - logger.error("Fail in create json file!"); - logger.error("invalid path"); - jsonConf = ordered_json::object(); - } +inline ordered_json CreateJson(const std::string& path, const std::string& defContent, bool allowComment = true) { + ordered_json jsonConf; + if (!std::filesystem::exists(ll::string_utils::str2wstr(path))) { + if (path.find('/') != std::string::npos) { // e.g. plugins/LiteLoader/LiteLoader.json + std::size_t pos = path.find_last_of('/'); + if (pos != std::string::npos) { + std::string dirPath = path.substr(0, pos); + CreateDirs(dirPath); + } + } else if (path.find('\\') != std::string::npos) { // e.g. plugins\\LiteLoader\\LiteLoader.json + std::size_t pos = path.find_last_of('\\'); + if (pos != std::string::npos) { + std::string dirPath = path.substr(0, pos); + CreateDirs(dirPath); + } + } else { + logger.error("Fail in create json file!"); + logger.error("invalid path"); + jsonConf = ordered_json::object(); + } - if (!defContent.empty()) { - try { - jsonConf = ordered_json::parse(defContent, nullptr, true, allowComment); - } catch (std::exception &e) { - logger.error("Fail to parse default json content!"); - logger.error(ll::string_utils::tou8str(e.what())); - jsonConf = ordered_json::object(); - } - } else { - jsonConf = ordered_json::object(); - } + if (!defContent.empty()) { + try { + jsonConf = ordered_json::parse(defContent, nullptr, true, allowComment); + } catch (std::exception& e) { + logger.error("Fail to parse default json content!"); + logger.error(ll::string_utils::tou8str(e.what())); + jsonConf = ordered_json::object(); + } + } else { + jsonConf = ordered_json::object(); + } - std::ofstream jsonFile(path); - if (jsonFile.is_open() && !defContent.empty()) - jsonFile << jsonConf.dump(4); - jsonFile.close(); - } else { - // 已存在 - auto jsonTexts = ReadAllFile(path); - if (!jsonTexts) { - jsonConf = ordered_json::object(); + std::ofstream jsonFile(path); + if (jsonFile.is_open() && !defContent.empty()) jsonFile << jsonConf.dump(4); + jsonFile.close(); } else { - try { - jsonConf = ordered_json::parse(*jsonTexts, nullptr, true, allowComment); - } catch (std::exception &e) { - logger.error("Fail to parse json content in file!"); - logger.error(ll::string_utils::tou8str(e.what())); - jsonConf = ordered_json::object(); - } + // 已存在 + auto jsonTexts = ReadAllFile(path); + if (!jsonTexts) { + jsonConf = ordered_json::object(); + } else { + try { + jsonConf = ordered_json::parse(*jsonTexts, nullptr, true, allowComment); + } catch (std::exception& e) { + logger.error("Fail to parse json content in file!"); + logger.error(ll::string_utils::tou8str(e.what())); + jsonConf = ordered_json::object(); + } + } } - } - return jsonConf; + return jsonConf; } \ No newline at end of file diff --git a/src/utils/Utils.cpp b/src/utils/Utils.cpp index 3cdce18c..fe086d0e 100644 --- a/src/utils/Utils.cpp +++ b/src/utils/Utils.cpp @@ -10,103 +10,130 @@ #include #include -std::vector SplitCmdLine(const std::string ¶s) { - if (paras.empty()) - return std::vector(); +std::vector SplitCmdLine(const std::string& paras) { + if (paras.empty()) return std::vector(); - std::vector res; - std::string now, strInQuote = ""; - std::istringstream strIn(paras); - while (strIn >> now) { + std::vector res; + std::string now, strInQuote = ""; + std::istringstream strIn(paras); + while (strIn >> now) { + if (!strInQuote.empty()) { + strInQuote = strInQuote + " " + now; + if (now.back() == '\"') { + strInQuote.pop_back(); + res.push_back(strInQuote.erase(0, 1)); + strInQuote = ""; + } + } else { + if (now.front() == '\"') { + if (now.back() == '\"') { + now = now.substr(1, now.size() - 2); + res.push_back(now); + } else strInQuote = now; + } else res.push_back(now); + } + } if (!strInQuote.empty()) { - strInQuote = strInQuote + " " + now; - if (now.back() == '\"') { - strInQuote.pop_back(); - res.push_back(strInQuote.erase(0, 1)); - strInQuote = ""; - } - } else { - if (now.front() == '\"') { - if (now.back() == '\"') { - now = now.substr(1, now.size() - 2); - res.push_back(now); - } else - strInQuote = now; - } else - res.push_back(now); + std::istringstream leftIn(strInQuote); + while (leftIn >> now) res.push_back(now); } - } - if (!strInQuote.empty()) { - std::istringstream leftIn(strInQuote); - while (leftIn >> now) - res.push_back(now); - } - return res; + return res; } -bool IsVersionLess(const std::string &v1, const std::string &v2) { - auto vers1 = ll::string_utils::splitByPattern(v1, "."); - auto vers2 = ll::string_utils::splitByPattern(v2, "."); - return IsVersionLess( - std::stoi(std::string(vers1[0])), std::stoi(std::string(vers1[1])), - std::stoi(std::string(vers1[2])), std::stoi(std::string(vers2[0])), - std::stoi(std::string(vers2[1])), std::stoi(std::string(vers2[2]))); +bool IsVersionLess(const std::string& v1, const std::string& v2) { + auto vers1 = ll::string_utils::splitByPattern(v1, "."); + auto vers2 = ll::string_utils::splitByPattern(v2, "."); + return IsVersionLess( + std::stoi(std::string(vers1[0])), + std::stoi(std::string(vers1[1])), + std::stoi(std::string(vers1[2])), + std::stoi(std::string(vers2[0])), + std::stoi(std::string(vers2[1])), + std::stoi(std::string(vers2[2])) + ); } bool IsVersionLess(int v1a, int v1b, int v1c, int v2a, int v2b, int v2c) { - return (v1a < v2a || (v1a == v2a && v1b < v2b) || - (v1a == v2a && v1b == v2b && v1c < v2c)); + return (v1a < v2a || (v1a == v2a && v1b < v2b) || (v1a == v2a && v1b == v2b && v1c < v2c)); } -wchar_t *str2cwstr(std::string str) { - auto len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0); - wchar_t *buffer = new wchar_t[len + 1]; - MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, buffer, len + 1); - buffer[len] = L'\0'; - return buffer; +wchar_t* str2cwstr(std::string str) { + auto len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0); + wchar_t* buffer = new wchar_t[len + 1]; + MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, buffer, len + 1); + buffer[len] = L'\0'; + return buffer; } unsigned long long GetCurrentTimeStampMS() { - SYSTEMTIME currentTime = {0}; - GetLocalTime(¤tTime); + SYSTEMTIME currentTime = {0}; + GetLocalTime(¤tTime); - struct tm currTm = {currentTime.wSecond, currentTime.wMinute, - currentTime.wHour, currentTime.wDay, - currentTime.wMonth - 1, currentTime.wYear - 1900}; + struct tm currTm = { + currentTime.wSecond, + currentTime.wMinute, + currentTime.wHour, + currentTime.wDay, + currentTime.wMonth - 1, + currentTime.wYear - 1900}; - unsigned long long nNow = mktime(&currTm) * 1000 + currentTime.wMilliseconds; - return nNow; + unsigned long long nNow = mktime(&currTm) * 1000 + currentTime.wMilliseconds; + return nNow; } std::string Raw_GetDateTimeStr() { - time_t t = time(NULL); - tm ts; - localtime_s(&ts, &t); - char buf[24] = {0}; - strftime(buf, 24, "%Y-%m-%d %H:%M:%S", &ts); - return string(buf); + time_t t = time(NULL); + tm ts; + localtime_s(&ts, &t); + char buf[24] = {0}; + strftime(buf, 24, "%Y-%m-%d %H:%M:%S", &ts); + return string(buf); } std::string Raw_RandomGuid() { - GUID guid; - CoCreateGuid(&guid); + GUID guid; + CoCreateGuid(&guid); - char dst[36] = {0}; - snprintf(dst, 36, "%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x", guid.Data1, - guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], - guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], - guid.Data4[7]); - return string(dst); + char dst[36] = {0}; + snprintf( + dst, + 36, + "%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x", + guid.Data1, + guid.Data2, + guid.Data3, + guid.Data4[0], + guid.Data4[1], + guid.Data4[2], + guid.Data4[3], + guid.Data4[4], + guid.Data4[5], + guid.Data4[6], + guid.Data4[7] + ); + return string(dst); } std::wstring Raw_RandomGuidW() { - GUID guid; - CoCreateGuid(&guid); + GUID guid; + CoCreateGuid(&guid); - wchar_t dst[36] = {0}; - _snwprintf_s(dst, 36, L"%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x", - guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], - guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], - guid.Data4[6], guid.Data4[7]); - return std::wstring(dst); + wchar_t dst[36] = {0}; + _snwprintf_s( + dst, + 36, + L"%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x", + guid.Data1, + guid.Data2, + guid.Data3, + guid.Data4[0], + guid.Data4[1], + guid.Data4[2], + guid.Data4[3], + guid.Data4[4], + guid.Data4[5], + guid.Data4[6], + guid.Data4[7] + ); + return std::wstring(dst); } \ No newline at end of file diff --git a/src/utils/Utils.h b/src/utils/Utils.h index 4bbd224d..c1224781 100644 --- a/src/utils/Utils.h +++ b/src/utils/Utils.h @@ -4,15 +4,15 @@ #include #include -std::vector SplitCmdLine(const std::string ¶s); +std::vector SplitCmdLine(const std::string& paras); -bool IsVersionLess(const std::string &v1, const std::string &v2); +bool IsVersionLess(const std::string& v1, const std::string& v2); bool IsVersionLess(int v1a, int v1b, int v1c, int v2a, int v2b, int v2c); unsigned long long GetCurrentTimeStampMS(); -wchar_t *str2cwstr(std::string str); +wchar_t* str2cwstr(std::string str); // System -std::string Raw_GetDateTimeStr(); -std::string Raw_RandomGuid(); +std::string Raw_GetDateTimeStr(); +std::string Raw_RandomGuid(); std::wstring Raw_RandomGuidW();