From 3cdda73eac2a69a4cb865f0bc427363122765f9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E6=80=9D=E6=B5=B7?= <10001@qq.com> Date: Thu, 9 Jan 2025 14:22:37 +0800 Subject: [PATCH] init --- .github/workflows/publish-release.yml | 51 + .github/workflows/sync.yml | 288 +++++ LICENSE.md | 21 + LICENSE.md.meta | 3 + README.md | 30 + README.md.meta | 3 + Runtime.meta | 3 + Runtime/BeanBase.cs | 10 + Runtime/BeanBase.cs.meta | 3 + Runtime/ByteBuf.cs | 1608 +++++++++++++++++++++++++ Runtime/ByteBuf.cs.meta | 3 + Runtime/ITypeId.cs | 10 + Runtime/ITypeId.cs.meta | 3 + Runtime/LuBan.Runtime.asmdef | 15 + Runtime/LuBan.Runtime.asmdef.meta | 3 + Runtime/LuBanCroppingHelper.cs | 23 + Runtime/LuBanCroppingHelper.cs.meta | 3 + Runtime/StringUtil.cs | 53 + Runtime/StringUtil.cs.meta | 3 + Runtime/link.xml | 5 + Runtime/link.xml.meta | 3 + package.json | 22 + package.json.meta | 7 + 23 files changed, 2173 insertions(+) create mode 100644 .github/workflows/publish-release.yml create mode 100644 .github/workflows/sync.yml create mode 100644 LICENSE.md create mode 100644 LICENSE.md.meta create mode 100644 README.md create mode 100644 README.md.meta create mode 100644 Runtime.meta create mode 100644 Runtime/BeanBase.cs create mode 100644 Runtime/BeanBase.cs.meta create mode 100644 Runtime/ByteBuf.cs create mode 100644 Runtime/ByteBuf.cs.meta create mode 100644 Runtime/ITypeId.cs create mode 100644 Runtime/ITypeId.cs.meta create mode 100644 Runtime/LuBan.Runtime.asmdef create mode 100644 Runtime/LuBan.Runtime.asmdef.meta create mode 100644 Runtime/LuBanCroppingHelper.cs create mode 100644 Runtime/LuBanCroppingHelper.cs.meta create mode 100644 Runtime/StringUtil.cs create mode 100644 Runtime/StringUtil.cs.meta create mode 100644 Runtime/link.xml create mode 100644 Runtime/link.xml.meta create mode 100644 package.json create mode 100644 package.json.meta diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml new file mode 100644 index 0000000..90b9618 --- /dev/null +++ b/.github/workflows/publish-release.yml @@ -0,0 +1,51 @@ +name: Publish Release + +on: + push: + tags: + - '*' + # branches: [main] + #schedule: + # 定时任务,每天 UTC 时间 0 点运行 + #- cron: "0 0 * * *" + #workflow_dispatch: +permissions: # Global permissions configuration starts here + contents: read # 'read' access to repository contents + pull-requests: write # 'write' access to pull requests + +jobs: + tags: + runs-on: ubuntu-latest + + permissions: + contents: write + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 # 为了 git pull --unshallow,我们需要获取所有的提交历史 + + - name: Set up Git user + run: | + git config --global user.email "wangfj11@foxmail.com" + git config --global user.name "AlianBlank" + + - name: "✏️ Generate release changelog" + uses: heinrichreimer/action-github-changelog-generator@v2.3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Commit CHANGELOG.md + run: | + git add CHANGELOG.md + git commit -m "[修改]1.修改更新日志" + + - name: change-version-by-tag + uses: AlianBlank/github-action-tag-version@1.0.0 + with: + version: ${{ github.ref_name }} + + - name: Push changes + uses: ad-m/github-push-action@master + with: + branch: ${{ github.head_ref }} \ No newline at end of file diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml new file mode 100644 index 0000000..fb1c812 --- /dev/null +++ b/.github/workflows/sync.yml @@ -0,0 +1,288 @@ +name: Sync Github To Image + +on: + push: + branches: [main] + #schedule: + # 定时任务,每天 UTC 时间 0 点运行 + #- cron: "0 0 * * *" + #workflow_dispatch: + +jobs: + sync-gitlink: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 # 为了 git pull --unshallow,我们需要获取所有的提交历史 + + - name: Set up Git user + run: | + git config --global user.email "wangfj11@foxmail.com" + git config --global user.name "AlianBlank" + + - name: Set SSH + run: | + mkdir -p ~/.ssh + echo "${{ secrets.GITLINK_ID_RSA }}" >> ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + eval $(ssh-agent -s) && ssh-add ~/.ssh/id_rsa + # 信任域名 + ssh-keyscan -H code.gitlink.org.cn >> ~/.ssh/known_hosts + + # 查看当前分支 + - name: Check current branch + run: echo 当前分支:${{ github.ref_name }} ${{ github.Repository }} + + # 查看远端 地址 + - name: echo git url + run: echo git@code.gitlink.org.cn:${{ github.Repository }}.git + + # 添加远端 + - name: add remote url + run: git remote add gitlink "git@code.gitlink.org.cn:${{ github.Repository }}.git" + + # 获取 + - name: fetch + run: git fetch --prune gitlink --tags --verbose + + # 拉取 + - name: pull and push + run: | + if [ "${{ github.ref_name }}" ]; then + git checkout ${{ github.ref_name }} + git pull --progress -v --no-rebase gitlink ${{ github.ref_name }} --tags --verbose || echo 远端不存在${{ github.ref_name }}分支; + git push -u gitlink ${{ github.ref_name }} --tags --verbose + fi + + sync-gitlab: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 # 为了 git pull --unshallow,我们需要获取所有的提交历史 + + - name: Set up Git user + run: | + git config --global user.email "wangfj11@foxmail.com" + git config --global user.name "AlianBlank" + + - name: Set SSH + run: | + mkdir -p ~/.ssh + echo "${{ secrets.GITLAB_ID_RSA }}" >> ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + eval $(ssh-agent -s) && ssh-add ~/.ssh/id_rsa + # 信任域名 + ssh-keyscan -H gitlab.com >> ~/.ssh/known_hosts + # 查看当前分支 + - name: Check current branch + run: echo 当前分支:${{ github.ref_name }} ${{ github.Repository }} + # 查看远端 地址 + - name: echo git url + run: echo git@gitlab.com:${{ github.Repository }}.git + + # 添加远端 + - name: add remote url + run: git remote add gitlab "git@gitlab.com:${{ github.Repository }}.git" + + # 获取 + - name: fetch + run: git fetch --prune gitlab --tags --verbose + + # 拉取 + - name: pull and push + run: | + if [ "${{ github.ref_name }}" ]; then + git checkout ${{ github.ref_name }} + git pull --progress -v --no-rebase gitlab ${{ github.ref_name }} --tags --verbose || echo 远端不存在${{ github.ref_name }}分支; + git push -u gitlab ${{ github.ref_name }} --tags --verbose + fi + + sync-gitee: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 # 为了 git pull --unshallow,我们需要获取所有的提交历史 + + - name: Set up Git user + run: | + git config --global user.email "wangfj11@foxmail.com" + git config --global user.name "AlianBlank" + + - name: Set SSH + run: | + mkdir -p ~/.ssh + echo "${{ secrets.GITEE_ID_RSA }}" >> ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + eval $(ssh-agent -s) && ssh-add ~/.ssh/id_rsa + # 信任域名 + ssh-keyscan -H gitee.com >> ~/.ssh/known_hosts + # 查看当前分支 + - name: Check current branch + run: echo 当前分支:${{ github.ref_name }} ${{ github.Repository }} + # 查看远端 地址 + - name: echo git url + run: echo git@gitee.com:${{ github.Repository }}.git + + # 添加远端 + - name: add remote url + run: git remote add gitee "git@gitee.com:${{ github.Repository }}.git" + + # 获取 + - name: fetch + run: git fetch --prune gitee --tags --verbose + + # 拉取 + - name: pull and push + run: | + if [ "${{ github.ref_name }}" ]; then + git checkout ${{ github.ref_name }} + git pull --progress -v --no-rebase gitee ${{ github.ref_name }} --tags --verbose || echo 远端不存在${{ github.ref_name }}分支; + git push -u gitee ${{ github.ref_name }} --tags --verbose + fi + + sync-atomgit: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 # 为了 git pull --unshallow,我们需要获取所有的提交历史 + + - name: Set up Git user + run: | + git config --global user.email "wangfj11@foxmail.com" + git config --global user.name "AlianBlank" + + - name: Set SSH + run: | + mkdir -p ~/.ssh + echo "${{ secrets.ATOMGIT_ID_RSA }}" >> ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + eval $(ssh-agent -s) && ssh-add ~/.ssh/id_rsa + # 信任域名 + ssh-keyscan -H atomgit.com >> ~/.ssh/known_hosts + # 查看当前分支 + - name: Check current branch + run: echo 当前分支:${{ github.ref_name }} ${{ github.Repository }} + # 查看远端 地址 + - name: echo git url + run: echo git@atomgit.com:${{ github.Repository }}.git + + # 添加远端 + - name: add remote url + run: git remote add atomgit "git@atomgit.com:${{ github.Repository }}.git" + + # 获取 + - name: fetch + run: git fetch --prune atomgit --tags --verbose + + # 拉取 + - name: pull and push + run: | + if [ "${{ github.ref_name }}" ]; then + git checkout ${{ github.ref_name }} + git pull --progress -v --no-rebase atomgit ${{ github.ref_name }} --tags --verbose || echo 远端不存在${{ github.ref_name }}分支; + git push -u atomgit ${{ github.ref_name }} --tags --verbose + fi + + sync-gitcode: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 # 为了 git pull --unshallow,我们需要获取所有的提交历史 + + - name: Set up Git user + run: | + git config --global user.email "wangfj11@foxmail.com" + git config --global user.name "AlianBlank" + + - name: Set SSH + run: | + mkdir -p ~/.ssh + echo "${{ secrets.GITCODE_ID_RSA }}" >> ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + eval $(ssh-agent -s) && ssh-add ~/.ssh/id_rsa + # 信任域名 + ssh-keyscan -H gitcode.net >> ~/.ssh/known_hosts + # 查看当前分支 + - name: Check current branch + run: echo 当前分支:${{ github.ref_name }} ${{ github.Repository }} + # 查看远端 地址 + - name: echo git url + run: echo git@gitcode.net:${{ github.Repository }}.git + + # 添加远端 + - name: add remote url + run: git remote add gitcode "git@gitcode.net:${{ github.Repository }}.git" + + # 获取 + - name: fetch + run: git fetch --prune gitcode --tags --verbose + + # 拉取 + - name: pull and push + run: | + if [ "${{ github.ref_name }}" ]; then + git checkout ${{ github.ref_name }} + git pull --progress -v --no-rebase gitcode ${{ github.ref_name }} --tags --verbose || echo 远端不存在${{ github.ref_name }}分支; + git push -u gitcode ${{ github.ref_name }} --tags --verbose + fi + + sync-framagit: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 # 为了 git pull --unshallow,我们需要获取所有的提交历史 + + - name: Set up Git user + run: | + git config --global user.email "wangfj11@foxmail.com" + git config --global user.name "AlianBlank" + + - name: Set SSH + run: | + mkdir -p ~/.ssh + echo "${{ secrets.FRAMAGIT_ID_RSA }}" >> ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + eval $(ssh-agent -s) && ssh-add ~/.ssh/id_rsa + # 信任域名 + ssh-keyscan -H framagit.org >> ~/.ssh/known_hosts + # 查看当前分支 + - name: Check current branch + run: echo 当前分支:${{ github.ref_name }} ${{ github.Repository }} + # 查看远端 地址 + - name: echo git url + run: echo git@framagit.org:${{ github.Repository }}.git + + # 添加远端 + - name: add remote url + run: git remote add framagit "git@framagit.org:${{ github.Repository }}.git" + + # 获取 + - name: fetch + run: git fetch --prune framagit --tags --verbose + + # 拉取 + - name: pull and push + run: | + if [ "${{ github.ref_name }}" ]; then + git checkout ${{ github.ref_name }} + git pull --progress -v --no-rebase framagit ${{ github.ref_name }} --tags --verbose || echo 远端不存在${{ github.ref_name }}分支; + git push -u framagit ${{ github.ref_name }} --tags --verbose + fi diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..f3828d5 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Blank + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/LICENSE.md.meta b/LICENSE.md.meta new file mode 100644 index 0000000..e740473 --- /dev/null +++ b/LICENSE.md.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 65ab0fd9d052403ebdaead4404d96767 +timeCreated: 1702092259 \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..ccb3105 --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ + +# 非常强大的配置表解决方案 + +uban是一个强大、易用、优雅、稳定的游戏配置解决方案。它设计目标为满足从小型到超大型游戏项目的简单到复杂的游戏配置工作流需求。 + +luban可以处理丰富的文件类型,支持主流的语言,可以生成多种导出格式,支持丰富的数据检验功能,具有良好的跨平台能力,并且生成极快。 luban有清晰优雅的生成管线设计,支持良好的模块化和插件化,方便开发者进行二次开发。开发者很容易就能将luban适配到自己的配置格式,定制出满足项目要求的强大的配置工具。 + +luban标准化了游戏配置开发工作流,可以极大提升策划和程序的工作效率。 + +该库主要服务于 `https://github.com/GameFrameX/GameFrameX` 作为子库使用。 + + +# 使用方式(三种方式) +1. 直接在 `manifest.json` 文件中添加以下内容 + ```json + {"com.gameframex.unity.focus-creative-games.luban": "https://github.com/gameframex/com.gameframex.unity.focus-creative-games.luban.git"} + ``` +2. 在Unity 的`Packages Manager` 中使用`Git URL` 的方式添加库,地址为:https://github.com/gameframex/com.gameframex.unity.focus-creative-games.luban.git + +3. 直接下载仓库放置到Unity 项目的`Packages` 目录下。会自动加载识别 + +# 改动功能 + +1. 增加 `Packages` 的支持 +2. 移除ODIN 的依赖 +3. 增加防裁剪的帮助类。需要在启动的主场景中挂载 `LuBanCroppingHelper` 脚本即可 + +# 使用文档 + +https://luban.doc.code-philosophy.com/docs/intro \ No newline at end of file diff --git a/README.md.meta b/README.md.meta new file mode 100644 index 0000000..0275d78 --- /dev/null +++ b/README.md.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5c4f345aed3f4bbe89a61e801e26701a +timeCreated: 1702092253 \ No newline at end of file diff --git a/Runtime.meta b/Runtime.meta new file mode 100644 index 0000000..611e6ad --- /dev/null +++ b/Runtime.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f8d53bef08d0491fbbecdca8822460f4 +timeCreated: 1684724064 \ No newline at end of file diff --git a/Runtime/BeanBase.cs b/Runtime/BeanBase.cs new file mode 100644 index 0000000..4b89980 --- /dev/null +++ b/Runtime/BeanBase.cs @@ -0,0 +1,10 @@ +using UnityEngine.Scripting; + +namespace LuBan.Runtime +{ + [Preserve] + public abstract class BeanBase : ITypeId + { + public abstract int GetTypeId(); + } +} \ No newline at end of file diff --git a/Runtime/BeanBase.cs.meta b/Runtime/BeanBase.cs.meta new file mode 100644 index 0000000..0b4f02f --- /dev/null +++ b/Runtime/BeanBase.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 560e8a442bea463c938d8741a0cf5b44 +timeCreated: 1684724088 \ No newline at end of file diff --git a/Runtime/ByteBuf.cs b/Runtime/ByteBuf.cs new file mode 100644 index 0000000..804e3f1 --- /dev/null +++ b/Runtime/ByteBuf.cs @@ -0,0 +1,1608 @@ +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Text; +using UnityEngine.Scripting; + +namespace LuBan.Runtime +{ + [Preserve] + public enum EDeserializeError + { + OK, + NOT_ENOUGH, + EXCEED_SIZE, + // UNMARSHAL_ERR, + } + + [Preserve] + public class SerializationException : Exception + { + public SerializationException() + { + } + + public SerializationException(string msg) : base(msg) + { + } + + public SerializationException(string message, Exception innerException) : base(message, innerException) + { + } + } + + [Preserve] + public readonly struct SegmentSaveState + { + public SegmentSaveState(int readerIndex, int writerIndex) + { + ReaderIndex = readerIndex; + WriterIndex = writerIndex; + } + + public int ReaderIndex { get; } + + public int WriterIndex { get; } + } + + [Preserve] + public sealed class ByteBuf : ICloneable, IEquatable + { + public ByteBuf() + { + Bytes = Array.Empty(); + ReaderIndex = WriterIndex = 0; + } + + public ByteBuf(int capacity) + { + Bytes = capacity > 0 ? new byte[capacity] : Array.Empty(); + ReaderIndex = 0; + WriterIndex = 0; + } + + public ByteBuf(byte[] bytes) + { + Bytes = bytes; + ReaderIndex = 0; + WriterIndex = Capacity; + } + + public ByteBuf(byte[] bytes, int readIndex, int writeIndex) + { + Bytes = bytes; + ReaderIndex = readIndex; + WriterIndex = writeIndex; + } + + public ByteBuf(int capacity, Action releaser) : this(capacity) + { + _releaser = releaser; + } + + public static ByteBuf Wrap(byte[] bytes) + { + return new ByteBuf(bytes, 0, bytes.Length); + } + + public void Replace(byte[] bytes) + { + Bytes = bytes; + ReaderIndex = 0; + WriterIndex = Capacity; + } + + public void Replace(byte[] bytes, int beginPos, int endPos) + { + Bytes = bytes; + ReaderIndex = beginPos; + WriterIndex = endPos; + } + + public int ReaderIndex { get; set; } + + public int WriterIndex { get; set; } + + private readonly Action _releaser; + + public int Capacity => Bytes.Length; + + public int Size + { + get { return WriterIndex - ReaderIndex; } + } + + public bool Empty => WriterIndex <= ReaderIndex; + + public bool NotEmpty => WriterIndex > ReaderIndex; + + + public void AddWriteIndex(int add) + { + WriterIndex += add; + } + + public void AddReadIndex(int add) + { + ReaderIndex += add; + } + +#pragma warning disable CA1819 // 属性不应返回数组 + public byte[] Bytes { get; private set; } +#pragma warning restore CA1819 // 属性不应返回数组 + + public byte[] CopyData() + { + var n = Remaining; + if (n > 0) + { + var arr = new byte[n]; + Buffer.BlockCopy(Bytes, ReaderIndex, arr, 0, n); + return arr; + } + else + { + return Array.Empty(); + } + } + + public int Remaining + { + get { return WriterIndex - ReaderIndex; } + } + + public void DiscardReadBytes() + { + WriterIndex -= ReaderIndex; + Array.Copy(Bytes, ReaderIndex, Bytes, 0, WriterIndex); + ReaderIndex = 0; + } + + public int NotCompactWritable + { + get { return Capacity - WriterIndex; } + } + + public void WriteBytesWithoutSize(byte[] bs) + { + WriteBytesWithoutSize(bs, 0, bs.Length); + } + + public void WriteBytesWithoutSize(byte[] bs, int offset, int len) + { + EnsureWrite(len); + Buffer.BlockCopy(bs, offset, Bytes, WriterIndex, len); + WriterIndex += len; + } + + public void Clear() + { + ReaderIndex = WriterIndex = 0; + } + + private const int MIN_CAPACITY = 16; + + private static int PropSize(int initSize, int needSize) + { + for (int i = Math.Max(initSize, MIN_CAPACITY);; i <<= 1) + { + if (i >= needSize) + { + return i; + } + } + } + + private void EnsureWrite0(int size) + { + var needSize = WriterIndex + size - ReaderIndex; + if (needSize < Capacity) + { + WriterIndex -= ReaderIndex; + Array.Copy(Bytes, ReaderIndex, Bytes, 0, WriterIndex); + ReaderIndex = 0; + } + else + { + int newCapacity = PropSize(Capacity, needSize); + var newBytes = new byte[newCapacity]; + WriterIndex -= ReaderIndex; + Buffer.BlockCopy(Bytes, ReaderIndex, newBytes, 0, WriterIndex); + ReaderIndex = 0; + Bytes = newBytes; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void EnsureWrite(int size) + { + if (WriterIndex + size > Capacity) + { + EnsureWrite0(size); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void EnsureRead(int size) + { + if (ReaderIndex + size > WriterIndex) + { + throw new SerializationException(); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private bool CanRead(int size) + { + return (ReaderIndex + size <= WriterIndex); + } + + public void Append(byte x) + { + EnsureWrite(1); + Bytes[WriterIndex++] = x; + } + + public void WriteBool(bool b) + { + EnsureWrite(1); + Bytes[WriterIndex++] = (byte)(b ? 1 : 0); + } + + public bool ReadBool() + { + EnsureRead(1); + return Bytes[ReaderIndex++] != 0; + } + + public void WriteByte(byte x) + { + EnsureWrite(1); + Bytes[WriterIndex++] = x; + } + + public byte ReadByte() + { + EnsureRead(1); + return Bytes[ReaderIndex++]; + } + + + public void WriteShort(short x) + { + if (x >= 0) + { + if (x < 0x80) + { + EnsureWrite(1); + Bytes[WriterIndex++] = (byte)x; + return; + } + else if (x < 0x4000) + { + EnsureWrite(2); + Bytes[WriterIndex + 1] = (byte)x; + Bytes[WriterIndex] = (byte)((x >> 8) | 0x80); + WriterIndex += 2; + return; + } + } + + EnsureWrite(3); + Bytes[WriterIndex] = 0xff; + Bytes[WriterIndex + 2] = (byte)x; + Bytes[WriterIndex + 1] = (byte)(x >> 8); + WriterIndex += 3; + } + + public short ReadShort() + { + EnsureRead(1); + int h = Bytes[ReaderIndex]; + if (h < 0x80) + { + ReaderIndex++; + return (short)h; + } + else if (h < 0xc0) + { + EnsureRead(2); + int x = ((h & 0x3f) << 8) | Bytes[ReaderIndex + 1]; + ReaderIndex += 2; + return (short)x; + } + else if ((h == 0xff)) + { + EnsureRead(3); + int x = (Bytes[ReaderIndex + 1] << 8) | Bytes[ReaderIndex + 2]; + ReaderIndex += 3; + return (short)x; + } + else + { + throw new SerializationException(); + } + } + + public short ReadFshort() + { + EnsureRead(2); + short x; +#if CPU_SUPPORT_MEMORY_NOT_ALIGN + unsafe + { + fixed (byte* b = &Bytes[ReaderIndex]) + { + x = *(short*)b; + } + } +#else + x = (short)((Bytes[ReaderIndex + 1] << 8) | Bytes[ReaderIndex]); + +#endif + ReaderIndex += 2; + return x; + } + + public void WriteFshort(short x) + { + EnsureWrite(2); +#if CPU_SUPPORT_MEMORY_NOT_ALIGN + unsafe + { + fixed (byte* b = &Bytes[WriterIndex]) + { + *(short*)b = x; + } + } +#else + Bytes[WriterIndex] = (byte)x; + Bytes[WriterIndex + 1] = (byte)(x >> 8); +#endif + WriterIndex += 2; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void WriteInt(int x) + { + WriteUint((uint)x); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int ReadInt() + { + return (int)ReadUint(); + } + + + public void WriteUint(uint x) + { + // 如果有修改,记得也把 EndWriteSegment改了 + // 0 111 1111 + if (x < 0x80) + { + EnsureWrite(1); + Bytes[WriterIndex++] = (byte)x; + } + else if (x < 0x4000) // 10 11 1111, - + { + EnsureWrite(2); + Bytes[WriterIndex + 1] = (byte)x; + Bytes[WriterIndex] = (byte)((x >> 8) | 0x80); + WriterIndex += 2; + } + else if (x < 0x200000) // 110 1 1111, -,- + { + EnsureWrite(3); + Bytes[WriterIndex + 2] = (byte)x; + Bytes[WriterIndex + 1] = (byte)(x >> 8); + Bytes[WriterIndex] = (byte)((x >> 16) | 0xc0); + WriterIndex += 3; + } + else if (x < 0x10000000) // 1110 1111,-,-,- + { + EnsureWrite(4); + Bytes[WriterIndex + 3] = (byte)x; + Bytes[WriterIndex + 2] = (byte)(x >> 8); + Bytes[WriterIndex + 1] = (byte)(x >> 16); + Bytes[WriterIndex] = (byte)((x >> 24) | 0xe0); + WriterIndex += 4; + } + else + { + EnsureWrite(5); + Bytes[WriterIndex] = 0xf0; + Bytes[WriterIndex + 4] = (byte)x; + Bytes[WriterIndex + 3] = (byte)(x >> 8); + Bytes[WriterIndex + 2] = (byte)(x >> 16); + Bytes[WriterIndex + 1] = (byte)(x >> 24); + WriterIndex += 5; + } + } + + public uint ReadUint() + { + /// + /// 警告! 如有修改,记得调整 TryDeserializeInplaceOctets + EnsureRead(1); + uint h = Bytes[ReaderIndex]; + if (h < 0x80) + { + ReaderIndex++; + return h; + } + else if (h < 0xc0) + { + EnsureRead(2); + uint x = ((h & 0x3f) << 8) | Bytes[ReaderIndex + 1]; + ReaderIndex += 2; + return x; + } + else if (h < 0xe0) + { + EnsureRead(3); + uint x = ((h & 0x1f) << 16) | ((uint)Bytes[ReaderIndex + 1] << 8) | Bytes[ReaderIndex + 2]; + ReaderIndex += 3; + return x; + } + else if (h < 0xf0) + { + EnsureRead(4); + uint x = ((h & 0x0f) << 24) | ((uint)Bytes[ReaderIndex + 1] << 16) | ((uint)Bytes[ReaderIndex + 2] << 8) | Bytes[ReaderIndex + 3]; + ReaderIndex += 4; + return x; + } + else + { + EnsureRead(5); + uint x = ((uint)Bytes[ReaderIndex + 1] << 24) | ((uint)(Bytes[ReaderIndex + 2] << 16)) | ((uint)Bytes[ReaderIndex + 3] << 8) | Bytes[ReaderIndex + 4]; + ReaderIndex += 5; + return x; + } + } + + public unsafe void WriteUint_Unsafe(uint x) + { + // 0 111 1111 + if (x < 0x80) + { + EnsureWrite(1); + Bytes[WriterIndex++] = (byte)(x << 1); + } + else if (x < 0x4000) // 10 11 1111, - + { + EnsureWrite(2); + + fixed (byte* wb = &Bytes[WriterIndex]) + { + *(uint*)(wb) = (x << 2 | 0b01); + } + + WriterIndex += 2; + } + else if (x < 0x200000) // 110 1 1111, -,- + { + EnsureWrite(3); + + fixed (byte* wb = &Bytes[WriterIndex]) + { + *(uint*)(wb) = (x << 3 | 0b011); + } + + WriterIndex += 3; + } + else if (x < 0x10000000) // 1110 1111,-,-,- + { + EnsureWrite(4); + fixed (byte* wb = &Bytes[WriterIndex]) + { + *(uint*)(wb) = (x << 4 | 0b0111); + } + + WriterIndex += 4; + } + else + { + EnsureWrite(5); + fixed (byte* wb = &Bytes[WriterIndex]) + { + *(uint*)(wb) = (x << 5 | 0b01111); + } + + WriterIndex += 5; + } + } + + public unsafe uint ReadUint_Unsafe() + { + /// + /// 警告! 如有修改,记得调整 TryDeserializeInplaceOctets + EnsureRead(1); + uint h = Bytes[ReaderIndex]; + if ((h & 0b1) == 0b0) + { + ReaderIndex++; + return (h >> 1); + } + else if ((h & 0b11) == 0b01) + { + EnsureRead(2); + fixed (byte* rb = &Bytes[ReaderIndex]) + { + ReaderIndex += 2; + return (*(uint*)rb) >> 2; + } + } + else if ((h & 0b111) == 0b011) + { + EnsureRead(3); + fixed (byte* rb = &Bytes[ReaderIndex]) + { + ReaderIndex += 3; + return (*(uint*)rb) >> 3; + } + } + else if ((h & 0b1111) == 0b0111) + { + EnsureRead(4); + fixed (byte* rb = &Bytes[ReaderIndex]) + { + ReaderIndex += 4; + return (*(uint*)rb) >> 4; + } + } + else + { + EnsureRead(5); + fixed (byte* rb = &Bytes[ReaderIndex]) + { + ReaderIndex += 5; + return (*(uint*)rb) >> 5; + } + } + } + + public int ReadFint() + { + EnsureRead(4); + int x; +#if CPU_SUPPORT_MEMORY_NOT_ALIGN + unsafe + { + fixed (byte* b = &Bytes[ReaderIndex]) + { + x = *(int*)b; + } + } +#else + x = (Bytes[ReaderIndex + 3] << 24) | (Bytes[ReaderIndex + 2] << 16) | (Bytes[ReaderIndex + 1] << 8) | (Bytes[ReaderIndex]); + +#endif + ReaderIndex += 4; + return x; + } + + + public void WriteFint(int x) + { + EnsureWrite(4); +#if CPU_SUPPORT_MEMORY_NOT_ALIGN + unsafe + { + fixed (byte* b = &Bytes[WriterIndex]) + { + *(int*)b = x; + } + } +#else + Bytes[WriterIndex] = (byte)x; + Bytes[WriterIndex + 1] = (byte)(x >> 8); + Bytes[WriterIndex + 2] = (byte)(x >> 16); + Bytes[WriterIndex + 3] = (byte)(x >> 24); +#endif + WriterIndex += 4; + } + + public int ReadFint_Safe() + { + EnsureRead(4); + int x; + + x = (Bytes[ReaderIndex + 3] << 24) | (Bytes[ReaderIndex + 2] << 16) | (Bytes[ReaderIndex + 1] << 8) | (Bytes[ReaderIndex]); + + ReaderIndex += 4; + return x; + } + + + public void WriteFint_Safe(int x) + { + EnsureWrite(4); + Bytes[WriterIndex] = (byte)x; + Bytes[WriterIndex + 1] = (byte)(x >> 8); + Bytes[WriterIndex + 2] = (byte)(x >> 16); + Bytes[WriterIndex + 3] = (byte)(x >> 24); + WriterIndex += 4; + } + + public void WriteLong(long x) + { + WriteUlong((ulong)x); + } + + public long ReadLong() + { + return (long)ReadUlong(); + } + + public void WriteNumberAsLong(double x) + { + WriteLong((long)x); + } + + public double ReadLongAsNumber() + { + return ReadLong(); + } + + private void WriteUlong(ulong x) + { + // 0 111 1111 + if (x < 0x80) + { + EnsureWrite(1); + Bytes[WriterIndex++] = (byte)x; + } + else if (x < 0x4000) // 10 11 1111, - + { + EnsureWrite(2); + Bytes[WriterIndex + 1] = (byte)x; + Bytes[WriterIndex] = (byte)((x >> 8) | 0x80); + WriterIndex += 2; + } + else if (x < 0x200000) // 110 1 1111, -,- + { + EnsureWrite(3); + Bytes[WriterIndex + 2] = (byte)x; + Bytes[WriterIndex + 1] = (byte)(x >> 8); + Bytes[WriterIndex] = (byte)((x >> 16) | 0xc0); + WriterIndex += 3; + } + else if (x < 0x10000000) // 1110 1111,-,-,- + { + EnsureWrite(4); + Bytes[WriterIndex + 3] = (byte)x; + Bytes[WriterIndex + 2] = (byte)(x >> 8); + Bytes[WriterIndex + 1] = (byte)(x >> 16); + Bytes[WriterIndex] = (byte)((x >> 24) | 0xe0); + WriterIndex += 4; + } + else if (x < 0x800000000L) // 1111 0xxx,-,-,-,- + { + EnsureWrite(5); + Bytes[WriterIndex + 4] = (byte)x; + Bytes[WriterIndex + 3] = (byte)(x >> 8); + Bytes[WriterIndex + 2] = (byte)(x >> 16); + Bytes[WriterIndex + 1] = (byte)(x >> 24); + Bytes[WriterIndex] = (byte)((x >> 32) | 0xf0); + WriterIndex += 5; + } + else if (x < 0x40000000000L) // 1111 10xx, + { + EnsureWrite(6); + Bytes[WriterIndex + 5] = (byte)x; + Bytes[WriterIndex + 4] = (byte)(x >> 8); + Bytes[WriterIndex + 3] = (byte)(x >> 16); + Bytes[WriterIndex + 2] = (byte)(x >> 24); + Bytes[WriterIndex + 1] = (byte)(x >> 32); + Bytes[WriterIndex] = (byte)((x >> 40) | 0xf8); + WriterIndex += 6; + } + else if (x < 0x200000000000L) // 1111 110x, + { + EnsureWrite(7); + Bytes[WriterIndex + 6] = (byte)x; + Bytes[WriterIndex + 5] = (byte)(x >> 8); + Bytes[WriterIndex + 4] = (byte)(x >> 16); + Bytes[WriterIndex + 3] = (byte)(x >> 24); + Bytes[WriterIndex + 2] = (byte)(x >> 32); + Bytes[WriterIndex + 1] = (byte)(x >> 40); + Bytes[WriterIndex] = (byte)((x >> 48) | 0xfc); + WriterIndex += 7; + } + else if (x < 0x100000000000000L) // 1111 1110 + { + EnsureWrite(8); + Bytes[WriterIndex + 7] = (byte)x; + Bytes[WriterIndex + 6] = (byte)(x >> 8); + Bytes[WriterIndex + 5] = (byte)(x >> 16); + Bytes[WriterIndex + 4] = (byte)(x >> 24); + Bytes[WriterIndex + 3] = (byte)(x >> 32); + Bytes[WriterIndex + 2] = (byte)(x >> 40); + Bytes[WriterIndex + 1] = (byte)(x >> 48); + Bytes[WriterIndex] = 0xfe; + WriterIndex += 8; + } + else // 1111 1111 + { + EnsureWrite(9); + Bytes[WriterIndex] = 0xff; + Bytes[WriterIndex + 8] = (byte)x; + Bytes[WriterIndex + 7] = (byte)(x >> 8); + Bytes[WriterIndex + 6] = (byte)(x >> 16); + Bytes[WriterIndex + 5] = (byte)(x >> 24); + Bytes[WriterIndex + 4] = (byte)(x >> 32); + Bytes[WriterIndex + 3] = (byte)(x >> 40); + Bytes[WriterIndex + 2] = (byte)(x >> 48); + Bytes[WriterIndex + 1] = (byte)(x >> 56); + WriterIndex += 9; + } + } + + public ulong ReadUlong() + { + EnsureRead(1); + uint h = Bytes[ReaderIndex]; + if (h < 0x80) + { + ReaderIndex++; + return h; + } + else if (h < 0xc0) + { + EnsureRead(2); + uint x = ((h & 0x3f) << 8) | Bytes[ReaderIndex + 1]; + ReaderIndex += 2; + return x; + } + else if (h < 0xe0) + { + EnsureRead(3); + uint x = ((h & 0x1f) << 16) | ((uint)Bytes[ReaderIndex + 1] << 8) | Bytes[ReaderIndex + 2]; + ReaderIndex += 3; + return x; + } + else if (h < 0xf0) + { + EnsureRead(4); + uint x = ((h & 0x0f) << 24) | ((uint)Bytes[ReaderIndex + 1] << 16) | ((uint)Bytes[ReaderIndex + 2] << 8) | Bytes[ReaderIndex + 3]; + ReaderIndex += 4; + return x; + } + else if (h < 0xf8) + { + EnsureRead(5); + uint xl = ((uint)Bytes[ReaderIndex + 1] << 24) | ((uint)(Bytes[ReaderIndex + 2] << 16)) | ((uint)Bytes[ReaderIndex + 3] << 8) | (Bytes[ReaderIndex + 4]); + uint xh = h & 0x07; + ReaderIndex += 5; + return ((ulong)xh << 32) | xl; + } + else if (h < 0xfc) + { + EnsureRead(6); + uint xl = ((uint)Bytes[ReaderIndex + 2] << 24) | ((uint)(Bytes[ReaderIndex + 3] << 16)) | ((uint)Bytes[ReaderIndex + 4] << 8) | (Bytes[ReaderIndex + 5]); + uint xh = ((h & 0x03) << 8) | Bytes[ReaderIndex + 1]; + ReaderIndex += 6; + return ((ulong)xh << 32) | xl; + } + else if (h < 0xfe) + { + EnsureRead(7); + uint xl = ((uint)Bytes[ReaderIndex + 3] << 24) | ((uint)(Bytes[ReaderIndex + 4] << 16)) | ((uint)Bytes[ReaderIndex + 5] << 8) | (Bytes[ReaderIndex + 6]); + uint xh = ((h & 0x01) << 16) | ((uint)Bytes[ReaderIndex + 1] << 8) | Bytes[ReaderIndex + 2]; + ReaderIndex += 7; + return ((ulong)xh << 32) | xl; + } + else if (h < 0xff) + { + EnsureRead(8); + uint xl = ((uint)Bytes[ReaderIndex + 4] << 24) | ((uint)(Bytes[ReaderIndex + 5] << 16)) | ((uint)Bytes[ReaderIndex + 6] << 8) | (Bytes[ReaderIndex + 7]); + uint xh = /*((h & 0x01) << 24) |*/ ((uint)Bytes[ReaderIndex + 1] << 16) | ((uint)Bytes[ReaderIndex + 2] << 8) | Bytes[ReaderIndex + 3]; + ReaderIndex += 8; + return ((ulong)xh << 32) | xl; + } + else + { + EnsureRead(9); + uint xl = ((uint)Bytes[ReaderIndex + 5] << 24) | ((uint)(Bytes[ReaderIndex + 6] << 16)) | ((uint)Bytes[ReaderIndex + 7] << 8) | (Bytes[ReaderIndex + 8]); + uint xh = ((uint)Bytes[ReaderIndex + 1] << 24) | ((uint)Bytes[ReaderIndex + 2] << 16) | ((uint)Bytes[ReaderIndex + 3] << 8) | Bytes[ReaderIndex + 4]; + ReaderIndex += 9; + return ((ulong)xh << 32) | xl; + } + } + + + public void WriteFlong(long x) + { + EnsureWrite(8); +#if CPU_SUPPORT_MEMORY_NOT_ALIGN + unsafe + { + fixed (byte* b = &Bytes[WriterIndex]) + { + *(long*)b = x; + } + } +#else + + Bytes[WriterIndex] = (byte)x; + Bytes[WriterIndex + 1] = (byte)(x >> 8); + Bytes[WriterIndex + 2] = (byte)(x >> 16); + Bytes[WriterIndex + 3] = (byte)(x >> 24); + Bytes[WriterIndex + 4] = (byte)(x >> 32); + Bytes[WriterIndex + 5] = (byte)(x >> 40); + Bytes[WriterIndex + 6] = (byte)(x >> 48); + Bytes[WriterIndex + 7] = (byte)(x >> 56); +#endif + WriterIndex += 8; + } + + public long ReadFlong() + { + EnsureRead(8); + long x; +#if CPU_SUPPORT_MEMORY_NOT_ALIGN + unsafe + { + fixed (byte* b = &Bytes[ReaderIndex]) + { + x = *(long*)b; + } + } +#else + int xl = (Bytes[ReaderIndex + 3] << 24) | ((Bytes[ReaderIndex + 2] << 16)) | (Bytes[ReaderIndex + 1] << 8) | (Bytes[ReaderIndex]); + int xh = (Bytes[ReaderIndex + 7] << 24) | (Bytes[ReaderIndex + 6] << 16) | (Bytes[ReaderIndex + 5] << 8) | Bytes[ReaderIndex + 4]; + x = ((long)xh << 32) | (long)xl; +#endif + ReaderIndex += 8; + return x; + } + + private static unsafe void Copy8(byte* dst, byte* src) + { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + dst[4] = src[4]; + dst[5] = src[5]; + dst[6] = src[6]; + dst[7] = src[7]; + } + + private static unsafe void Copy4(byte* dst, byte* src) + { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + } + + + //const bool isLittleEndian = true; + public void WriteFloat(float x) + { + EnsureWrite(4); + unsafe + { + fixed (byte* b = &Bytes[WriterIndex]) + { +#if !CPU_SUPPORT_MEMORY_NOT_ALIGN + if ((long)b % 4 == 0) + { + *(float*)b = x; + } + else + { + Copy4(b, (byte*)&x); + } +#else + *(float*)b = x; +#endif + } + } + + //if (!BitConverter.IsLittleEndian) + //{ + // Array.Reverse(data, endPos, 4); + //} + WriterIndex += 4; + } + + public float ReadFloat() + { + EnsureRead(4); + //if (!BitConverter.IsLittleEndian) + //{ + // Array.Reverse(data, beginPos, 4); + //} + float x; + unsafe + { + fixed (byte* b = &Bytes[ReaderIndex]) + { +#if !CPU_SUPPORT_MEMORY_NOT_ALIGN + if ((long)b % 4 == 0) + { + x = *(float*)b; + } + else + { + *((int*)&x) = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24); + } +#else + x = *(float*)b; +#endif + } + } + + ReaderIndex += 4; + return x; + } + + public void WriteDouble(double x) + { + EnsureWrite(8); + unsafe + { + fixed (byte* b = &Bytes[WriterIndex]) + { +#if !CPU_SUPPORT_MEMORY_NOT_ALIGN + if ((long)b % 8 == 0) + { + *(double*)b = x; + } + else + { + Copy8(b, (byte*)&x); + } +#else + *(double*)b = x; +#endif + } + //if (!BitConverter.IsLittleEndian) + //{ + // Array.Reverse(data, endPos, 8); + //} + } + + WriterIndex += 8; + } + + public double ReadDouble() + { + EnsureRead(8); + //if (!BitConverter.IsLittleEndian) + //{ + // Array.Reverse(data, beginPos, 8); + //} + double x; + unsafe + { + fixed (byte* b = &Bytes[ReaderIndex]) + { +#if !CPU_SUPPORT_MEMORY_NOT_ALIGN + if ((long)b % 8 == 0) + { + x = *(double*)b; + } + else + { + int low = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24); + int high = (b[4]) | (b[5] << 8) | (b[6] << 16) | (b[7] << 24); + *((long*)&x) = ((long)high << 32) | (uint)low; + } +#else + x = *(double*)b; +#endif + } + } + + ReaderIndex += 8; + return x; + } + + public void WriteSize(int n) + { + WriteUint((uint)n); + } + + public int ReadSize() + { + return (int)ReadUint(); + } + + // marshal int + // n -> (n << 1) ^ (n >> 31) + // Read + // (x >>> 1) ^ ((x << 31) >> 31) + // (x >>> 1) ^ -(n&1) + public void WriteSint(int x) + { + WriteUint(((uint)x << 1) ^ ((uint)x >> 31)); + } + + public int ReadSint() + { + uint x = ReadUint(); + return (int)((x >> 1) ^ ((x & 1) << 31)); + } + + + // marshal long + // n -> (n << 1) ^ (n >> 63) + // Read + // (x >>> 1) ^((x << 63) >> 63) + // (x >>> 1) ^ -(n&1L) + public void WriteSlong(long x) + { + WriteUlong(((ulong)x << 1) ^ ((ulong)x >> 63)); + } + + public long ReadSlong() + { + long x = ReadLong(); + return ((long)((ulong)x >> 1) ^ ((x & 1) << 63)); + } + + public void WriteString(string x) + { + var n = x != null ? Encoding.UTF8.GetByteCount(x) : 0; + WriteSize(n); + if (n > 0) + { + EnsureWrite(n); + Encoding.UTF8.GetBytes(x, 0, x.Length, Bytes, WriterIndex); + WriterIndex += n; + } + } + + // byte[], [start, end) + public static Func StringCacheFinder { get; set; } + + public string ReadString() + { + var n = ReadSize(); + if (n > 0) + { + EnsureRead(n); + string s; + + if (StringCacheFinder == null) + { + s = Encoding.UTF8.GetString(Bytes, ReaderIndex, n); + } + else + { + // 只缓存比较小的字符串 + s = StringCacheFinder(Bytes, ReaderIndex, n); + } + + ReaderIndex += n; + return s; + } + else + { + return string.Empty; + } + } + + public void WriteBytes(byte[] x) + { + var n = x != null ? x.Length : 0; + WriteSize(n); + if (n > 0) + { + EnsureWrite(n); + x.CopyTo(Bytes, WriterIndex); + WriterIndex += n; + } + } + + public byte[] ReadBytes() + { + var n = ReadSize(); + if (n > 0) + { + EnsureRead(n); + var x = new byte[n]; + Buffer.BlockCopy(Bytes, ReaderIndex, x, 0, n); + ReaderIndex += n; + return x; + } + else + { + return Array.Empty(); + } + } + + // 以下是一些特殊类型 + + public void WriteComplex(Complex x) + { + WriteDouble(x.Real); + WriteDouble(x.Imaginary); + } + + public Complex ReadComplex() + { + var x = ReadDouble(); + var y = ReadDouble(); + return new Complex(x, y); + } + + public void WriteVector2(Vector2 x) + { + WriteFloat(x.X); + WriteFloat(x.Y); + } + + public Vector2 ReadVector2() + { + float x = ReadFloat(); + float y = ReadFloat(); + return new Vector2(x, y); + } + + public void WriteVector3(Vector3 x) + { + WriteFloat(x.X); + WriteFloat(x.Y); + WriteFloat(x.Z); + } + + public Vector3 ReadVector3() + { + float x = ReadFloat(); + float y = ReadFloat(); + float z = ReadFloat(); + return new Vector3(x, y, z); + } + + public void WriteVector4(Vector4 x) + { + WriteFloat(x.X); + WriteFloat(x.Y); + WriteFloat(x.Z); + WriteFloat(x.W); + } + + public Vector4 ReadVector4() + { + float x = ReadFloat(); + float y = ReadFloat(); + float z = ReadFloat(); + float w = ReadFloat(); + return new Vector4(x, y, z, w); + } + + + public void WriteQuaternion(Quaternion x) + { + WriteFloat(x.X); + WriteFloat(x.Y); + WriteFloat(x.Z); + WriteFloat(x.W); + } + + public Quaternion ReadQuaternion() + { + float x = ReadFloat(); + float y = ReadFloat(); + float z = ReadFloat(); + float w = ReadFloat(); + return new Quaternion(x, y, z, w); + } + + + public void WriteMatrix4x4(Matrix4x4 x) + { + WriteFloat(x.M11); + WriteFloat(x.M12); + WriteFloat(x.M13); + WriteFloat(x.M14); + WriteFloat(x.M21); + WriteFloat(x.M22); + WriteFloat(x.M23); + WriteFloat(x.M24); + WriteFloat(x.M31); + WriteFloat(x.M32); + WriteFloat(x.M33); + WriteFloat(x.M34); + WriteFloat(x.M41); + WriteFloat(x.M42); + WriteFloat(x.M43); + WriteFloat(x.M44); + } + + public Matrix4x4 ReadMatrix4x4() + { + float m11 = ReadFloat(); + float m12 = ReadFloat(); + float m13 = ReadFloat(); + float m14 = ReadFloat(); + float m21 = ReadFloat(); + float m22 = ReadFloat(); + float m23 = ReadFloat(); + float m24 = ReadFloat(); + float m31 = ReadFloat(); + float m32 = ReadFloat(); + float m33 = ReadFloat(); + float m34 = ReadFloat(); + float m41 = ReadFloat(); + float m42 = ReadFloat(); + float m43 = ReadFloat(); + float m44 = ReadFloat(); + return new Matrix4x4(m11, m12, m13, m14, + m21, m22, m23, m24, + m31, m32, m33, m34, + m41, m42, m43, m44); + } + + internal void SkipBytes() + { + int n = ReadSize(); + EnsureRead(n); + ReaderIndex += n; + } + + + public void WriteByteBufWithSize(ByteBuf o) + { + int n = o.Size; + if (n > 0) + { + WriteSize(n); + WriteBytesWithoutSize(o.Bytes, o.ReaderIndex, n); + } + else + { + WriteByte(0); + } + } + + public void WriteByteBufWithoutSize(ByteBuf o) + { + int n = o.Size; + if (n > 0) + { + WriteBytesWithoutSize(o.Bytes, o.ReaderIndex, n); + } + } + + public bool TryReadByte(out byte x) + { + if (CanRead(1)) + { + x = Bytes[ReaderIndex++]; + return true; + } + else + { + x = 0; + return false; + } + } + + public EDeserializeError TryDeserializeInplaceByteBuf(int maxSize, ByteBuf inplaceTempBody) + { + //if (!CanRead(1)) { return EDeserializeError.NOT_ENOUGH; } + int oldReadIndex = ReaderIndex; + bool commit = false; + try + { + int n; + int h = Bytes[ReaderIndex]; + if (h < 0x80) + { + ReaderIndex++; + n = h; + } + else if (h < 0xc0) + { + if (!CanRead(2)) + { + return EDeserializeError.NOT_ENOUGH; + } + + n = ((h & 0x3f) << 8) | Bytes[ReaderIndex + 1]; + ReaderIndex += 2; + } + else if (h < 0xe0) + { + if (!CanRead(3)) + { + return EDeserializeError.NOT_ENOUGH; + } + + n = ((h & 0x1f) << 16) | (Bytes[ReaderIndex + 1] << 8) | Bytes[ReaderIndex + 2]; + ReaderIndex += 3; + } + else if (h < 0xf0) + { + if (!CanRead(4)) + { + return EDeserializeError.NOT_ENOUGH; + } + + n = ((h & 0x0f) << 24) | (Bytes[ReaderIndex + 1] << 16) | (Bytes[ReaderIndex + 2] << 8) | Bytes[ReaderIndex + 3]; + ReaderIndex += 4; + } + else + { + return EDeserializeError.EXCEED_SIZE; + } + + if (n > maxSize) + { + return EDeserializeError.EXCEED_SIZE; + } + + if (Remaining < n) + { + return EDeserializeError.NOT_ENOUGH; + } + + int inplaceReadIndex = ReaderIndex; + ReaderIndex += n; + + inplaceTempBody.Replace(Bytes, inplaceReadIndex, ReaderIndex); + commit = true; + } + finally + { + if (!commit) + { + ReaderIndex = oldReadIndex; + } + } + + return EDeserializeError.OK; + } + + public void WriteRawTag(byte b1) + { + EnsureWrite(1); + Bytes[WriterIndex++] = b1; + } + + public void WriteRawTag(byte b1, byte b2) + { + EnsureWrite(2); + Bytes[WriterIndex] = b1; + Bytes[WriterIndex + 1] = b2; + WriterIndex += 2; + } + + public void WriteRawTag(byte b1, byte b2, byte b3) + { + EnsureWrite(3); + Bytes[WriterIndex] = b1; + Bytes[WriterIndex + 1] = b2; + Bytes[WriterIndex + 2] = b3; + WriterIndex += 3; + } + + #region segment + + public void BeginWriteSegment(out int oldSize) + { + oldSize = Size; + EnsureWrite(1); + WriterIndex += 1; + } + + public void EndWriteSegment(int oldSize) + { + int startPos = ReaderIndex + oldSize; + int segmentSize = WriterIndex - startPos - 1; + + // 0 111 1111 + if (segmentSize < 0x80) + { + Bytes[startPos] = (byte)segmentSize; + } + else if (segmentSize < 0x4000) // 10 11 1111, - + { + EnsureWrite(1); + Bytes[WriterIndex] = Bytes[startPos + 1]; + Bytes[startPos + 1] = (byte)segmentSize; + + Bytes[startPos] = (byte)((segmentSize >> 8) | 0x80); + WriterIndex += 1; + } + else if (segmentSize < 0x200000) // 110 1 1111, -,- + { + EnsureWrite(2); + Bytes[WriterIndex + 1] = Bytes[startPos + 2]; + Bytes[startPos + 2] = (byte)segmentSize; + + Bytes[WriterIndex] = Bytes[startPos + 1]; + Bytes[startPos + 1] = (byte)(segmentSize >> 8); + + Bytes[startPos] = (byte)((segmentSize >> 16) | 0xc0); + WriterIndex += 2; + } + else if (segmentSize < 0x10000000) // 1110 1111,-,-,- + { + EnsureWrite(3); + Bytes[WriterIndex + 2] = Bytes[startPos + 3]; + Bytes[startPos + 3] = (byte)segmentSize; + + Bytes[WriterIndex + 1] = Bytes[startPos + 2]; + Bytes[startPos + 2] = (byte)(segmentSize >> 8); + + Bytes[WriterIndex] = Bytes[startPos + 1]; + Bytes[startPos + 1] = (byte)(segmentSize >> 16); + + Bytes[startPos] = (byte)((segmentSize >> 24) | 0xe0); + WriterIndex += 3; + } + else + { + throw new SerializationException("exceed max segment size"); + } + } + + public void ReadSegment(out int startIndex, out int segmentSize) + { + EnsureRead(1); + int h = Bytes[ReaderIndex++]; + + startIndex = ReaderIndex; + + if (h < 0x80) + { + segmentSize = h; + ReaderIndex += segmentSize; + } + else if (h < 0xc0) + { + EnsureRead(1); + segmentSize = ((h & 0x3f) << 8) | Bytes[ReaderIndex]; + int endPos = ReaderIndex + segmentSize; + Bytes[ReaderIndex] = Bytes[endPos]; + ReaderIndex += segmentSize + 1; + } + else if (h < 0xe0) + { + EnsureRead(2); + segmentSize = ((h & 0x1f) << 16) | ((int)Bytes[ReaderIndex] << 8) | Bytes[ReaderIndex + 1]; + int endPos = ReaderIndex + segmentSize; + Bytes[ReaderIndex] = Bytes[endPos]; + Bytes[ReaderIndex + 1] = Bytes[endPos + 1]; + ReaderIndex += segmentSize + 2; + } + else if (h < 0xf0) + { + EnsureRead(3); + segmentSize = ((h & 0x0f) << 24) | ((int)Bytes[ReaderIndex] << 16) | ((int)Bytes[ReaderIndex + 1] << 8) | Bytes[ReaderIndex + 2]; + int endPos = ReaderIndex + segmentSize; + Bytes[ReaderIndex] = Bytes[endPos]; + Bytes[ReaderIndex + 1] = Bytes[endPos + 1]; + Bytes[ReaderIndex + 2] = Bytes[endPos + 2]; + ReaderIndex += segmentSize + 3; + } + else + { + throw new SerializationException("exceed max size"); + } + + if (ReaderIndex > WriterIndex) + { + throw new SerializationException("segment data not enough"); + } + } + + public void ReadSegment(ByteBuf buf) + { + ReadSegment(out int startPos, out var size); + buf.Bytes = Bytes; + buf.ReaderIndex = startPos; + buf.WriterIndex = startPos + size; + } + + public void EnterSegment(out SegmentSaveState saveState) + { + ReadSegment(out int startPos, out int size); + + saveState = new SegmentSaveState(ReaderIndex, WriterIndex); + ReaderIndex = startPos; + WriterIndex = startPos + size; + } + + public void LeaveSegment(SegmentSaveState saveState) + { + ReaderIndex = saveState.ReaderIndex; + WriterIndex = saveState.WriterIndex; + } + + #endregion + + public override string ToString() + { + string[] datas = new string[WriterIndex - ReaderIndex]; + for (var i = ReaderIndex; i < WriterIndex; i++) + { + datas[i - ReaderIndex] = Bytes[i].ToString("X2"); + } + + return string.Join(".", datas); + } + + public override bool Equals(object obj) + { + return (obj is ByteBuf other) && Equals(other); + } + + public bool Equals(ByteBuf other) + { + if (other == null) + { + return false; + } + + if (Size != other.Size) + { + return false; + } + + for (int i = 0, n = Size; i < n; i++) + { + if (Bytes[ReaderIndex + i] != other.Bytes[other.ReaderIndex + i]) + { + return false; + } + } + + return true; + } + + public object Clone() + { + return new ByteBuf(CopyData()); + } + + + public static ByteBuf FromString(string value) + { + var ss = value.Split(','); + byte[] data = new byte[ss.Length]; + for (int i = 0; i < data.Length; i++) + { + data[i] = byte.Parse(ss[i]); + } + + return new ByteBuf(data); + } + + public override int GetHashCode() + { + int hash = 17; + for (int i = ReaderIndex; i < WriterIndex; i++) + { + hash = hash * 23 + Bytes[i]; + } + + return hash; + } + + public void Release() + { + _releaser?.Invoke(this); + } + +#if SUPPORT_PUERTS_ARRAYBUF + // -- add for puerts + public Puerts.ArrayBuffer ReadArrayBuffer() + { + return new Puerts.ArrayBuffer(ReadBytes()); + } + + public void WriteArrayBuffer(Puerts.ArrayBuffer bytes) + { + WriteBytes(bytes.Bytes); + } +#endif + } +} \ No newline at end of file diff --git a/Runtime/ByteBuf.cs.meta b/Runtime/ByteBuf.cs.meta new file mode 100644 index 0000000..b8a75fe --- /dev/null +++ b/Runtime/ByteBuf.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: eca47860d2cb49dd8b8fb5e9f9221605 +timeCreated: 1684724088 \ No newline at end of file diff --git a/Runtime/ITypeId.cs b/Runtime/ITypeId.cs new file mode 100644 index 0000000..82234f8 --- /dev/null +++ b/Runtime/ITypeId.cs @@ -0,0 +1,10 @@ +using UnityEngine.Scripting; + +namespace LuBan.Runtime +{ + [Preserve] + public interface ITypeId + { + int GetTypeId(); + } +} \ No newline at end of file diff --git a/Runtime/ITypeId.cs.meta b/Runtime/ITypeId.cs.meta new file mode 100644 index 0000000..a5d9db2 --- /dev/null +++ b/Runtime/ITypeId.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8fa700725576482699db273e14132680 +timeCreated: 1684724088 \ No newline at end of file diff --git a/Runtime/LuBan.Runtime.asmdef b/Runtime/LuBan.Runtime.asmdef new file mode 100644 index 0000000..70f7dbd --- /dev/null +++ b/Runtime/LuBan.Runtime.asmdef @@ -0,0 +1,15 @@ +{ + "name": "LuBan.Runtime", + "references": [ + "SimpleJSON.Runtime" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": true, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Runtime/LuBan.Runtime.asmdef.meta b/Runtime/LuBan.Runtime.asmdef.meta new file mode 100644 index 0000000..9561456 --- /dev/null +++ b/Runtime/LuBan.Runtime.asmdef.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 35f72b24bc994054b1e03b73edf578cb +timeCreated: 1684724081 \ No newline at end of file diff --git a/Runtime/LuBanCroppingHelper.cs b/Runtime/LuBanCroppingHelper.cs new file mode 100644 index 0000000..01db4bc --- /dev/null +++ b/Runtime/LuBanCroppingHelper.cs @@ -0,0 +1,23 @@ +using UnityEngine; +using UnityEngine.Scripting; + +namespace LuBan.Runtime +{ + /// + /// 防止代码运行时发生裁剪报错。将这个脚本添加到启动场景中。不会对逻辑有任何影响 + /// + [Preserve] + public class LuBanCroppingHelper : MonoBehaviour + { + void Start() + { + _ = typeof(LuBan.Runtime.BeanBase); + _ = typeof(LuBan.Runtime.EDeserializeError); + _ = typeof(LuBan.Runtime.SerializationException); + _ = typeof(LuBan.Runtime.SegmentSaveState); + _ = typeof(LuBan.Runtime.ByteBuf); + _ = typeof(LuBan.Runtime.ITypeId); + _ = typeof(LuBan.Runtime.StringUtil); + } + } +} \ No newline at end of file diff --git a/Runtime/LuBanCroppingHelper.cs.meta b/Runtime/LuBanCroppingHelper.cs.meta new file mode 100644 index 0000000..70cd5b3 --- /dev/null +++ b/Runtime/LuBanCroppingHelper.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 86fe866ea05248349bea870a0bb0d7b3 +timeCreated: 1708607173 \ No newline at end of file diff --git a/Runtime/StringUtil.cs b/Runtime/StringUtil.cs new file mode 100644 index 0000000..19a1b33 --- /dev/null +++ b/Runtime/StringUtil.cs @@ -0,0 +1,53 @@ +using System.Collections.Generic; +using System.Text; +using UnityEngine.Scripting; + +namespace LuBan.Runtime +{ + [Preserve] + public static class StringUtil + { + public static string ToStr(object o) + { + return ToStr(o, new StringBuilder()); + } + + public static string ToStr(object o, StringBuilder sb) + { + foreach (var p in o.GetType().GetFields()) + { + sb.Append($"{p.Name} = {p.GetValue(o)},"); + } + + foreach (var p in o.GetType().GetProperties()) + { + sb.Append($"{p.Name} = {p.GetValue(o)},"); + } + + return sb.ToString(); + } + + public static string ArrayToString(T[] arr) + { + return "[" + string.Join(",", arr) + "]"; + } + + public static string CollectionToString(IEnumerable arr) + { + return "[" + string.Join(",", arr) + "]"; + } + + public static string CollectionToString(IDictionary dic) + { + var sb = new StringBuilder('{'); + foreach (var e in dic) + { + sb.Append(e.Key).Append(':'); + sb.Append(e.Value).Append(','); + } + + sb.Append('}'); + return sb.ToString(); + } + } +} \ No newline at end of file diff --git a/Runtime/StringUtil.cs.meta b/Runtime/StringUtil.cs.meta new file mode 100644 index 0000000..ec06f28 --- /dev/null +++ b/Runtime/StringUtil.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: bc1758ffb2834e7da0f2759a4b6614cf +timeCreated: 1684724088 \ No newline at end of file diff --git a/Runtime/link.xml b/Runtime/link.xml new file mode 100644 index 0000000..196b22b --- /dev/null +++ b/Runtime/link.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/Runtime/link.xml.meta b/Runtime/link.xml.meta new file mode 100644 index 0000000..3edc605 --- /dev/null +++ b/Runtime/link.xml.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 0b0fb94376904b4f8702b5b796ca5944 +timeCreated: 1706789252 \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..efc07e7 --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "com.alicizax.unity.focus-creative-games.luban", + "displayName": "Aliciza X LuBan Config", + "category": "AlicizaX X", + "description": "Luban Config", + "version": "2.0.0", + "unity": "2019.4", + "keywords": [ + "Game Framework X" + ], + "repository": { + "name": "com.gameframex.unity.web", + "url": "https://github.com/gameframex/com.gameframex.unity.web.git", + "type": "git" + }, + "author": { + "name": "Blank", + "email": "alianblank@outlook.com", + "url": "https://gameframex.doc.alianblank.com" + }, + "dependencies": {} +} diff --git a/package.json.meta b/package.json.meta new file mode 100644 index 0000000..c1db5c4 --- /dev/null +++ b/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 04e79f64fb26b4fc4976bb3618b5a002 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: