16 Commits

Author SHA1 Message Date
edmand46 9bda871e7c Merge remote-tracking branch 'origin/master' 2026-03-25 13:02:40 +03:00
edmand46 cf2e095fbe feat: added lua 2026-03-25 13:02:08 +03:00
edmand46 be703e4a10 chore: remove comments 2026-03-24 12:23:24 +03:00
edmand46 57f3d9e976 chore: update tests 2026-03-23 19:50:37 +03:00
edmand46 330e6bd692 chore: update README.md 2026-03-23 16:32:23 +03:00
edmand46 b4ddf5dd6e chore: added license 2026-03-23 16:30:47 +03:00
edmand46 ec840f7db2 fix: linter 2026-03-23 16:25:49 +03:00
edmand46 6f8e6bd735 fix: linter 2026-03-23 16:22:42 +03:00
edmand46 23121a4741 fix: linter 2026-03-23 16:19:17 +03:00
edmand46 14ef3cf2c5 fix: error of naming packet 2026-03-23 16:08:06 +03:00
edmand46 db2ba03a47 chore: update README.md 2026-03-23 16:05:24 +03:00
edmand46 d41cef5576 feat: added support typescript 2026-03-23 16:04:31 +03:00
edmand46 40b81de08d chore: format messages 2026-03-23 12:53:54 +03:00
edmand46 fe70aa5404 feat: added benchmarks 2026-03-23 12:52:30 +03:00
edmand46 f490b7383b chore: update readme 2026-03-23 09:53:22 +03:00
edmand46 5d6e46dc7e chore: update readme 2026-03-23 09:50:10 +03:00
69 changed files with 9695 additions and 90 deletions
+97
View File
@@ -0,0 +1,97 @@
name: Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
go-version: ['1.25', '1.26']
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
- name: Cache Go modules
uses: actions/cache@v4
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Download dependencies
run: go mod download
- name: Run unit tests
run: go test -v ./parser/... ./generator/...
- name: Run benchmarks (short)
run: go test -bench=. -benchtime=100ms -run=^$ ./benchmarks/...
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
- name: golangci-lint
uses: golangci/golangci-lint-action@v7
with:
version: latest
args: --timeout=5m
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
- name: Build arpack CLI
run: go build -v ./cmd/arpack
- name: Test code generation
run: |
go run ./cmd/arpack -in testdata/sample.go -out-go /tmp/gen-go -out-ts /tmp/gen-ts
test -f /tmp/gen-go/sample_gen.go
test -f /tmp/gen-ts/Sample.gen.ts
e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
- name: Set up .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Run E2E tests
run: go test -v ./e2e/...
+6
View File
@@ -3,6 +3,12 @@
.codex
.DS_Store
Library
Logs
Packages
Temp
UserSettings
.idea
bin
obj
+1 -6
View File
@@ -15,9 +15,4 @@ linters:
formatters:
enable:
- goimports
linters-settings:
goimports:
local-prefixes:
- gorena/server
- goimports
+10
View File
@@ -0,0 +1,10 @@
FROM golang:1.21-bookworm
RUN apt-get update && apt-get install -y --no-install-recommends \
protobuf-compiler \
flatbuffers-compiler \
&& rm -rf /var/lib/apt/lists/*
RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.36.11
WORKDIR /workspace
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 Eduard Kargin
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.
+35
View File
@@ -0,0 +1,35 @@
UNITY_ASSETS := benchmarks/unity/Assets
.PHONY: bench-image generate bench size gen-unity
IMAGE := arpack-bench
bench-image:
docker build -f Dockerfile.bench -t $(IMAGE) .
generate:
go run ./cmd/arpack -in benchmarks/arpackmsg/messages.go -out-go benchmarks/arpackmsg
protoc --go_out=. --go_opt=paths=source_relative benchmarks/proto/move.proto
generate-docker: bench-image
docker run --rm -v "$(PWD):/workspace" -w /workspace $(IMAGE) make generate
bench:
go test ./benchmarks/... -bench=. -benchmem -count=1 -run=^$$
size:
go test ./benchmarks/... -run=TestMessageSize -v
bench-docker: bench-image
docker run --rm -v "$(PWD):/workspace" -w /workspace $(IMAGE) make bench
gen-unity:
mkdir -p "$(UNITY_ASSETS)/Benchmarks"
go run ./cmd/arpack \
-in benchmarks/arpackmsg/messages.go \
-out-cs "$(UNITY_ASSETS)/Benchmarks/" \
-cs-namespace Arpack.Messages
protoc -I benchmarks/proto \
--csharp_out="$(UNITY_ASSETS)/Benchmarks/" \
benchmarks/proto/move.proto
@echo "Done. Attach BenchmarkRunner to a GameObject in SampleScene and press Play."
+134 -20
View File
@@ -4,18 +4,34 @@
# ArPack
Binary serialization code generator for Go and C#. Define messages once as Go structs — get zero-allocation `Marshal`/`Unmarshal` for Go and `unsafe` pointer-based `Serialize`/`Deserialize` for C#.
![Tests](https://github.com/edmand46/arpack/actions/workflows/tests.yml/badge.svg)
![GitHub Tag](https://img.shields.io/github/v/tag/edmand46/arpack)
![GitHub License](https://img.shields.io/github/license/edmand46/arpack)
Built for game networking where every byte and allocation matters.
Binary serialization code generator for Go, C#, TypeScript, and Lua. Define messages once as Go structs — get zero-allocation `Marshal`/`Unmarshal` for Go, `unsafe` pointer-based `Serialize`/`Deserialize` for C#, `DataView`-based serialization for TypeScript/browser, and pure Lua implementation for Defold/LuaJIT.
## Features
- **Single source of truth** — define messages in Go, generate both Go and C# code
- **Single source of truth** — define messages in Go, generate code for Go, C#, TypeScript, and Lua
- **Float quantization** — compress `float32`/`float64` to 8 or 16 bits with a `pack` struct tag
- **Boolean packing** — consecutive `bool` fields are packed into single bytes (up to 8 per byte)
- **Enums** — `type Opcode uint16` + `const` block becomes a C# `enum`
- **Enums** — `type Opcode uint16` + `const` block becomes C#/TypeScript enums
- **Nested types, fixed arrays, slices** — full support for complex message structures
- **Cross-language binary compatibility** — Go and C# produce identical wire formats
- **Cross-language binary compatibility** — Go, C#, TypeScript, and Lua produce identical wire formats
- **Browser support** — TypeScript target uses native DataView API for zero-dependency serialization
## When to use
ArPack is designed for real-time multiplayer games and other latency-sensitive systems where a Go backend talks to a C# client over a binary protocol.
Typical setups:
- **[Nakama](https://heroiclabs.com/nakama/) + Unity** — define all network messages in Go, generate C# structs for Unity. Both sides share the exact same wire format with no reflection or boxing.
- **Custom Go game server + Unity** — roll your own server without pulling in a serialization framework. ArPack generates plain `Marshal`/`Unmarshal` methods with zero allocations on the hot path.
- **Any Go service + .NET client** — works anywhere you control both ends and want a compact binary protocol without Protobuf's runtime overhead or code-gen complexity.
- **Go backend + Browser/WebSocket** — generate TypeScript classes for browser-based clients. Uses native DataView API with zero dependencies.
- **Go backend + Defold/Lua** — generate Lua modules for Defold game engine. Pure Lua implementation compatible with LuaJIT.
## Installation
@@ -26,7 +42,14 @@ go install github.com/edmand46/arpack/cmd/arpack@latest
## Usage
```bash
arpack -in messages.go -out-go ./gen -out-cs ../Unity/Assets/Scripts
# Generate Go + C# + TypeScript
arpack -in messages.go -out-go ./gen -out-cs ../Unity/Assets/Scripts -out-ts ./web/src/messages
# Generate only TypeScript
arpack -in messages.go -out-ts ./web/src/messages
# Generate only Lua (for Defold)
arpack -in messages.go -out-lua ./defold/scripts/messages
```
| Flag | Description |
@@ -34,13 +57,15 @@ arpack -in messages.go -out-go ./gen -out-cs ../Unity/Assets/Scripts
| `-in` | Input Go file with struct definitions (required) |
| `-out-go` | Output directory for generated Go code |
| `-out-cs` | Output directory for generated C# code |
| `-out-ts` | Output directory for generated TypeScript code |
| `-out-lua` | Output directory for generated Lua code |
| `-cs-namespace` | C# namespace (default: `Arpack.Messages`) |
At least one of `-out-go` or `-out-cs` is required.
**Output files:**
- Go: `{name}_gen.go`
- C#: `{Name}.gen.cs`
- TypeScript: `{Name}.gen.ts`
- Lua: `{name}_gen.lua` (snake_case for Lua `require()` compatibility)
## Schema Definition
@@ -79,16 +104,19 @@ type MoveMessage struct {
### Supported Types
| Type | Wire Size |
|---|---|
| `bool` (packed) | 1 bit (up to 8 per byte) |
| `int8`, `uint8` | 1 byte |
| `int16`, `uint16` | 2 bytes |
| `int32`, `uint32`, `float32` | 4 bytes |
| `int64`, `uint64`, `float64` | 8 bytes |
| `string` | 2-byte length prefix + UTF-8 |
| `[N]T` | N × sizeof(T) |
| `[]T` | 2-byte length prefix + N × sizeof(T) |
| Type | Wire Size | Lua Support |
|---|---|---|
| `bool` (packed) | 1 bit (up to 8 per byte) | ✓ (uses BitOp library) |
| `int8`, `uint8` | 1 byte | ✓ |
| `int16`, `uint16` | 2 bytes | ✓ |
| `int32`, `uint32`, `float32` | 4 bytes | ✓ |
| `int64`, `uint64` | 8 bytes | ✗ (LuaJIT limitation) |
| `float64` | 8 bytes | ✓ |
| `string` | 2-byte length prefix + UTF-8 | ✓ |
| `[N]T` | N × sizeof(T) | ✓ |
| `[]T` | 2-byte length prefix + N × sizeof(T) | ✓ |
**Note:** `int64`/`uint64` are not supported in Lua target. LuaJIT (used by Defold) represents numbers as double-precision floats, which can only safely represent integers up to 2^53. Use `int32`/`uint32` instead.
### Float Quantization
@@ -127,6 +155,53 @@ public static unsafe int Deserialize(byte* buffer, out MoveMessage msg)
Uses unsafe pointers for zero-copy serialization. Returns bytes written/consumed.
### TypeScript
```typescript
export class MoveMessage {
position: Vector3 = new Vector3();
velocity: number[] = new Array<number>(3).fill(0);
waypoints: Vector3[] = [];
playerId: number = 0;
active: boolean = false;
visible: boolean = false;
ghost: boolean = false;
name: string = "";
serialize(view: DataView, offset: number): number
static deserialize(view: DataView, offset: number): [MoveMessage, number]
}
```
Uses native DataView API for browser-compatible serialization with zero dependencies. Returns bytes written/consumed.
**Note:** TypeScript field names are converted to camelCase (e.g., `PlayerID``playerId`).
### Lua
```lua
local messages = require("messages.messages_gen")
-- Create message
local msg = messages.new_move_message()
msg.player_id = 123
msg.active = true
-- Serialize
local data = messages.serialize_move_message(msg)
-- Deserialize
local decoded, bytes_read = messages.deserialize_move_message(data, 1)
```
Uses pure Lua with inline helper functions for byte manipulation. Compatible with LuaJIT (Defold). All identifiers use snake_case (e.g., `MoveMessage``move_message`, `PlayerID``player_id`).
**Requirements:** The generated Lua code requires the [BitOp library](https://bitop.luajit.org/) for bit manipulation. This library is included in LuaJIT (used by Defold).
**Limitations:**
- Lua target does not support `int64`/`uint64` types. Use `int32`/`uint32` instead. This is because LuaJIT represents numbers as double-precision floats, which can only safely represent integers up to 2^53.
- Generated file uses snake_case naming (e.g., `messages_gen.lua`) for proper Lua `require()` resolution.
## Wire Format
- Little-endian byte order
@@ -135,12 +210,51 @@ Uses unsafe pointers for zero-copy serialization. Returns bytes written/consumed
- Booleans packed as bitfields (LSB first, up to 8 per byte)
- Quantized floats stored as `uint8` or `uint16`
## Benchmarks
### Go Results (M3 Max)
```
BenchmarkArPack_Marshal-16 382568360 9.5 ns/op 5065 MB/s 0 B/op 0 allocs/op
BenchmarkArPack_Unmarshal-16 98895892 34.6 ns/op 1388 MB/s 40 B/op 2 allocs/op
BenchmarkProto_Marshal-16 21989466 163.6 ns/op 416 MB/s 0 B/op 0 allocs/op
BenchmarkProto_Unmarshal-16 13950333 256.9 ns/op 265 MB/s 248 B/op 7 allocs/op
BenchmarkFlatBuffers_Marshal-16 16297458 221.4 ns/op 687 MB/s 0 B/op 0 allocs/op
BenchmarkFlatBuffers_Unmarshal-16 56095480 64.8 ns/op 2345 MB/s 24 B/op 1 allocs/op
```
| Format | Size |
|---|---|
| ArPack | 48 bytes |
| Protobuf | 68 bytes |
| FlatBuffers | 152 bytes |
```bash
go test ./benchmarks/... -bench=. -benchmem
```
### Unity Mono (M3 Max)
```
ArPack Serialize: 96.7 ns/op | 0 B/op
ArPack Deserialize: 205.4 ns/op | 0 B/op
Proto Serialize (alloc): 930.2 ns/op | 0 B/op
Proto Deserialize (alloc): 1621.2 ns/op | 29 B/op
Proto Serialize (reuse): 652.7 ns/op | 0 B/op
```
ArPack serialize is ~10× faster than Protobuf in Unity. Protobuf deserialize allocates on every call — a GC pressure source in hot game loops. ArPack deserialize is zero-alloc.
```bash
make gen-unity
# then attach BenchmarkRunner to any GameObject in SampleScene and press Play
```
## Running Tests
```bash
# Unit tests (parser + generator)
# Unit tests
go test ./parser/... ./generator/...
# End-to-end cross-language tests (requires dotnet SDK)
# End-to-end cross-language tests
go test ./e2e/...
```
+39
View File
@@ -0,0 +1,39 @@
package arpackmsg
type Vector3 struct {
X float32 `pack:"min=-500,max=500,bits=16"`
Y float32 `pack:"min=-500,max=500,bits=16"`
Z float32 `pack:"min=-500,max=500,bits=16"`
}
type Opcode uint16
const (
OpcodeUnknown Opcode = iota
OpcodeAuthorize
OpcodeJoinRoom
)
type MoveMessage struct {
Position Vector3
Velocity [3]float32
Waypoints []Vector3
PlayerID uint32
Active bool
Visible bool
Ghost bool
Name string
}
type SpawnMessage struct {
EntityID uint64
Position Vector3
Health int16
Tags []string
Data []uint8
}
type EnvelopeMessage struct {
Code Opcode
Counter uint8
}
+221
View File
@@ -0,0 +1,221 @@
// Code generated by arpack. DO NOT EDIT.
package arpackmsg
import (
"encoding/binary"
"errors"
"math"
)
func (m *Vector3) Marshal(buf []byte) []byte {
_qm_X := uint16((m.X - (-500)) / (500 - (-500)) * 65535)
buf = binary.LittleEndian.AppendUint16(buf, _qm_X)
_qm_Y := uint16((m.Y - (-500)) / (500 - (-500)) * 65535)
buf = binary.LittleEndian.AppendUint16(buf, _qm_Y)
_qm_Z := uint16((m.Z - (-500)) / (500 - (-500)) * 65535)
buf = binary.LittleEndian.AppendUint16(buf, _qm_Z)
return buf
}
func (m *Vector3) Unmarshal(data []byte) (int, error) {
if len(data) < 6 {
return 0, errors.New("arpack: buffer too short for Vector3")
}
offset := 0
if len(data) < offset+2 {
return 0, errors.New("arpack: buffer too short")
}
_qm_X := binary.LittleEndian.Uint16(data[offset:])
offset += 2
m.X = float32(_qm_X)/65535*(500-(-500)) + (-500)
if len(data) < offset+2 {
return 0, errors.New("arpack: buffer too short")
}
_qm_Y := binary.LittleEndian.Uint16(data[offset:])
offset += 2
m.Y = float32(_qm_Y)/65535*(500-(-500)) + (-500)
if len(data) < offset+2 {
return 0, errors.New("arpack: buffer too short")
}
_qm_Z := binary.LittleEndian.Uint16(data[offset:])
offset += 2
m.Z = float32(_qm_Z)/65535*(500-(-500)) + (-500)
return offset, nil
}
func (m *MoveMessage) Marshal(buf []byte) []byte {
buf = m.Position.Marshal(buf)
for _iVelocity := 0; _iVelocity < 3; _iVelocity++ {
buf = binary.LittleEndian.AppendUint32(buf, math.Float32bits(m.Velocity[_iVelocity]))
}
buf = binary.LittleEndian.AppendUint16(buf, uint16(len(m.Waypoints)))
for _iWaypoints := range m.Waypoints {
buf = m.Waypoints[_iWaypoints].Marshal(buf)
}
buf = binary.LittleEndian.AppendUint32(buf, m.PlayerID)
var _boolByte4 uint8
if m.Active {
_boolByte4 |= 1 << 0
}
if m.Visible {
_boolByte4 |= 1 << 1
}
if m.Ghost {
_boolByte4 |= 1 << 2
}
buf = append(buf, _boolByte4)
buf = binary.LittleEndian.AppendUint16(buf, uint16(len(m.Name)))
buf = append(buf, m.Name...)
return buf
}
func (m *MoveMessage) Unmarshal(data []byte) (int, error) {
if len(data) < 23 {
return 0, errors.New("arpack: buffer too short for MoveMessage")
}
offset := 0
_nPosition, _err := m.Position.Unmarshal(data[offset:])
if _err != nil {
return 0, _err
}
offset += _nPosition
for _iVelocity := 0; _iVelocity < 3; _iVelocity++ {
if len(data) < offset+4 {
return 0, errors.New("arpack: buffer too short")
}
m.Velocity[_iVelocity] = math.Float32frombits(binary.LittleEndian.Uint32(data[offset:]))
offset += 4
}
if len(data) < offset+2 {
return 0, errors.New("arpack: buffer too short")
}
_lenWaypoints := int(binary.LittleEndian.Uint16(data[offset:]))
offset += 2
m.Waypoints = make([]Vector3, _lenWaypoints)
for _iWaypoints := 0; _iWaypoints < _lenWaypoints; _iWaypoints++ {
_nWaypoints__iWaypoints_, _err := m.Waypoints[_iWaypoints].Unmarshal(data[offset:])
if _err != nil {
return 0, _err
}
offset += _nWaypoints__iWaypoints_
}
if len(data) < offset+4 {
return 0, errors.New("arpack: buffer too short")
}
m.PlayerID = binary.LittleEndian.Uint32(data[offset:])
offset += 4
if len(data) < offset+1 {
return 0, errors.New("arpack: buffer too short")
}
_boolByte4 := data[offset]
offset++
m.Active = _boolByte4&(1<<0) != 0
m.Visible = _boolByte4&(1<<1) != 0
m.Ghost = _boolByte4&(1<<2) != 0
if len(data) < offset+2 {
return 0, errors.New("arpack: buffer too short")
}
_slenm_Name := int(binary.LittleEndian.Uint16(data[offset:]))
offset += 2
if len(data) < offset+_slenm_Name {
return 0, errors.New("arpack: buffer too short")
}
m.Name = string(data[offset : offset+_slenm_Name])
offset += _slenm_Name
return offset, nil
}
func (m *SpawnMessage) Marshal(buf []byte) []byte {
buf = binary.LittleEndian.AppendUint64(buf, m.EntityID)
buf = m.Position.Marshal(buf)
buf = binary.LittleEndian.AppendUint16(buf, uint16(m.Health))
buf = binary.LittleEndian.AppendUint16(buf, uint16(len(m.Tags)))
for _iTags := range m.Tags {
buf = binary.LittleEndian.AppendUint16(buf, uint16(len(m.Tags[_iTags])))
buf = append(buf, m.Tags[_iTags]...)
}
buf = binary.LittleEndian.AppendUint16(buf, uint16(len(m.Data)))
for _iData := range m.Data {
buf = append(buf, m.Data[_iData])
}
return buf
}
func (m *SpawnMessage) Unmarshal(data []byte) (int, error) {
if len(data) < 16 {
return 0, errors.New("arpack: buffer too short for SpawnMessage")
}
offset := 0
if len(data) < offset+8 {
return 0, errors.New("arpack: buffer too short")
}
m.EntityID = binary.LittleEndian.Uint64(data[offset:])
offset += 8
_nPosition, _err := m.Position.Unmarshal(data[offset:])
if _err != nil {
return 0, _err
}
offset += _nPosition
if len(data) < offset+2 {
return 0, errors.New("arpack: buffer too short")
}
m.Health = int16(binary.LittleEndian.Uint16(data[offset:]))
offset += 2
if len(data) < offset+2 {
return 0, errors.New("arpack: buffer too short")
}
_lenTags := int(binary.LittleEndian.Uint16(data[offset:]))
offset += 2
m.Tags = make([]string, _lenTags)
for _iTags := 0; _iTags < _lenTags; _iTags++ {
if len(data) < offset+2 {
return 0, errors.New("arpack: buffer too short")
}
_slenm_Tags__iTags_ := int(binary.LittleEndian.Uint16(data[offset:]))
offset += 2
if len(data) < offset+_slenm_Tags__iTags_ {
return 0, errors.New("arpack: buffer too short")
}
m.Tags[_iTags] = string(data[offset : offset+_slenm_Tags__iTags_])
offset += _slenm_Tags__iTags_
}
if len(data) < offset+2 {
return 0, errors.New("arpack: buffer too short")
}
_lenData := int(binary.LittleEndian.Uint16(data[offset:]))
offset += 2
m.Data = make([]uint8, _lenData)
for _iData := 0; _iData < _lenData; _iData++ {
if len(data) < offset+1 {
return 0, errors.New("arpack: buffer too short")
}
m.Data[_iData] = data[offset]
offset += 1
}
return offset, nil
}
func (m *EnvelopeMessage) Marshal(buf []byte) []byte {
buf = binary.LittleEndian.AppendUint16(buf, uint16(m.Code))
buf = append(buf, m.Counter)
return buf
}
func (m *EnvelopeMessage) Unmarshal(data []byte) (int, error) {
if len(data) < 3 {
return 0, errors.New("arpack: buffer too short for EnvelopeMessage")
}
offset := 0
if len(data) < offset+2 {
return 0, errors.New("arpack: buffer too short")
}
m.Code = Opcode(binary.LittleEndian.Uint16(data[offset:]))
offset += 2
if len(data) < offset+1 {
return 0, errors.New("arpack: buffer too short")
}
m.Counter = data[offset]
offset += 1
return offset, nil
}
+217
View File
@@ -0,0 +1,217 @@
package bench_test
import (
"fmt"
"testing"
"github.com/edmand46/arpack/benchmarks/arpackmsg"
benchfbs "github.com/edmand46/arpack/benchmarks/flatbuffers"
benchpb "github.com/edmand46/arpack/benchmarks/proto"
flatbuffers "github.com/google/flatbuffers/go"
"google.golang.org/protobuf/proto"
)
// testMoveArpack returns a fully populated arpackmsg.MoveMessage for benchmarks.
func testMoveArpack() arpackmsg.MoveMessage {
return arpackmsg.MoveMessage{
Position: arpackmsg.Vector3{X: 100, Y: -50, Z: 0},
Velocity: [3]float32{1.5, -2.5, 0},
Waypoints: []arpackmsg.Vector3{{X: 10, Y: 20, Z: 0}, {X: -10, Y: 0, Z: 100}},
PlayerID: 999,
Active: true,
Visible: false,
Ghost: true,
Name: "PlayerOne",
}
}
// testMoveProto returns a fully populated proto MoveMessage for benchmarks.
func testMoveProto() *benchpb.MoveMessage {
return &benchpb.MoveMessage{
Position: &benchpb.Vector3{X: 100, Y: -50, Z: 0},
Velocity: []float32{1.5, -2.5, 0},
Waypoints: []*benchpb.Vector3{
{X: 10, Y: 20, Z: 0},
{X: -10, Y: 0, Z: 100},
},
PlayerId: 999,
Active: true,
Visible: false,
Ghost: true,
Name: "PlayerOne",
}
}
// testMoveFbs returns a fully populated benchfbs.MoveMsg for benchmarks.
func testMoveFbs() *benchfbs.MoveMsg {
return &benchfbs.MoveMsg{
Position: benchfbs.Vec3{X: 100, Y: -50, Z: 0},
Velocity: [3]float32{1.5, -2.5, 0},
Waypoints: []benchfbs.Vec3{{X: 10, Y: 20, Z: 0}, {X: -10, Y: 0, Z: 100}},
PlayerID: 999,
Active: true,
Visible: false,
Ghost: true,
Name: "PlayerOne",
}
}
// TestMessageSize prints the wire size for each serialization format.
func TestMessageSize(t *testing.T) {
// ArPack
apMsg := testMoveArpack()
apBuf := apMsg.Marshal(nil)
fmt.Printf("ArPack wire size: %d bytes\n", len(apBuf))
// Protobuf
pbMsg := testMoveProto()
pbBuf, err := proto.Marshal(pbMsg)
if err != nil {
t.Fatalf("proto.Marshal: %v", err)
}
fmt.Printf("Protobuf wire size: %d bytes\n", len(pbBuf))
// FlatBuffers
fbMsg := testMoveFbs()
b := flatbuffers.NewBuilder(256)
fbBuf := benchfbs.Marshal(b, fbMsg)
fmt.Printf("FlatBuf wire size: %d bytes\n", len(fbBuf))
// Sanity-check round-trips
var apOut arpackmsg.MoveMessage
if _, err := apOut.Unmarshal(apBuf); err != nil {
t.Fatalf("ArPack Unmarshal: %v", err)
}
if apOut.PlayerID != 999 || apOut.Name != "PlayerOne" {
t.Errorf("ArPack round-trip mismatch: %+v", apOut)
}
var pbOut benchpb.MoveMessage
if err := proto.Unmarshal(pbBuf, &pbOut); err != nil {
t.Fatalf("proto.Unmarshal: %v", err)
}
if pbOut.PlayerId != 999 || pbOut.Name != "PlayerOne" {
t.Errorf("Proto round-trip mismatch: PlayerId=%d Name=%s", pbOut.PlayerId, pbOut.Name)
}
var fbOut benchfbs.MoveMsg
benchfbs.Unmarshal(fbBuf, &fbOut)
if fbOut.PlayerID != 999 || fbOut.Name != "PlayerOne" {
t.Errorf("FlatBuffers round-trip mismatch: %+v", fbOut)
}
}
// --- ArPack benchmarks ---
func BenchmarkArPack_Marshal(b *testing.B) {
msg := testMoveArpack()
buf := msg.Marshal(nil)
wireSize := len(buf)
b.ReportAllocs()
b.SetBytes(int64(wireSize))
b.ResetTimer()
var out []byte
for i := 0; i < b.N; i++ {
out = msg.Marshal(out[:0])
}
_ = out
}
func BenchmarkArPack_Unmarshal(b *testing.B) {
msg := testMoveArpack()
buf := msg.Marshal(nil)
wireSize := len(buf)
b.ReportAllocs()
b.SetBytes(int64(wireSize))
b.ResetTimer()
var out arpackmsg.MoveMessage
for i := 0; i < b.N; i++ {
if _, err := out.Unmarshal(buf); err != nil {
b.Fatal(err)
}
}
}
// --- Protobuf benchmarks ---
func BenchmarkProto_Marshal(b *testing.B) {
msg := testMoveProto()
buf, err := proto.Marshal(msg)
if err != nil {
b.Fatal(err)
}
wireSize := len(buf)
b.ReportAllocs()
b.SetBytes(int64(wireSize))
b.ResetTimer()
var out []byte
for i := 0; i < b.N; i++ {
out, err = proto.MarshalOptions{}.MarshalAppend(out[:0], msg)
if err != nil {
b.Fatal(err)
}
}
_ = out
}
func BenchmarkProto_Unmarshal(b *testing.B) {
msg := testMoveProto()
buf, err := proto.Marshal(msg)
if err != nil {
b.Fatal(err)
}
wireSize := len(buf)
b.ReportAllocs()
b.SetBytes(int64(wireSize))
b.ResetTimer()
var out benchpb.MoveMessage
for i := 0; i < b.N; i++ {
out.Reset()
if err := proto.Unmarshal(buf, &out); err != nil {
b.Fatal(err)
}
}
}
// --- FlatBuffers benchmarks ---
func BenchmarkFlatBuffers_Marshal(b *testing.B) {
msg := testMoveFbs()
builder := flatbuffers.NewBuilder(256)
buf := benchfbs.Marshal(builder, msg)
wireSize := len(buf)
b.ReportAllocs()
b.SetBytes(int64(wireSize))
b.ResetTimer()
for i := 0; i < b.N; i++ {
benchfbs.Marshal(builder, msg)
}
}
func BenchmarkFlatBuffers_Unmarshal(b *testing.B) {
msg := testMoveFbs()
builder := flatbuffers.NewBuilder(256)
buf := benchfbs.Marshal(builder, msg)
wireSize := len(buf)
b.ReportAllocs()
b.SetBytes(int64(wireSize))
b.ResetTimer()
var out benchfbs.MoveMsg
for i := 0; i < b.N; i++ {
out = benchfbs.MoveMsg{}
benchfbs.Unmarshal(buf, &out)
}
_ = out
}
+174
View File
@@ -0,0 +1,174 @@
package benchfbs
import (
flatbuffers "github.com/google/flatbuffers/go"
)
// Vec3 mirrors the MoveMessage's Vector3 fields for FlatBuffers encoding.
type Vec3 struct {
X, Y, Z float32
}
// MoveMsg is the Go struct used in the FlatBuffers benchmark.
type MoveMsg struct {
Position Vec3
Velocity [3]float32
Waypoints []Vec3
PlayerID uint32
Active, Visible, Ghost bool
Name string
}
// vtable slot indices for MoveMessage fields (0-based slot -> vtable offset = 4 + 2*slot)
// slot 0 -> position (vtable offset 4)
// slot 1 -> velocity (vtable offset 6)
// slot 2 -> waypoints (vtable offset 8)
// slot 3 -> player_id (vtable offset 10)
// slot 4 -> active (vtable offset 12)
// slot 5 -> visible (vtable offset 14)
// slot 6 -> ghost (vtable offset 16)
// slot 7 -> name (vtable offset 18)
const (
slotPosition = 0
slotVelocity = 1
slotWaypoints = 2
slotPlayerID = 3
slotActive = 4
slotVisible = 5
slotGhost = 6
slotName = 7
)
// buildVec3 writes a Vec3 as a table with 3 float32 fields and returns its offset.
// Vec3 slots: x=0, y=1, z=2
func buildVec3(b *flatbuffers.Builder, v Vec3) flatbuffers.UOffsetT {
b.StartObject(3)
b.PrependFloat32Slot(0, v.X, 0)
b.PrependFloat32Slot(1, v.Y, 0)
b.PrependFloat32Slot(2, v.Z, 0)
return b.EndObject()
}
// Marshal serialises msg into a FlatBuffer using b and returns the finished bytes.
// The builder is reset before use, so callers can reuse it across calls.
func Marshal(b *flatbuffers.Builder, msg *MoveMsg) []byte {
b.Reset()
// 1. Build all variable-length data first (must be done outside object construction).
// name string
nameOff := b.CreateString(msg.Name)
// velocity vector: 3 × float32
b.StartVector(4, 3, 4)
for i := 2; i >= 0; i-- {
b.PrependFloat32(msg.Velocity[i])
}
velOff := b.EndVector(3)
// waypoints vector: repeated Vec3 tables (build each table first, collect offsets)
wpOffsets := make([]flatbuffers.UOffsetT, len(msg.Waypoints))
for i, wp := range msg.Waypoints {
wpOffsets[i] = buildVec3(b, wp)
}
b.StartVector(4, len(wpOffsets), 4)
for i := len(wpOffsets) - 1; i >= 0; i-- {
b.PrependUOffsetT(wpOffsets[i])
}
wpVecOff := b.EndVector(len(wpOffsets))
// position table
posOff := buildVec3(b, msg.Position)
// 2. Build the MoveMessage table.
b.StartObject(8)
b.PrependUOffsetTSlot(slotPosition, posOff, 0)
b.PrependUOffsetTSlot(slotVelocity, velOff, 0)
b.PrependUOffsetTSlot(slotWaypoints, wpVecOff, 0)
b.PrependUint32Slot(slotPlayerID, msg.PlayerID, 0)
b.PrependBoolSlot(slotActive, msg.Active, false)
b.PrependBoolSlot(slotVisible, msg.Visible, false)
b.PrependBoolSlot(slotGhost, msg.Ghost, false)
b.PrependUOffsetTSlot(slotName, nameOff, 0)
root := b.EndObject()
b.Finish(root)
return b.FinishedBytes()
}
// readVec3 reads a Vec3 from a table at the given absolute position in buf.
func readVec3(buf []byte, tablePos flatbuffers.UOffsetT) Vec3 {
tab := flatbuffers.Table{Bytes: buf, Pos: tablePos}
var v Vec3
if o := tab.Offset(4); o != 0 { // slot 0 -> vtable offset 4
v.X = tab.GetFloat32(tab.Pos + flatbuffers.UOffsetT(o))
}
if o := tab.Offset(6); o != 0 { // slot 1 -> vtable offset 6
v.Y = tab.GetFloat32(tab.Pos + flatbuffers.UOffsetT(o))
}
if o := tab.Offset(8); o != 0 { // slot 2 -> vtable offset 8
v.Z = tab.GetFloat32(tab.Pos + flatbuffers.UOffsetT(o))
}
return v
}
// Unmarshal reads all fields from a finished FlatBuffer into out.
func Unmarshal(buf []byte, out *MoveMsg) {
// The root offset is stored at byte 0 of the finished buffer.
rootPos := flatbuffers.GetUOffsetT(buf)
tab := flatbuffers.Table{Bytes: buf, Pos: rootPos}
// position (slot 0, vtable offset 4)
if o := tab.Offset(4); o != 0 {
absOff := tab.Pos + flatbuffers.UOffsetT(o)
posPos := tab.Indirect(absOff)
out.Position = readVec3(buf, posPos)
}
// velocity vector (slot 1, vtable offset 6)
if o := tab.Offset(6); o != 0 {
vecStart := tab.Vector(flatbuffers.UOffsetT(o))
for i := 0; i < 3; i++ {
out.Velocity[i] = flatbuffers.GetFloat32(buf[int(vecStart)+i*4:])
}
}
// waypoints vector (slot 2, vtable offset 8)
if o := tab.Offset(8); o != 0 {
n := tab.VectorLen(flatbuffers.UOffsetT(o))
out.Waypoints = make([]Vec3, n)
vecStart := tab.Vector(flatbuffers.UOffsetT(o))
for i := 0; i < n; i++ {
// Each element is an UOffsetT pointing to the table.
elemOff := vecStart + flatbuffers.UOffsetT(i*4)
tablePos := elemOff + flatbuffers.GetUOffsetT(buf[elemOff:])
out.Waypoints[i] = readVec3(buf, tablePos)
}
}
// player_id (slot 3, vtable offset 10)
if o := tab.Offset(10); o != 0 {
out.PlayerID = tab.GetUint32(tab.Pos + flatbuffers.UOffsetT(o))
}
// active (slot 4, vtable offset 12)
if o := tab.Offset(12); o != 0 {
out.Active = tab.GetBool(tab.Pos + flatbuffers.UOffsetT(o))
}
// visible (slot 5, vtable offset 14)
if o := tab.Offset(14); o != 0 {
out.Visible = tab.GetBool(tab.Pos + flatbuffers.UOffsetT(o))
}
// ghost (slot 6, vtable offset 16)
if o := tab.Offset(16); o != 0 {
out.Ghost = tab.GetBool(tab.Pos + flatbuffers.UOffsetT(o))
}
// name (slot 7, vtable offset 18)
if o := tab.Offset(18); o != 0 {
absOff := tab.Pos + flatbuffers.UOffsetT(o)
out.Name = tab.String(absOff)
}
}
+253
View File
@@ -0,0 +1,253 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.10
// protoc v6.33.0
// source: benchmarks/proto/move.proto
package proto
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type Vector3 struct {
state protoimpl.MessageState `protogen:"open.v1"`
X float32 `protobuf:"fixed32,1,opt,name=x,proto3" json:"x,omitempty"`
Y float32 `protobuf:"fixed32,2,opt,name=y,proto3" json:"y,omitempty"`
Z float32 `protobuf:"fixed32,3,opt,name=z,proto3" json:"z,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *Vector3) Reset() {
*x = Vector3{}
mi := &file_benchmarks_proto_move_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *Vector3) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Vector3) ProtoMessage() {}
func (x *Vector3) ProtoReflect() protoreflect.Message {
mi := &file_benchmarks_proto_move_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Vector3.ProtoReflect.Descriptor instead.
func (*Vector3) Descriptor() ([]byte, []int) {
return file_benchmarks_proto_move_proto_rawDescGZIP(), []int{0}
}
func (x *Vector3) GetX() float32 {
if x != nil {
return x.X
}
return 0
}
func (x *Vector3) GetY() float32 {
if x != nil {
return x.Y
}
return 0
}
func (x *Vector3) GetZ() float32 {
if x != nil {
return x.Z
}
return 0
}
type MoveMessage struct {
state protoimpl.MessageState `protogen:"open.v1"`
Position *Vector3 `protobuf:"bytes,1,opt,name=position,proto3" json:"position,omitempty"`
Velocity []float32 `protobuf:"fixed32,2,rep,packed,name=velocity,proto3" json:"velocity,omitempty"`
Waypoints []*Vector3 `protobuf:"bytes,3,rep,name=waypoints,proto3" json:"waypoints,omitempty"`
PlayerId uint32 `protobuf:"varint,4,opt,name=player_id,json=playerId,proto3" json:"player_id,omitempty"`
Active bool `protobuf:"varint,5,opt,name=active,proto3" json:"active,omitempty"`
Visible bool `protobuf:"varint,6,opt,name=visible,proto3" json:"visible,omitempty"`
Ghost bool `protobuf:"varint,7,opt,name=ghost,proto3" json:"ghost,omitempty"`
Name string `protobuf:"bytes,8,opt,name=name,proto3" json:"name,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *MoveMessage) Reset() {
*x = MoveMessage{}
mi := &file_benchmarks_proto_move_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *MoveMessage) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MoveMessage) ProtoMessage() {}
func (x *MoveMessage) ProtoReflect() protoreflect.Message {
mi := &file_benchmarks_proto_move_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use MoveMessage.ProtoReflect.Descriptor instead.
func (*MoveMessage) Descriptor() ([]byte, []int) {
return file_benchmarks_proto_move_proto_rawDescGZIP(), []int{1}
}
func (x *MoveMessage) GetPosition() *Vector3 {
if x != nil {
return x.Position
}
return nil
}
func (x *MoveMessage) GetVelocity() []float32 {
if x != nil {
return x.Velocity
}
return nil
}
func (x *MoveMessage) GetWaypoints() []*Vector3 {
if x != nil {
return x.Waypoints
}
return nil
}
func (x *MoveMessage) GetPlayerId() uint32 {
if x != nil {
return x.PlayerId
}
return 0
}
func (x *MoveMessage) GetActive() bool {
if x != nil {
return x.Active
}
return false
}
func (x *MoveMessage) GetVisible() bool {
if x != nil {
return x.Visible
}
return false
}
func (x *MoveMessage) GetGhost() bool {
if x != nil {
return x.Ghost
}
return false
}
func (x *MoveMessage) GetName() string {
if x != nil {
return x.Name
}
return ""
}
var File_benchmarks_proto_move_proto protoreflect.FileDescriptor
const file_benchmarks_proto_move_proto_rawDesc = "" +
"\n" +
"\x1bbenchmarks/proto/move.proto\x12\n" +
"benchproto\"3\n" +
"\aVector3\x12\f\n" +
"\x01x\x18\x01 \x01(\x02R\x01x\x12\f\n" +
"\x01y\x18\x02 \x01(\x02R\x01y\x12\f\n" +
"\x01z\x18\x03 \x01(\x02R\x01z\"\x86\x02\n" +
"\vMoveMessage\x12/\n" +
"\bposition\x18\x01 \x01(\v2\x13.benchproto.Vector3R\bposition\x12\x1a\n" +
"\bvelocity\x18\x02 \x03(\x02R\bvelocity\x121\n" +
"\twaypoints\x18\x03 \x03(\v2\x13.benchproto.Vector3R\twaypoints\x12\x1b\n" +
"\tplayer_id\x18\x04 \x01(\rR\bplayerId\x12\x16\n" +
"\x06active\x18\x05 \x01(\bR\x06active\x12\x18\n" +
"\avisible\x18\x06 \x01(\bR\avisible\x12\x14\n" +
"\x05ghost\x18\a \x01(\bR\x05ghost\x12\x12\n" +
"\x04name\x18\b \x01(\tR\x04nameB-Z+github.com/edmand46/arpack/benchmarks/protob\x06proto3"
var (
file_benchmarks_proto_move_proto_rawDescOnce sync.Once
file_benchmarks_proto_move_proto_rawDescData []byte
)
func file_benchmarks_proto_move_proto_rawDescGZIP() []byte {
file_benchmarks_proto_move_proto_rawDescOnce.Do(func() {
file_benchmarks_proto_move_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_benchmarks_proto_move_proto_rawDesc), len(file_benchmarks_proto_move_proto_rawDesc)))
})
return file_benchmarks_proto_move_proto_rawDescData
}
var file_benchmarks_proto_move_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_benchmarks_proto_move_proto_goTypes = []any{
(*Vector3)(nil), // 0: benchproto.Vector3
(*MoveMessage)(nil), // 1: benchproto.MoveMessage
}
var file_benchmarks_proto_move_proto_depIdxs = []int32{
0, // 0: benchproto.MoveMessage.position:type_name -> benchproto.Vector3
0, // 1: benchproto.MoveMessage.waypoints:type_name -> benchproto.Vector3
2, // [2:2] is the sub-list for method output_type
2, // [2:2] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
2, // [2:2] is the sub-list for extension extendee
0, // [0:2] is the sub-list for field type_name
}
func init() { file_benchmarks_proto_move_proto_init() }
func file_benchmarks_proto_move_proto_init() {
if File_benchmarks_proto_move_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_benchmarks_proto_move_proto_rawDesc), len(file_benchmarks_proto_move_proto_rawDesc)),
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_benchmarks_proto_move_proto_goTypes,
DependencyIndexes: file_benchmarks_proto_move_proto_depIdxs,
MessageInfos: file_benchmarks_proto_move_proto_msgTypes,
}.Build()
File_benchmarks_proto_move_proto = out.File
file_benchmarks_proto_move_proto_goTypes = nil
file_benchmarks_proto_move_proto_depIdxs = nil
}
+20
View File
@@ -0,0 +1,20 @@
syntax = "proto3";
package benchproto;
option go_package = "github.com/edmand46/arpack/benchmarks/proto";
message Vector3 {
float x = 1;
float y = 2;
float z = 3;
}
message MoveMessage {
Vector3 position = 1;
repeated float velocity = 2;
repeated Vector3 waypoints = 3;
uint32 player_id = 4;
bool active = 5;
bool visible = 6;
bool ghost = 7;
string name = 8;
}
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7b9f947cf50f547f08cabcd88b87750e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,141 @@
using System;
using System.Diagnostics;
using Google.Protobuf;
using UnityEngine;
public class BenchmarkRunner : MonoBehaviour
{
private const int N = 10_000;
private const int Warmup = 1_000;
private unsafe void Start()
{
var apMsg = new Arpack.Messages.MoveMessage
{
Position = new Arpack.Messages.Vector3 { X = 100, Y = -50, Z = 0 },
Velocity = new float[] { 1.5f, -2.5f, 0f },
Waypoints = new Arpack.Messages.Vector3[]
{
new Arpack.Messages.Vector3 { X = 10, Y = 20, Z = 0 },
new Arpack.Messages.Vector3 { X = -10, Y = 0, Z = 100 },
},
PlayerID = 999,
Active = true,
Visible = false,
Ghost = true,
Name = "PlayerOne",
};
var pbMsg = new Benchproto.MoveMessage
{
Position = new Benchproto.Vector3 { X = 100, Y = -50, Z = 0 },
PlayerId = 999,
Active = true,
Visible = false,
Ghost = true,
Name = "PlayerOne",
};
pbMsg.Velocity.AddRange(new float[] { 1.5f, -2.5f, 0f });
pbMsg.Waypoints.Add(new Benchproto.Vector3 { X = 10, Y = 20, Z = 0 });
pbMsg.Waypoints.Add(new Benchproto.Vector3 { X = -10, Y = 0, Z = 100 });
byte[] apBuf = new byte[256];
int apWireSize;
fixed (byte* ptr = apBuf) { apWireSize = apMsg.Serialize(ptr); }
byte[] apBytes = new byte[apWireSize];
Array.Copy(apBuf, apBytes, apWireSize);
byte[] pbBytes = pbMsg.ToByteArray();
int pbWireSize = pbBytes.Length;
byte[] protoOutputBuf = new byte[256];
// Warmup (JIT)
for (int i = 0; i < Warmup; i++)
{
fixed (byte* ptr = apBuf) { apMsg.Serialize(ptr); }
fixed (byte* ptr = apBytes) { Arpack.Messages.MoveMessage.Deserialize(ptr, out _); }
_ = pbMsg.ToByteArray();
_ = Benchproto.MoveMessage.Parser.ParseFrom(pbBytes);
var cos = new CodedOutputStream(protoOutputBuf);
pbMsg.WriteTo(cos);
cos.Flush();
}
Stopwatch sw;
long gcBefore, gcAfter;
// ArPack Serialize
GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();
gcBefore = GC.GetTotalMemory(false);
sw = Stopwatch.StartNew();
for (int i = 0; i < N; i++)
{
fixed (byte* ptr = apBuf) { apMsg.Serialize(ptr); }
}
sw.Stop();
gcAfter = GC.GetTotalMemory(false);
Log("ArPack Serialize ", sw, N, gcAfter - gcBefore);
// ArPack Deserialize
GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();
gcBefore = GC.GetTotalMemory(false);
sw = Stopwatch.StartNew();
for (int i = 0; i < N; i++)
{
fixed (byte* ptr = apBytes) { Arpack.Messages.MoveMessage.Deserialize(ptr, out _); }
}
sw.Stop();
gcAfter = GC.GetTotalMemory(false);
Log("ArPack Deserialize ", sw, N, gcAfter - gcBefore);
// Proto Serialize (alloc)
GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();
gcBefore = GC.GetTotalMemory(false);
sw = Stopwatch.StartNew();
byte[] pbOut = null;
for (int i = 0; i < N; i++)
{
pbOut = pbMsg.ToByteArray();
}
sw.Stop();
gcAfter = GC.GetTotalMemory(false);
Log("Proto Serialize (alloc) ", sw, N, gcAfter - gcBefore);
_ = pbOut;
// Proto Deserialize (alloc)
GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();
gcBefore = GC.GetTotalMemory(false);
sw = Stopwatch.StartNew();
for (int i = 0; i < N; i++)
{
_ = Benchproto.MoveMessage.Parser.ParseFrom(pbBytes);
}
sw.Stop();
gcAfter = GC.GetTotalMemory(false);
Log("Proto Deserialize (alloc)", sw, N, gcAfter - gcBefore);
// Proto Serialize (reuse buffer)
GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();
gcBefore = GC.GetTotalMemory(false);
sw = Stopwatch.StartNew();
for (int i = 0; i < N; i++)
{
var cos = new CodedOutputStream(protoOutputBuf);
pbMsg.WriteTo(cos);
cos.Flush();
}
sw.Stop();
gcAfter = GC.GetTotalMemory(false);
Log("Proto Serialize (reuse) ", sw, N, gcAfter - gcBefore);
UnityEngine.Debug.Log($"[Bench] Wire sizes — ArPack: {apWireSize} bytes | Protobuf: {pbWireSize} bytes");
}
private static void Log(string label, Stopwatch sw, int n, long gcDelta)
{
double nsPerOp = sw.Elapsed.TotalMilliseconds * 1_000_000.0 / n;
long bPerOp = Math.Max(0, gcDelta) / n;
UnityEngine.Debug.Log($"[Bench] {label}: {nsPerOp,8:F1} ns/op | {bPerOp,6} B/op");
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ac4456ca45dd64092a7c26b7fc6cff0f
@@ -0,0 +1,16 @@
{
"name": "Benchmarks",
"rootNamespace": "",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": true,
"overrideReferences": false,
"precompiledReferences": [
"Google.Protobuf"
],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 20a66c82a93d34a489c40c5f81b4a203
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,206 @@
// <auto-generated> arpack </auto-generated>
// Code generated by arpack. DO NOT EDIT.
#pragma warning disable CS8500
using System;
using System.Text;
namespace Arpack.Messages
{
public enum Opcode : ushort
{
Unknown = 0,
Authorize = 1,
JoinRoom = 2
}
public unsafe struct Vector3
{
public float X;
public float Y;
public float Z;
public int Serialize(byte* buffer)
{
byte* ptr = buffer;
*(ushort*)ptr = (ushort)((X - (-500f)) / (500f - (-500f)) * 65535f); ptr += 2;
*(ushort*)ptr = (ushort)((Y - (-500f)) / (500f - (-500f)) * 65535f); ptr += 2;
*(ushort*)ptr = (ushort)((Z - (-500f)) / (500f - (-500f)) * 65535f); ptr += 2;
return (int)(ptr - buffer);
}
public static int Deserialize(byte* buffer, out Vector3 msg)
{
byte* ptr = buffer;
msg = default;
msg.X = (float)(*(ushort*)ptr) / 65535f * (500f - (-500f)) + (-500f); ptr += 2;
msg.Y = (float)(*(ushort*)ptr) / 65535f * (500f - (-500f)) + (-500f); ptr += 2;
msg.Z = (float)(*(ushort*)ptr) / 65535f * (500f - (-500f)) + (-500f); ptr += 2;
return (int)(ptr - buffer);
}
}
public unsafe struct MoveMessage
{
public Vector3 Position;
public float[] Velocity;
public Vector3[] Waypoints;
public uint PlayerID;
public bool Active;
public bool Visible;
public bool Ghost;
public string Name;
public int Serialize(byte* buffer)
{
byte* ptr = buffer;
ptr += Position.Serialize(ptr);
for (int _iVelocity = 0; _iVelocity < 3; _iVelocity++)
{
*(float*)ptr = Velocity[_iVelocity]; ptr += 4;
}
*(ushort*)ptr = (ushort)(Waypoints?.Length ?? 0); ptr += 2;
if (Waypoints != null)
{
for (int _iWaypoints = 0; _iWaypoints < Waypoints.Length; _iWaypoints++)
{
ptr += Waypoints[_iWaypoints].Serialize(ptr);
}
}
*(uint*)ptr = PlayerID; ptr += 4;
byte _boolByte4 = 0;
if (Active) _boolByte4 |= (byte)(1 << 0);
if (Visible) _boolByte4 |= (byte)(1 << 1);
if (Ghost) _boolByte4 |= (byte)(1 << 2);
*ptr = _boolByte4; ptr++;
int _slenName = Name != null ? Encoding.UTF8.GetByteCount(Name) : 0;
*(ushort*)ptr = (ushort)_slenName; ptr += 2;
if (Name != null && _slenName > 0)
{
fixed (char* _charsName = Name)
{
Encoding.UTF8.GetBytes(_charsName, Name.Length, ptr, _slenName);
}
}
ptr += _slenName;
return (int)(ptr - buffer);
}
public static int Deserialize(byte* buffer, out MoveMessage msg)
{
byte* ptr = buffer;
msg = default;
ptr += Vector3.Deserialize(ptr, out msg.Position);
msg.Velocity = new float[3];
for (int _iVelocity = 0; _iVelocity < 3; _iVelocity++)
{
msg.Velocity[_iVelocity] = *(float*)ptr; ptr += 4;
}
int _lenWaypoints = *(ushort*)ptr; ptr += 2;
msg.Waypoints = new Vector3[_lenWaypoints];
for (int _iWaypoints = 0; _iWaypoints < _lenWaypoints; _iWaypoints++)
{
ptr += Vector3.Deserialize(ptr, out msg.Waypoints[_iWaypoints]);
}
msg.PlayerID = *(uint*)ptr; ptr += 4;
byte _boolByte4 = *ptr; ptr++;
msg.Active = (_boolByte4 & (1 << 0)) != 0;
msg.Visible = (_boolByte4 & (1 << 1)) != 0;
msg.Ghost = (_boolByte4 & (1 << 2)) != 0;
int _slenmsg_Name = *(ushort*)ptr; ptr += 2;
msg.Name = _slenmsg_Name > 0 ? Encoding.UTF8.GetString(ptr, _slenmsg_Name) : string.Empty;
ptr += _slenmsg_Name;
return (int)(ptr - buffer);
}
}
public unsafe struct SpawnMessage
{
public ulong EntityID;
public Vector3 Position;
public short Health;
public string[] Tags;
public byte[] Data;
public int Serialize(byte* buffer)
{
byte* ptr = buffer;
*(ulong*)ptr = EntityID; ptr += 8;
ptr += Position.Serialize(ptr);
*(short*)ptr = Health; ptr += 2;
*(ushort*)ptr = (ushort)(Tags?.Length ?? 0); ptr += 2;
if (Tags != null)
{
for (int _iTags = 0; _iTags < Tags.Length; _iTags++)
{
int _slenTags__iTags_ = Tags[_iTags] != null ? Encoding.UTF8.GetByteCount(Tags[_iTags]) : 0;
*(ushort*)ptr = (ushort)_slenTags__iTags_; ptr += 2;
if (Tags[_iTags] != null && _slenTags__iTags_ > 0)
{
fixed (char* _charsTags__iTags_ = Tags[_iTags])
{
Encoding.UTF8.GetBytes(_charsTags__iTags_, Tags[_iTags].Length, ptr, _slenTags__iTags_);
}
}
ptr += _slenTags__iTags_;
}
}
*(ushort*)ptr = (ushort)(Data?.Length ?? 0); ptr += 2;
if (Data != null)
{
for (int _iData = 0; _iData < Data.Length; _iData++)
{
*ptr = Data[_iData]; ptr += 1;
}
}
return (int)(ptr - buffer);
}
public static int Deserialize(byte* buffer, out SpawnMessage msg)
{
byte* ptr = buffer;
msg = default;
msg.EntityID = *(ulong*)ptr; ptr += 8;
ptr += Vector3.Deserialize(ptr, out msg.Position);
msg.Health = *(short*)ptr; ptr += 2;
int _lenTags = *(ushort*)ptr; ptr += 2;
msg.Tags = new string[_lenTags];
for (int _iTags = 0; _iTags < _lenTags; _iTags++)
{
int _slenmsg_Tags__iTags_ = *(ushort*)ptr; ptr += 2;
msg.Tags[_iTags] = _slenmsg_Tags__iTags_ > 0 ? Encoding.UTF8.GetString(ptr, _slenmsg_Tags__iTags_) : string.Empty;
ptr += _slenmsg_Tags__iTags_;
}
int _lenData = *(ushort*)ptr; ptr += 2;
msg.Data = new byte[_lenData];
for (int _iData = 0; _iData < _lenData; _iData++)
{
msg.Data[_iData] = *ptr; ptr += 1;
}
return (int)(ptr - buffer);
}
}
public unsafe struct EnvelopeMessage
{
public Opcode Code;
public byte Counter;
public int Serialize(byte* buffer)
{
byte* ptr = buffer;
*(ushort*)ptr = (ushort)Code; ptr += 2;
*ptr = Counter; ptr += 1;
return (int)(ptr - buffer);
}
public static int Deserialize(byte* buffer, out EnvelopeMessage msg)
{
byte* ptr = buffer;
msg = default;
msg.Code = (Opcode)(*(ushort*)ptr); ptr += 2;
msg.Counter = *ptr; ptr += 1;
return (int)(ptr - buffer);
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 9755692abdaf54daf912862821fb9fd6
+768
View File
@@ -0,0 +1,768 @@
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: move.proto
// </auto-generated>
#pragma warning disable 1591, 0612, 3021, 8981
#region Designer generated code
using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
namespace Benchproto {
/// <summary>Holder for reflection information generated from move.proto</summary>
public static partial class MoveReflection {
#region Descriptor
/// <summary>File descriptor for move.proto</summary>
public static pbr::FileDescriptor Descriptor {
get { return descriptor; }
}
private static pbr::FileDescriptor descriptor;
static MoveReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"Cgptb3ZlLnByb3RvEgpiZW5jaHByb3RvIioKB1ZlY3RvcjMSCQoBeBgBIAEo",
"AhIJCgF5GAIgASgCEgkKAXoYAyABKAIivwEKC01vdmVNZXNzYWdlEiUKCHBv",
"c2l0aW9uGAEgASgLMhMuYmVuY2hwcm90by5WZWN0b3IzEhAKCHZlbG9jaXR5",
"GAIgAygCEiYKCXdheXBvaW50cxgDIAMoCzITLmJlbmNocHJvdG8uVmVjdG9y",
"MxIRCglwbGF5ZXJfaWQYBCABKA0SDgoGYWN0aXZlGAUgASgIEg8KB3Zpc2li",
"bGUYBiABKAgSDQoFZ2hvc3QYByABKAgSDAoEbmFtZRgIIAEoCUItWitnaXRo",
"dWIuY29tL2VkbWFuZDQ2L2FycGFjay9iZW5jaG1hcmtzL3Byb3RvYgZwcm90",
"bzM="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::Benchproto.Vector3), global::Benchproto.Vector3.Parser, new[]{ "X", "Y", "Z" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Benchproto.MoveMessage), global::Benchproto.MoveMessage.Parser, new[]{ "Position", "Velocity", "Waypoints", "PlayerId", "Active", "Visible", "Ghost", "Name" }, null, null, null, null)
}));
}
#endregion
}
#region Messages
[global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")]
public sealed partial class Vector3 : pb::IMessage<Vector3>
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
, pb::IBufferMessage
#endif
{
private static readonly pb::MessageParser<Vector3> _parser = new pb::MessageParser<Vector3>(() => new Vector3());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pb::MessageParser<Vector3> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::Benchproto.MoveReflection.Descriptor.MessageTypes[0]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public Vector3() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public Vector3(Vector3 other) : this() {
x_ = other.x_;
y_ = other.y_;
z_ = other.z_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public Vector3 Clone() {
return new Vector3(this);
}
/// <summary>Field number for the "x" field.</summary>
public const int XFieldNumber = 1;
private float x_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public float X {
get { return x_; }
set {
x_ = value;
}
}
/// <summary>Field number for the "y" field.</summary>
public const int YFieldNumber = 2;
private float y_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public float Y {
get { return y_; }
set {
y_ = value;
}
}
/// <summary>Field number for the "z" field.</summary>
public const int ZFieldNumber = 3;
private float z_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public float Z {
get { return z_; }
set {
z_ = value;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
return Equals(other as Vector3);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool Equals(Vector3 other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(X, other.X)) return false;
if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(Y, other.Y)) return false;
if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(Z, other.Z)) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override int GetHashCode() {
int hash = 1;
if (X != 0F) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(X);
if (Y != 0F) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(Y);
if (Z != 0F) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(Z);
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void WriteTo(pb::CodedOutputStream output) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
output.WriteRawMessage(this);
#else
if (X != 0F) {
output.WriteRawTag(13);
output.WriteFloat(X);
}
if (Y != 0F) {
output.WriteRawTag(21);
output.WriteFloat(Y);
}
if (Z != 0F) {
output.WriteRawTag(29);
output.WriteFloat(Z);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
if (X != 0F) {
output.WriteRawTag(13);
output.WriteFloat(X);
}
if (Y != 0F) {
output.WriteRawTag(21);
output.WriteFloat(Y);
}
if (Z != 0F) {
output.WriteRawTag(29);
output.WriteFloat(Z);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
}
#endif
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int CalculateSize() {
int size = 0;
if (X != 0F) {
size += 1 + 4;
}
if (Y != 0F) {
size += 1 + 4;
}
if (Z != 0F) {
size += 1 + 4;
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(Vector3 other) {
if (other == null) {
return;
}
if (other.X != 0F) {
X = other.X;
}
if (other.Y != 0F) {
Y = other.Y;
}
if (other.Z != 0F) {
Z = other.Z;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(pb::CodedInputStream input) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
input.ReadRawMessage(this);
#else
uint tag;
while ((tag = input.ReadTag()) != 0) {
if ((tag & 7) == 4) {
// Abort on any end group tag.
return;
}
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 13: {
X = input.ReadFloat();
break;
}
case 21: {
Y = input.ReadFloat();
break;
}
case 29: {
Z = input.ReadFloat();
break;
}
}
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
if ((tag & 7) == 4) {
// Abort on any end group tag.
return;
}
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
break;
case 13: {
X = input.ReadFloat();
break;
}
case 21: {
Y = input.ReadFloat();
break;
}
case 29: {
Z = input.ReadFloat();
break;
}
}
}
}
#endif
}
[global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")]
public sealed partial class MoveMessage : pb::IMessage<MoveMessage>
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
, pb::IBufferMessage
#endif
{
private static readonly pb::MessageParser<MoveMessage> _parser = new pb::MessageParser<MoveMessage>(() => new MoveMessage());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pb::MessageParser<MoveMessage> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::Benchproto.MoveReflection.Descriptor.MessageTypes[1]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public MoveMessage() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public MoveMessage(MoveMessage other) : this() {
position_ = other.position_ != null ? other.position_.Clone() : null;
velocity_ = other.velocity_.Clone();
waypoints_ = other.waypoints_.Clone();
playerId_ = other.playerId_;
active_ = other.active_;
visible_ = other.visible_;
ghost_ = other.ghost_;
name_ = other.name_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public MoveMessage Clone() {
return new MoveMessage(this);
}
/// <summary>Field number for the "position" field.</summary>
public const int PositionFieldNumber = 1;
private global::Benchproto.Vector3 position_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public global::Benchproto.Vector3 Position {
get { return position_; }
set {
position_ = value;
}
}
/// <summary>Field number for the "velocity" field.</summary>
public const int VelocityFieldNumber = 2;
private static readonly pb::FieldCodec<float> _repeated_velocity_codec
= pb::FieldCodec.ForFloat(18);
private readonly pbc::RepeatedField<float> velocity_ = new pbc::RepeatedField<float>();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public pbc::RepeatedField<float> Velocity {
get { return velocity_; }
}
/// <summary>Field number for the "waypoints" field.</summary>
public const int WaypointsFieldNumber = 3;
private static readonly pb::FieldCodec<global::Benchproto.Vector3> _repeated_waypoints_codec
= pb::FieldCodec.ForMessage(26, global::Benchproto.Vector3.Parser);
private readonly pbc::RepeatedField<global::Benchproto.Vector3> waypoints_ = new pbc::RepeatedField<global::Benchproto.Vector3>();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public pbc::RepeatedField<global::Benchproto.Vector3> Waypoints {
get { return waypoints_; }
}
/// <summary>Field number for the "player_id" field.</summary>
public const int PlayerIdFieldNumber = 4;
private uint playerId_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public uint PlayerId {
get { return playerId_; }
set {
playerId_ = value;
}
}
/// <summary>Field number for the "active" field.</summary>
public const int ActiveFieldNumber = 5;
private bool active_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool Active {
get { return active_; }
set {
active_ = value;
}
}
/// <summary>Field number for the "visible" field.</summary>
public const int VisibleFieldNumber = 6;
private bool visible_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool Visible {
get { return visible_; }
set {
visible_ = value;
}
}
/// <summary>Field number for the "ghost" field.</summary>
public const int GhostFieldNumber = 7;
private bool ghost_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool Ghost {
get { return ghost_; }
set {
ghost_ = value;
}
}
/// <summary>Field number for the "name" field.</summary>
public const int NameFieldNumber = 8;
private string name_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public string Name {
get { return name_; }
set {
name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
return Equals(other as MoveMessage);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool Equals(MoveMessage other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (!object.Equals(Position, other.Position)) return false;
if(!velocity_.Equals(other.velocity_)) return false;
if(!waypoints_.Equals(other.waypoints_)) return false;
if (PlayerId != other.PlayerId) return false;
if (Active != other.Active) return false;
if (Visible != other.Visible) return false;
if (Ghost != other.Ghost) return false;
if (Name != other.Name) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override int GetHashCode() {
int hash = 1;
if (position_ != null) hash ^= Position.GetHashCode();
hash ^= velocity_.GetHashCode();
hash ^= waypoints_.GetHashCode();
if (PlayerId != 0) hash ^= PlayerId.GetHashCode();
if (Active != false) hash ^= Active.GetHashCode();
if (Visible != false) hash ^= Visible.GetHashCode();
if (Ghost != false) hash ^= Ghost.GetHashCode();
if (Name.Length != 0) hash ^= Name.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void WriteTo(pb::CodedOutputStream output) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
output.WriteRawMessage(this);
#else
if (position_ != null) {
output.WriteRawTag(10);
output.WriteMessage(Position);
}
velocity_.WriteTo(output, _repeated_velocity_codec);
waypoints_.WriteTo(output, _repeated_waypoints_codec);
if (PlayerId != 0) {
output.WriteRawTag(32);
output.WriteUInt32(PlayerId);
}
if (Active != false) {
output.WriteRawTag(40);
output.WriteBool(Active);
}
if (Visible != false) {
output.WriteRawTag(48);
output.WriteBool(Visible);
}
if (Ghost != false) {
output.WriteRawTag(56);
output.WriteBool(Ghost);
}
if (Name.Length != 0) {
output.WriteRawTag(66);
output.WriteString(Name);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
if (position_ != null) {
output.WriteRawTag(10);
output.WriteMessage(Position);
}
velocity_.WriteTo(ref output, _repeated_velocity_codec);
waypoints_.WriteTo(ref output, _repeated_waypoints_codec);
if (PlayerId != 0) {
output.WriteRawTag(32);
output.WriteUInt32(PlayerId);
}
if (Active != false) {
output.WriteRawTag(40);
output.WriteBool(Active);
}
if (Visible != false) {
output.WriteRawTag(48);
output.WriteBool(Visible);
}
if (Ghost != false) {
output.WriteRawTag(56);
output.WriteBool(Ghost);
}
if (Name.Length != 0) {
output.WriteRawTag(66);
output.WriteString(Name);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
}
#endif
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int CalculateSize() {
int size = 0;
if (position_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Position);
}
size += velocity_.CalculateSize(_repeated_velocity_codec);
size += waypoints_.CalculateSize(_repeated_waypoints_codec);
if (PlayerId != 0) {
size += 1 + pb::CodedOutputStream.ComputeUInt32Size(PlayerId);
}
if (Active != false) {
size += 1 + 1;
}
if (Visible != false) {
size += 1 + 1;
}
if (Ghost != false) {
size += 1 + 1;
}
if (Name.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(MoveMessage other) {
if (other == null) {
return;
}
if (other.position_ != null) {
if (position_ == null) {
Position = new global::Benchproto.Vector3();
}
Position.MergeFrom(other.Position);
}
velocity_.Add(other.velocity_);
waypoints_.Add(other.waypoints_);
if (other.PlayerId != 0) {
PlayerId = other.PlayerId;
}
if (other.Active != false) {
Active = other.Active;
}
if (other.Visible != false) {
Visible = other.Visible;
}
if (other.Ghost != false) {
Ghost = other.Ghost;
}
if (other.Name.Length != 0) {
Name = other.Name;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(pb::CodedInputStream input) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
input.ReadRawMessage(this);
#else
uint tag;
while ((tag = input.ReadTag()) != 0) {
if ((tag & 7) == 4) {
// Abort on any end group tag.
return;
}
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
if (position_ == null) {
Position = new global::Benchproto.Vector3();
}
input.ReadMessage(Position);
break;
}
case 18:
case 21: {
velocity_.AddEntriesFrom(input, _repeated_velocity_codec);
break;
}
case 26: {
waypoints_.AddEntriesFrom(input, _repeated_waypoints_codec);
break;
}
case 32: {
PlayerId = input.ReadUInt32();
break;
}
case 40: {
Active = input.ReadBool();
break;
}
case 48: {
Visible = input.ReadBool();
break;
}
case 56: {
Ghost = input.ReadBool();
break;
}
case 66: {
Name = input.ReadString();
break;
}
}
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
if ((tag & 7) == 4) {
// Abort on any end group tag.
return;
}
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
break;
case 10: {
if (position_ == null) {
Position = new global::Benchproto.Vector3();
}
input.ReadMessage(Position);
break;
}
case 18:
case 21: {
velocity_.AddEntriesFrom(ref input, _repeated_velocity_codec);
break;
}
case 26: {
waypoints_.AddEntriesFrom(ref input, _repeated_waypoints_codec);
break;
}
case 32: {
PlayerId = input.ReadUInt32();
break;
}
case 40: {
Active = input.ReadBool();
break;
}
case 48: {
Visible = input.ReadBool();
break;
}
case 56: {
Ghost = input.ReadBool();
break;
}
case 66: {
Name = input.ReadString();
break;
}
}
}
}
#endif
}
#endregion
}
#endregion Designer generated code
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c7457f233226e42568ebd6ff92de57fc
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 3590b91b4603b465dbb4216d601bff33
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 11500000, guid: 8404be70184654265930450def6a9037, type: 3}
generateWrapperCode: 0
wrapperCodePath:
wrapperClassName:
wrapperCodeNamespace:
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f4bc80e0b96da47f3bbcaed7aa3fcb27
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f7d8cfb8b4c854ef88343739cde5f7d6
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c2528068817984550af33837b73bee36
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,231 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!29 &1
OcclusionCullingSettings:
m_ObjectHideFlags: 0
serializedVersion: 2
m_OcclusionBakeSettings:
smallestOccluder: 5
smallestHole: 0.25
backfaceThreshold: 100
m_SceneGUID: 00000000000000000000000000000000
m_OcclusionCullingData: {fileID: 0}
--- !u!104 &2
RenderSettings:
m_ObjectHideFlags: 0
serializedVersion: 10
m_Fog: 0
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
m_FogMode: 3
m_FogDensity: 0.01
m_LinearFogStart: 0
m_LinearFogEnd: 300
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
m_AmbientIntensity: 1
m_AmbientMode: 3
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
m_SkyboxMaterial: {fileID: 0}
m_HaloStrength: 0.5
m_FlareStrength: 1
m_FlareFadeSpeed: 3
m_HaloTexture: {fileID: 0}
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
m_DefaultReflectionMode: 0
m_DefaultReflectionResolution: 128
m_ReflectionBounces: 1
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
m_ObjectHideFlags: 0
serializedVersion: 13
m_BakeOnSceneLoad: 0
m_GISettings:
serializedVersion: 2
m_BounceScale: 1
m_IndirectOutputScale: 1
m_AlbedoBoost: 1
m_EnvironmentLightingMode: 0
m_EnableBakedLightmaps: 0
m_EnableRealtimeLightmaps: 0
m_LightmapEditorSettings:
serializedVersion: 12
m_Resolution: 2
m_BakeResolution: 40
m_AtlasSize: 1024
m_AO: 0
m_AOMaxDistance: 1
m_CompAOExponent: 1
m_CompAOExponentDirect: 0
m_ExtractAmbientOcclusion: 0
m_Padding: 2
m_LightmapParameters: {fileID: 0}
m_LightmapsBakeMode: 1
m_TextureCompression: 1
m_ReflectionCompression: 2
m_MixedBakeMode: 2
m_BakeBackend: 0
m_PVRSampling: 1
m_PVRDirectSampleCount: 32
m_PVRSampleCount: 500
m_PVRBounces: 2
m_PVREnvironmentSampleCount: 500
m_PVREnvironmentReferencePointCount: 2048
m_PVRFilteringMode: 2
m_PVRDenoiserTypeDirect: 0
m_PVRDenoiserTypeIndirect: 0
m_PVRDenoiserTypeAO: 0
m_PVRFilterTypeDirect: 0
m_PVRFilterTypeIndirect: 0
m_PVRFilterTypeAO: 0
m_PVREnvironmentMIS: 0
m_PVRCulling: 1
m_PVRFilteringGaussRadiusDirect: 1
m_PVRFilteringGaussRadiusIndirect: 5
m_PVRFilteringGaussRadiusAO: 2
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
m_PVRFilteringAtrousPositionSigmaIndirect: 2
m_PVRFilteringAtrousPositionSigmaAO: 1
m_ExportTrainingData: 0
m_TrainingDataDestination: TrainingData
m_LightProbeSampleCountMultiplier: 4
m_LightingDataAsset: {fileID: 0}
m_LightingSettings: {fileID: 0}
--- !u!196 &4
NavMeshSettings:
serializedVersion: 2
m_ObjectHideFlags: 0
m_BuildSettings:
serializedVersion: 3
agentTypeID: 0
agentRadius: 0.5
agentHeight: 2
agentSlope: 45
agentClimb: 0.4
ledgeDropHeight: 0
maxJumpAcrossDistance: 0
minRegionArea: 2
manualCellSize: 0
cellSize: 0.16666667
manualTileSize: 0
tileSize: 256
buildHeightMesh: 0
maxJobWorkers: 0
preserveTilesOutsideBounds: 0
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &519420028
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 519420032}
- component: {fileID: 519420031}
- component: {fileID: 519420029}
- component: {fileID: 519420033}
m_Layer: 0
m_Name: Main Camera
m_TagString: MainCamera
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!81 &519420029
AudioListener:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 519420028}
m_Enabled: 1
--- !u!20 &519420031
Camera:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 519420028}
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 2
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
m_projectionMatrixMode: 1
m_GateFitMode: 2
m_FOVAxisMode: 0
m_Iso: 200
m_ShutterSpeed: 0.005
m_Aperture: 16
m_FocusDistance: 10
m_FocalLength: 50
m_BladeCount: 5
m_Curvature: {x: 2, y: 11}
m_BarrelClipping: 0.25
m_Anamorphism: 0
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
near clip plane: 0.3
far clip plane: 1000
field of view: 60
orthographic: 1
orthographic size: 5
m_Depth: -1
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingPath: -1
m_TargetTexture: {fileID: 0}
m_TargetDisplay: 0
m_TargetEye: 0
m_HDR: 1
m_AllowMSAA: 0
m_AllowDynamicResolution: 0
m_ForceIntoRT: 0
m_OcclusionCulling: 0
m_StereoConvergence: 10
m_StereoSeparation: 0.022
--- !u!4 &519420032
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 519420028}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: -10}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &519420033
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 519420028}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ac4456ca45dd64092a7c26b7fc6cff0f, type: 3}
m_Name:
m_EditorClassIdentifier: Benchmarks::BenchmarkRunner
--- !u!1660057539 &9223372036854775807
SceneRoots:
m_ObjectHideFlags: 0
m_Roots:
- {fileID: 519420032}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 2cda990e2423bbf4892e6590ba056729
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+887
View File
@@ -0,0 +1,887 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<LangVersion>9.0</LangVersion>
<_TargetFrameworkDirectories>non_empty_path_generated_by_unity.rider.package</_TargetFrameworkDirectories>
<_FullFrameworkReferenceAssemblyPaths>non_empty_path_generated_by_unity.rider.package</_FullFrameworkReferenceAssemblyPaths>
<DisableHandlePackageFileConflicts>true</DisableHandlePackageFileConflicts>
<ResolveNuGetPackages>false</ResolveNuGetPackages>
</PropertyGroup>
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>10.0.20506</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<RootNamespace></RootNamespace>
<ProjectGuid>{b6ce87c6-d606-93b9-b8b1-3b520c8d6bae}</ProjectGuid>
<ProjectTypeGuids>{E097FAD1-6243-4DAD-9C02-E9B9EFC3FFC1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<AssemblyName>Benchmarks</AssemblyName>
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<BaseDirectory>.</BaseDirectory>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>Temp\Bin\Debug\Benchmarks\</OutputPath>
<DefineConstants>UNITY_6000_3_11;UNITY_6000_3;UNITY_6000;UNITY_5_3_OR_NEWER;UNITY_5_4_OR_NEWER;UNITY_5_5_OR_NEWER;UNITY_5_6_OR_NEWER;UNITY_2017_1_OR_NEWER;UNITY_2017_2_OR_NEWER;UNITY_2017_3_OR_NEWER;UNITY_2017_4_OR_NEWER;UNITY_2018_1_OR_NEWER;UNITY_2018_2_OR_NEWER;UNITY_2018_3_OR_NEWER;UNITY_2018_4_OR_NEWER;UNITY_2019_1_OR_NEWER;UNITY_2019_2_OR_NEWER;UNITY_2019_3_OR_NEWER;UNITY_2019_4_OR_NEWER;UNITY_2020_1_OR_NEWER;UNITY_2020_2_OR_NEWER;UNITY_2020_3_OR_NEWER;UNITY_2021_1_OR_NEWER;UNITY_2021_2_OR_NEWER;UNITY_2021_3_OR_NEWER;UNITY_2022_1_OR_NEWER;UNITY_2022_2_OR_NEWER;UNITY_2022_3_OR_NEWER;UNITY_2023_1_OR_NEWER;UNITY_2023_2_OR_NEWER;UNITY_2023_3_OR_NEWER;UNITY_6000_0_OR_NEWER;UNITY_6000_1_OR_NEWER;UNITY_6000_2_OR_NEWER;UNITY_6000_3_OR_NEWER;PLATFORM_ARCH_64;UNITY_64;UNITY_INCLUDE_TESTS;ENABLE_AR;ENABLE_AUDIO;ENABLE_AUDIO_SCRIPTABLE_PIPELINE;ENABLE_CACHING;ENABLE_CLOTH;ENABLE_MICROPHONE;ENABLE_MULTIPLE_DISPLAYS;ENABLE_PHYSICS;ENABLE_TEXTURE_STREAMING;ENABLE_VIRTUALTEXTURING;ENABLE_LZMA;ENABLE_UNITYEVENTS;ENABLE_VR;ENABLE_WEBCAM;ENABLE_UNITYWEBREQUEST;ENABLE_WWW;ENABLE_CLOUD_SERVICES;ENABLE_CLOUD_SERVICES_ADS;ENABLE_CLOUD_SERVICES_USE_WEBREQUEST;ENABLE_UNITY_CONSENT;ENABLE_UNITY_CLOUD_IDENTIFIERS;ENABLE_CLOUD_SERVICES_CRASH_REPORTING;ENABLE_CLOUD_SERVICES_NATIVE_CRASH_REPORTING;ENABLE_CLOUD_SERVICES_PURCHASING;ENABLE_CLOUD_SERVICES_ANALYTICS;ENABLE_CLOUD_SERVICES_BUILD;ENABLE_EDITOR_GAME_SERVICES;ENABLE_UNITY_GAME_SERVICES_ANALYTICS_SUPPORT;ENABLE_CLOUD_LICENSE;ENABLE_EDITOR_HUB_LICENSE;ENABLE_WEBSOCKET_CLIENT;ENABLE_GENERATE_NATIVE_PLUGINS_FOR_ASSEMBLIES_API;ENABLE_DIRECTOR_AUDIO;ENABLE_DIRECTOR_TEXTURE;ENABLE_MANAGED_JOBS;ENABLE_MANAGED_TRANSFORM_JOBS;ENABLE_MANAGED_ANIMATION_JOBS;ENABLE_MANAGED_AUDIO_JOBS;ENABLE_MANAGED_UNITYTLS;INCLUDE_DYNAMIC_GI;ENABLE_SCRIPTING_GC_WBARRIERS;PLATFORM_SUPPORTS_MONO;RENDER_SOFTWARE_CURSOR;ENABLE_MARSHALLING_TESTS;ENABLE_VIDEO;ENABLE_NAVIGATION_OFFMESHLINK_TO_NAVMESHLINK;ENABLE_ACCELERATOR_CLIENT_DEBUGGING;ENABLE_ACCESSIBILITY_SCREEN_READER;TEXTCORE_1_0_OR_NEWER;EDITOR_ONLY_NAVMESH_BUILDER_DEPRECATED;PLATFORM_STANDALONE_OSX;PLATFORM_STANDALONE;UNITY_STANDALONE_OSX;UNITY_STANDALONE;ENABLE_GAMECENTER;ENABLE_RUNTIME_GI;ENABLE_MOVIES;ENABLE_NETWORK;ENABLE_CRUNCH_TEXTURE_COMPRESSION;ENABLE_CLOUD_SERVICES_ENGINE_DIAGNOSTICS;ENABLE_CLUSTER_SYNC;ENABLE_CLUSTERINPUT;ENABLE_SPATIALTRACKING;PLATFORM_HAS_CUSTOM_MUTEX;PLATFORM_UPDATES_TIME_OUTSIDE_OF_PLAYER_LOOP;PLATFORM_SUPPORTS_SPLIT_GRAPHICS_JOBS;ENABLE_MONO;NET_STANDARD_2_0;NET_STANDARD;NET_STANDARD_2_1;NETSTANDARD;NETSTANDARD2_1;ENABLE_PROFILER;DEBUG;TRACE;UNITY_ASSERTIONS;UNITY_EDITOR;UNITY_EDITOR_64;UNITY_EDITOR_OSX;ENABLE_UNITY_COLLECTIONS_CHECKS;ENABLE_BURST_AOT;UNITY_TEAM_LICENSE;ENABLE_CUSTOM_RENDER_TEXTURE;ENABLE_DIRECTOR;ENABLE_LOCALIZATION;ENABLE_SPRITES;ENABLE_TERRAIN;ENABLE_TILEMAP;ENABLE_TIMELINE;ENABLE_INPUT_SYSTEM;TEXTCORE_FONT_ENGINE_1_5_OR_NEWER;TEXTCORE_TEXT_ENGINE_1_5_OR_NEWER;TEXTCORE_FONT_ENGINE_1_6_OR_NEWER;CSHARP_7_OR_LATER;CSHARP_7_3_OR_NEWER</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoWarn>0169,0649</NoWarn>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup>
<NoConfig>true</NoConfig>
<NoStdLib>true</NoStdLib>
<AddAdditionalExplicitAssemblyReferences>false</AddAdditionalExplicitAssemblyReferences>
<ImplicitlyExpandNETStandardFacades>false</ImplicitlyExpandNETStandardFacades>
<ImplicitlyExpandDesignTimeFacades>false</ImplicitlyExpandDesignTimeFacades>
</PropertyGroup>
<ItemGroup>
<Analyzer Include="/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/BuildPipeline/Unity.SourceGenerators/Unity.SourceGenerators.dll" />
<Analyzer Include="/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/BuildPipeline/Unity.SourceGenerators/Unity.Properties.SourceGenerator.dll" />
<Analyzer Include="/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/BuildPipeline/Unity.SourceGenerators/Unity.UIToolkit.SourceGenerator.dll" />
</ItemGroup>
<ItemGroup>
<Compile Include="Assets/Benchmarks/Messages.gen.cs" />
<Compile Include="Assets/Benchmarks/BenchmarkRunner.cs" />
<Compile Include="Assets/Benchmarks/Move.cs" />
<None Include="Assets/Benchmarks/Benchmarks.asmdef" />
<Reference Include="UnityEngine">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.AIModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.AIModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.ARModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.ARModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.AccessibilityModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.AccessibilityModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.AdaptivePerformanceModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.AdaptivePerformanceModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.AndroidJNIModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.AndroidJNIModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.AnimationModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.AnimationModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.AssetBundleModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.AssetBundleModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.AudioModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.AudioModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.ClothModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.ClothModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.ClusterInputModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.ClusterInputModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.ClusterRendererModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.ClusterRendererModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.ContentLoadModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.ContentLoadModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.CoreModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.CrashReportingModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.CrashReportingModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.DSPGraphModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.DSPGraphModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.DirectorModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.DirectorModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.GIModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.GIModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.GameCenterModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.GameCenterModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.GraphicsStateCollectionSerializerModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.GraphicsStateCollectionSerializerModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.GridModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.GridModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.HierarchyCoreModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.HierarchyCoreModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.HotReloadModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.HotReloadModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.IMGUIModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.IMGUIModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.IdentifiersModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.IdentifiersModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.ImageConversionModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.ImageConversionModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.InputModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.InputModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.InputForUIModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.InputForUIModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.InputLegacyModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.InputLegacyModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.InsightsModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.InsightsModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.JSONSerializeModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.JSONSerializeModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.LocalizationModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.LocalizationModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.MarshallingModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.MarshallingModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.MultiplayerModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.MultiplayerModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.ParticleSystemModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.ParticleSystemModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.PerformanceReportingModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.PerformanceReportingModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.PhysicsModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.PhysicsModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.Physics2DModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.Physics2DModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.PhysicsBackendPhysXModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.PhysicsBackendPhysXModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.PropertiesModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.PropertiesModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.RenderAs2DModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.RenderAs2DModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.RuntimeInitializeOnLoadManagerInitializerModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.RuntimeInitializeOnLoadManagerInitializerModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.ScreenCaptureModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.ScreenCaptureModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.ShaderRuntimeModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.ShaderRuntimeModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.ShaderVariantAnalyticsModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.ShaderVariantAnalyticsModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.SharedInternalsModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.SharedInternalsModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.SpriteMaskModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.SpriteMaskModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.SpriteShapeModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.SpriteShapeModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.StreamingModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.StreamingModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.SubstanceModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.SubstanceModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.SubsystemsModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.SubsystemsModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.TLSModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.TLSModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.TerrainModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.TerrainModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.TerrainPhysicsModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.TerrainPhysicsModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.TextCoreFontEngineModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.TextCoreFontEngineModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.TextCoreTextEngineModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.TextCoreTextEngineModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.TextRenderingModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.TextRenderingModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.TilemapModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.TilemapModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UIModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.UIModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UIElementsModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.UIElementsModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UmbraModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.UmbraModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UnityAnalyticsModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.UnityAnalyticsModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UnityAnalyticsCommonModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.UnityAnalyticsCommonModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UnityConnectModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.UnityConnectModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UnityConsentModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.UnityConsentModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UnityCurlModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.UnityCurlModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UnityWebRequestModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.UnityWebRequestModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UnityWebRequestAssetBundleModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.UnityWebRequestAssetBundleModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UnityWebRequestAudioModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.UnityWebRequestAudioModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UnityWebRequestTextureModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.UnityWebRequestTextureModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UnityWebRequestWWWModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.UnityWebRequestWWWModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.VFXModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.VFXModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.VRModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.VRModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.VectorGraphicsModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.VectorGraphicsModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.VehiclesModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.VehiclesModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.VideoModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.VideoModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.VirtualTexturingModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.VirtualTexturingModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.WindModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.WindModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.XRModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEngine.XRModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.AccessibilityModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.AccessibilityModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.AdaptivePerformanceModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.AdaptivePerformanceModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.AssetComplianceModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.AssetComplianceModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.BuildProfileModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.BuildProfileModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.ClothModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.ClothModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.CoreBusinessMetricsModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.CoreBusinessMetricsModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.CoreModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.CoreModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.DeviceSimulatorModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.DeviceSimulatorModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.DiagnosticsModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.DiagnosticsModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.EditorToolbarModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.EditorToolbarModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.EmbreeModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.EmbreeModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.GIModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.GIModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.GraphViewModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.GraphViewModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.GraphicsStateCollectionSerializerModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.GraphicsStateCollectionSerializerModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.GridAndSnapModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.GridAndSnapModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.GridModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.GridModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.HierarchyModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.HierarchyModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.MediaModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.MediaModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.MultiplayerModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.MultiplayerModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.Physics2DModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.Physics2DModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.PhysicsModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.PhysicsModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.PlayModeModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.PlayModeModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.PresetsUIModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.PresetsUIModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.PropertiesModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.PropertiesModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.QuickInstallModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.QuickInstallModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.QuickSearchModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.QuickSearchModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.SafeModeModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.SafeModeModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.SceneTemplateModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.SceneTemplateModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.SceneViewModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.SceneViewModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.ShaderBuildSettingsModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.ShaderBuildSettingsModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.ShaderCompilationModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.ShaderCompilationModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.ShaderFoundryModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.ShaderFoundryModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.SketchUpModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.SketchUpModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.SpriteMaskModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.SpriteMaskModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.SpriteShapeModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.SpriteShapeModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.SubstanceModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.SubstanceModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.TerrainModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.TerrainModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.TextCoreFontEngineModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.TextCoreFontEngineModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.TextCoreTextEngineModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.TextCoreTextEngineModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.TextRenderingModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.TextRenderingModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.TilemapModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.TilemapModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.TreeModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.TreeModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.UIAutomationModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.UIAutomationModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.UIBuilderModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.UIBuilderModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.UIElementsModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.UIElementsModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.UIElementsSamplesModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.UIElementsSamplesModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.UIToolkitAuthoringModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.UIToolkitAuthoringModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.UmbraModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.UmbraModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.UnityConnectModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.UnityConnectModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.VFXModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.VFXModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.VectorGraphicsModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.VectorGraphicsModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.VideoModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.VideoModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.XRModule">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEngine/UnityEditor.XRModule.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.Graphs">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/Managed/UnityEditor.Graphs.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.OSXStandalone.Extensions">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/PlaybackEngines/MacStandaloneSupport/UnityEditor.OSXStandalone.Extensions.dll</HintPath>
</Reference>
<Reference Include="Unity.VisualScripting.YamlDotNet">
<HintPath>/Users/edmand46/GolandProjects/arpack/benchmarks/unity/Library/PackageCache/com.unity.visualscripting@eb6004dcc707/Editor/VisualScripting.Core/Dependencies/YamlDotNet/Unity.VisualScripting.YamlDotNet.dll</HintPath>
</Reference>
<Reference Include="Unity.Collections.LowLevel.ILSupport">
<HintPath>/Users/edmand46/GolandProjects/arpack/benchmarks/unity/Library/PackageCache/com.unity.collections@aea9d3bd5e19/Unity.Collections.LowLevel.ILSupport/Unity.Collections.LowLevel.ILSupport.dll</HintPath>
</Reference>
<Reference Include="nunit.framework">
<HintPath>/Users/edmand46/GolandProjects/arpack/benchmarks/unity/Library/PackageCache/com.unity.ext.nunit@d8c07649098d/net40/unity-custom/nunit.framework.dll</HintPath>
</Reference>
<Reference Include="Unity.Plastic.Antlr3.Runtime">
<HintPath>/Users/edmand46/GolandProjects/arpack/benchmarks/unity/Library/PackageCache/com.unity.collab-proxy@a5329f833fa8/Lib/Editor/Unity.Plastic.Antlr3.Runtime.dll</HintPath>
</Reference>
<Reference Include="Unity.Plastic.Newtonsoft.Json">
<HintPath>/Users/edmand46/GolandProjects/arpack/benchmarks/unity/Library/PackageCache/com.unity.collab-proxy@a5329f833fa8/Lib/Editor/Unity.Plastic.Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="log4netPlastic">
<HintPath>/Users/edmand46/GolandProjects/arpack/benchmarks/unity/Library/PackageCache/com.unity.collab-proxy@a5329f833fa8/Lib/Editor/log4netPlastic.dll</HintPath>
</Reference>
<Reference Include="Unity.VisualScripting.IonicZip">
<HintPath>/Users/edmand46/GolandProjects/arpack/benchmarks/unity/Library/PackageCache/com.unity.visualscripting@eb6004dcc707/Editor/VisualScripting.Core/Dependencies/DotNetZip/Unity.VisualScripting.IonicZip.dll</HintPath>
</Reference>
<Reference Include="System.IO.Hashing">
<HintPath>/Users/edmand46/GolandProjects/arpack/benchmarks/unity/Library/PackageCache/com.unity.collections@aea9d3bd5e19/Unity.Collections.Tests/System.IO.Hashing/System.IO.Hashing.dll</HintPath>
</Reference>
<Reference Include="unityplastic">
<HintPath>/Users/edmand46/GolandProjects/arpack/benchmarks/unity/Library/PackageCache/com.unity.collab-proxy@a5329f833fa8/Lib/Editor/unityplastic.dll</HintPath>
</Reference>
<Reference Include="Unity.VisualScripting.Antlr3.Runtime">
<HintPath>/Users/edmand46/GolandProjects/arpack/benchmarks/unity/Library/PackageCache/com.unity.visualscripting@eb6004dcc707/Runtime/VisualScripting.Flow/Dependencies/NCalc/Unity.VisualScripting.Antlr3.Runtime.dll</HintPath>
</Reference>
<Reference Include="Unity.VisualScripting.TextureAssets">
<HintPath>/Users/edmand46/GolandProjects/arpack/benchmarks/unity/Library/PackageCache/com.unity.visualscripting@eb6004dcc707/Editor/VisualScripting.Core/EditorAssetResources/Unity.VisualScripting.TextureAssets.dll</HintPath>
</Reference>
<Reference Include="Mono.Cecil">
<HintPath>/Users/edmand46/GolandProjects/arpack/benchmarks/unity/Library/PackageCache/com.unity.nuget.mono-cecil@ecb9724e46ff/Mono.Cecil.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe">
<HintPath>/Users/edmand46/GolandProjects/arpack/benchmarks/unity/Library/PackageCache/com.unity.collections@aea9d3bd5e19/Unity.Collections.Tests/System.Runtime.CompilerServices.Unsafe/System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="Google.Protobuf">
<HintPath>/Users/edmand46/GolandProjects/arpack/benchmarks/unity/Assets/Plugins/Google.Protobuf.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.iOS.Extensions.Xcode">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/PlaybackEngines/MacStandaloneSupport/UnityEditor.iOS.Extensions.Xcode.dll</HintPath>
</Reference>
<Reference Include="netstandard">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/ref/2.1.0/netstandard.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Win32.Primitives">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/Microsoft.Win32.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.AppContext">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.AppContext.dll</HintPath>
</Reference>
<Reference Include="System.Buffers">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Collections.Concurrent">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Collections.Concurrent.dll</HintPath>
</Reference>
<Reference Include="System.Collections.NonGeneric">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Collections.NonGeneric.dll</HintPath>
</Reference>
<Reference Include="System.Collections.Specialized">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Collections.Specialized.dll</HintPath>
</Reference>
<Reference Include="System.Collections">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Collections.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.EventBasedAsync">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.ComponentModel.EventBasedAsync.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.Primitives">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.ComponentModel.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.TypeConverter">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.ComponentModel.TypeConverter.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.ComponentModel.dll</HintPath>
</Reference>
<Reference Include="System.Console">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Console.dll</HintPath>
</Reference>
<Reference Include="System.Data.Common">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Data.Common.dll</HintPath>
</Reference>
<Reference Include="System.Diagnostics.Contracts">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Diagnostics.Contracts.dll</HintPath>
</Reference>
<Reference Include="System.Diagnostics.Debug">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Diagnostics.Debug.dll</HintPath>
</Reference>
<Reference Include="System.Diagnostics.FileVersionInfo">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Diagnostics.FileVersionInfo.dll</HintPath>
</Reference>
<Reference Include="System.Diagnostics.Process">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Diagnostics.Process.dll</HintPath>
</Reference>
<Reference Include="System.Diagnostics.StackTrace">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Diagnostics.StackTrace.dll</HintPath>
</Reference>
<Reference Include="System.Diagnostics.TextWriterTraceListener">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Diagnostics.TextWriterTraceListener.dll</HintPath>
</Reference>
<Reference Include="System.Diagnostics.Tools">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Diagnostics.Tools.dll</HintPath>
</Reference>
<Reference Include="System.Diagnostics.TraceSource">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Diagnostics.TraceSource.dll</HintPath>
</Reference>
<Reference Include="System.Diagnostics.Tracing">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Diagnostics.Tracing.dll</HintPath>
</Reference>
<Reference Include="System.Drawing.Primitives">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Drawing.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Dynamic.Runtime">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Dynamic.Runtime.dll</HintPath>
</Reference>
<Reference Include="System.Globalization.Calendars">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Globalization.Calendars.dll</HintPath>
</Reference>
<Reference Include="System.Globalization.Extensions">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Globalization.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Globalization">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Globalization.dll</HintPath>
</Reference>
<Reference Include="System.IO.Compression.ZipFile">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.IO.Compression.ZipFile.dll</HintPath>
</Reference>
<Reference Include="System.IO.Compression">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.IO.Compression.dll</HintPath>
</Reference>
<Reference Include="System.IO.FileSystem.DriveInfo">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.IO.FileSystem.DriveInfo.dll</HintPath>
</Reference>
<Reference Include="System.IO.FileSystem.Primitives">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.IO.FileSystem.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.IO.FileSystem.Watcher">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.IO.FileSystem.Watcher.dll</HintPath>
</Reference>
<Reference Include="System.IO.FileSystem">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.IO.FileSystem.dll</HintPath>
</Reference>
<Reference Include="System.IO.IsolatedStorage">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.IO.IsolatedStorage.dll</HintPath>
</Reference>
<Reference Include="System.IO.MemoryMappedFiles">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.IO.MemoryMappedFiles.dll</HintPath>
</Reference>
<Reference Include="System.IO.Pipes">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.IO.Pipes.dll</HintPath>
</Reference>
<Reference Include="System.IO.UnmanagedMemoryStream">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.IO.UnmanagedMemoryStream.dll</HintPath>
</Reference>
<Reference Include="System.IO">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.IO.dll</HintPath>
</Reference>
<Reference Include="System.Linq.Expressions">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Linq.Expressions.dll</HintPath>
</Reference>
<Reference Include="System.Linq.Parallel">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Linq.Parallel.dll</HintPath>
</Reference>
<Reference Include="System.Linq.Queryable">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Linq.Queryable.dll</HintPath>
</Reference>
<Reference Include="System.Linq">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Linq.dll</HintPath>
</Reference>
<Reference Include="System.Memory">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Net.Http.dll</HintPath>
</Reference>
<Reference Include="System.Net.NameResolution">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Net.NameResolution.dll</HintPath>
</Reference>
<Reference Include="System.Net.NetworkInformation">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Net.NetworkInformation.dll</HintPath>
</Reference>
<Reference Include="System.Net.Ping">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Net.Ping.dll</HintPath>
</Reference>
<Reference Include="System.Net.Primitives">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Net.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Net.Requests">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Net.Requests.dll</HintPath>
</Reference>
<Reference Include="System.Net.Security">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Net.Security.dll</HintPath>
</Reference>
<Reference Include="System.Net.Sockets">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Net.Sockets.dll</HintPath>
</Reference>
<Reference Include="System.Net.WebHeaderCollection">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Net.WebHeaderCollection.dll</HintPath>
</Reference>
<Reference Include="System.Net.WebSockets.Client">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Net.WebSockets.Client.dll</HintPath>
</Reference>
<Reference Include="System.Net.WebSockets">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Net.WebSockets.dll</HintPath>
</Reference>
<Reference Include="System.Numerics.Vectors">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.ObjectModel">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.ObjectModel.dll</HintPath>
</Reference>
<Reference Include="System.Reflection.DispatchProxy">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Reflection.DispatchProxy.dll</HintPath>
</Reference>
<Reference Include="System.Reflection.Emit.ILGeneration">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Reflection.Emit.ILGeneration.dll</HintPath>
</Reference>
<Reference Include="System.Reflection.Emit.Lightweight">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Reflection.Emit.Lightweight.dll</HintPath>
</Reference>
<Reference Include="System.Reflection.Emit">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Reflection.Emit.dll</HintPath>
</Reference>
<Reference Include="System.Reflection.Extensions">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Reflection.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Reflection.Primitives">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Reflection.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Reflection">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Reflection.dll</HintPath>
</Reference>
<Reference Include="System.Resources.Reader">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Resources.Reader.dll</HintPath>
</Reference>
<Reference Include="System.Resources.ResourceManager">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Resources.ResourceManager.dll</HintPath>
</Reference>
<Reference Include="System.Resources.Writer">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Resources.Writer.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.VisualC">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Runtime.CompilerServices.VisualC.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Extensions">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Runtime.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Handles">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Runtime.Handles.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.InteropServices.RuntimeInformation">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Runtime.InteropServices.RuntimeInformation.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.InteropServices">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Runtime.InteropServices.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Numerics">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Runtime.Numerics.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Serialization.Formatters">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Runtime.Serialization.Formatters.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Serialization.Json">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Runtime.Serialization.Json.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Serialization.Primitives">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Runtime.Serialization.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Serialization.Xml">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Runtime.Serialization.Xml.dll</HintPath>
</Reference>
<Reference Include="System.Runtime">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Runtime.dll</HintPath>
</Reference>
<Reference Include="System.Security.Claims">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Security.Claims.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Algorithms">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Security.Cryptography.Algorithms.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Csp">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Security.Cryptography.Csp.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Encoding">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Security.Cryptography.Encoding.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Primitives">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Security.Cryptography.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.X509Certificates">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Security.Cryptography.X509Certificates.dll</HintPath>
</Reference>
<Reference Include="System.Security.Principal">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Security.Principal.dll</HintPath>
</Reference>
<Reference Include="System.Security.SecureString">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Security.SecureString.dll</HintPath>
</Reference>
<Reference Include="System.Text.Encoding.Extensions">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Text.Encoding.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Text.Encoding">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Text.Encoding.dll</HintPath>
</Reference>
<Reference Include="System.Text.RegularExpressions">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Text.RegularExpressions.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Overlapped">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Threading.Overlapped.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Parallel">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Threading.Tasks.Parallel.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Threading.Tasks.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Thread">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Threading.Thread.dll</HintPath>
</Reference>
<Reference Include="System.Threading.ThreadPool">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Threading.ThreadPool.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Timer">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Threading.Timer.dll</HintPath>
</Reference>
<Reference Include="System.Threading">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Threading.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.ValueTuple.dll</HintPath>
</Reference>
<Reference Include="System.Xml.ReaderWriter">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Xml.ReaderWriter.dll</HintPath>
</Reference>
<Reference Include="System.Xml.XDocument">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Xml.XDocument.dll</HintPath>
</Reference>
<Reference Include="System.Xml.XPath.XDocument">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Xml.XPath.XDocument.dll</HintPath>
</Reference>
<Reference Include="System.Xml.XPath">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Xml.XPath.dll</HintPath>
</Reference>
<Reference Include="System.Xml.XmlDocument">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Xml.XmlDocument.dll</HintPath>
</Reference>
<Reference Include="System.Xml.XmlSerializer">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netstandard/System.Xml.XmlSerializer.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.InteropServices.WindowsRuntime">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/Extensions/2.0.0/System.Runtime.InteropServices.WindowsRuntime.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.Composition">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netfx/System.ComponentModel.Composition.dll</HintPath>
</Reference>
<Reference Include="System.Core">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netfx/System.Core.dll</HintPath>
</Reference>
<Reference Include="System.Data">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netfx/System.Data.dll</HintPath>
</Reference>
<Reference Include="System.Drawing">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netfx/System.Drawing.dll</HintPath>
</Reference>
<Reference Include="System.IO.Compression.FileSystem">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netfx/System.IO.Compression.FileSystem.dll</HintPath>
</Reference>
<Reference Include="System.Net">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netfx/System.Net.dll</HintPath>
</Reference>
<Reference Include="System.Numerics">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netfx/System.Numerics.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Serialization">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netfx/System.Runtime.Serialization.dll</HintPath>
</Reference>
<Reference Include="System.ServiceModel.Web">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netfx/System.ServiceModel.Web.dll</HintPath>
</Reference>
<Reference Include="System.Transactions">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netfx/System.Transactions.dll</HintPath>
</Reference>
<Reference Include="System.Web">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netfx/System.Web.dll</HintPath>
</Reference>
<Reference Include="System.Windows">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netfx/System.Windows.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netfx/System.Xml.Linq.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Serialization">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netfx/System.Xml.Serialization.dll</HintPath>
</Reference>
<Reference Include="System.Xml">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netfx/System.Xml.dll</HintPath>
</Reference>
<Reference Include="System">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netfx/System.dll</HintPath>
</Reference>
<Reference Include="mscorlib">
<HintPath>/Applications/Unity/Hub/Editor/6000.3.11f1/Unity.app/Contents/Resources/Scripting/NetStandard/compat/2.1.0/shims/netfx/mscorlib.dll</HintPath>
</Reference>
<Reference Include="UnityEditor.UI">
<HintPath>/Users/edmand46/GolandProjects/arpack/benchmarks/unity/Library/ScriptAssemblies/UnityEditor.UI.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UI">
<HintPath>/Users/edmand46/GolandProjects/arpack/benchmarks/unity/Library/ScriptAssemblies/UnityEngine.UI.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
@@ -0,0 +1,19 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!11 &1
AudioManager:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Volume: 1
Rolloff Scale: 1
Doppler Factor: 1
Default Speaker Mode: 2
m_SampleRate: 0
m_DSPBufferSize: 1024
m_VirtualVoiceCount: 512
m_RealVoiceCount: 32
m_SpatializerPlugin:
m_AmbisonicDecoderPlugin:
m_DisableAudio: 0
m_VirtualizeEffects: 1
m_RequestedDSPBufferSize: 0
@@ -0,0 +1,6 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!236 &1
ClusterInputManager:
m_ObjectHideFlags: 0
m_Inputs: []
@@ -0,0 +1,37 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!55 &1
PhysicsManager:
m_ObjectHideFlags: 0
serializedVersion: 13
m_Gravity: {x: 0, y: -9.81, z: 0}
m_DefaultMaterial: {fileID: 0}
m_BounceThreshold: 2
m_DefaultMaxDepenetrationVelocity: 10
m_SleepThreshold: 0.005
m_DefaultContactOffset: 0.01
m_DefaultSolverIterations: 6
m_DefaultSolverVelocityIterations: 1
m_QueriesHitBackfaces: 0
m_QueriesHitTriggers: 1
m_EnableAdaptiveForce: 0
m_ClothInterCollisionDistance: 0.1
m_ClothInterCollisionStiffness: 0.2
m_ContactsGeneration: 1
m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
m_AutoSimulation: 1
m_AutoSyncTransforms: 0
m_ReuseCollisionCallbacks: 1
m_ClothInterCollisionSettingsToggle: 0
m_ClothGravity: {x: 0, y: -9.81, z: 0}
m_ContactPairsMode: 0
m_BroadphaseType: 0
m_WorldBounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 250, y: 250, z: 250}
m_WorldSubdivisions: 8
m_FrictionType: 0
m_EnableEnhancedDeterminism: 0
m_EnableUnifiedHeightmaps: 1
m_SolverType: 0
m_DefaultMaxAngularSpeed: 50
@@ -0,0 +1,13 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1045 &1
EditorBuildSettings:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Scenes:
- enabled: 1
path: Assets/Scenes/SampleScene.unity
guid: 2cda990e2423bbf4892e6590ba056729
m_configObjects:
com.unity.input.settings.actions: {fileID: -944628639613478452, guid: 3590b91b4603b465dbb4216d601bff33, type: 3}
m_UseUCBPForAssetBundles: 0
@@ -0,0 +1,50 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!159 &1
EditorSettings:
m_ObjectHideFlags: 0
serializedVersion: 15
m_SerializationMode: 2
m_LineEndingsForNewScripts: 0
m_DefaultBehaviorMode: 1
m_PrefabRegularEnvironment: {fileID: 0}
m_PrefabUIEnvironment: {fileID: 0}
m_SpritePackerMode: 5
m_SpritePackerCacheSize: 10
m_SpritePackerPaddingPower: 1
m_Bc7TextureCompressor: 0
m_EtcTextureCompressorBehavior: 1
m_EtcTextureFastCompressor: 1
m_EtcTextureNormalCompressor: 2
m_EtcTextureBestCompressor: 4
m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;asmref;rsp
m_ProjectGenerationRootNamespace:
m_EnableTextureStreamingInEditMode: 1
m_EnableTextureStreamingInPlayMode: 1
m_EnableEditorAsyncCPUTextureLoading: 0
m_AsyncShaderCompilation: 1
m_PrefabModeAllowAutoSave: 1
m_EnterPlayModeOptionsEnabled: 1
m_EnterPlayModeOptions: 0
m_GameObjectNamingDigits: 1
m_GameObjectNamingScheme: 0
m_AssetNamingUsesSpace: 1
m_InspectorUseIMGUIDefaultInspector: 0
m_UseLegacyProbeSampleCount: 0
m_SerializeInlineMappingsOnOneLine: 1
m_DisableCookiesInLightmapper: 1
m_ShadowmaskStitching: 0
m_AssetPipelineMode: 1
m_RefreshImportMode: 0
m_CacheServerMode: 0
m_CacheServerEndpoint:
m_CacheServerNamespacePrefix: default
m_CacheServerEnableDownload: 1
m_CacheServerEnableUpload: 1
m_CacheServerEnableAuth: 0
m_CacheServerEnableTls: 0
m_CacheServerValidationMode: 2
m_CacheServerDownloadBatchSize: 128
m_EnableEnlightenBakedGI: 0
m_ReferencedClipsExactNaming: 1
m_ForceAssetUnloadAndGCOnSceneLoad: 1
@@ -0,0 +1,64 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!30 &1
GraphicsSettings:
m_ObjectHideFlags: 0
serializedVersion: 13
m_Deferred:
m_Mode: 1
m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0}
m_DeferredReflections:
m_Mode: 1
m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0}
m_ScreenSpaceShadows:
m_Mode: 1
m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0}
m_LegacyDeferred:
m_Mode: 1
m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0}
m_DepthNormals:
m_Mode: 1
m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0}
m_MotionVectors:
m_Mode: 1
m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0}
m_LightHalo:
m_Mode: 1
m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0}
m_LensFlare:
m_Mode: 1
m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0}
m_VideoShadersIncludeMode: 2
m_AlwaysIncludedShaders:
- {fileID: 7, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0}
m_PreloadedShaders: []
m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
m_CustomRenderPipeline: {fileID: 0}
m_TransparencySortMode: 0
m_TransparencySortAxis: {x: 0, y: 0, z: 1}
m_DefaultRenderingPath: 1
m_DefaultMobileRenderingPath: 1
m_TierSettings: []
m_LightmapStripping: 0
m_FogStripping: 0
m_InstancingStripping: 0
m_LightmapKeepPlain: 1
m_LightmapKeepDirCombined: 1
m_LightmapKeepDynamicPlain: 1
m_LightmapKeepDynamicDirCombined: 1
m_LightmapKeepShadowMask: 1
m_LightmapKeepSubtractive: 1
m_FogKeepLinear: 1
m_FogKeepExp: 1
m_FogKeepExp2: 1
m_AlbedoSwatchInfos: []
m_LightsUseLinearIntensity: 0
m_LightsUseColorTemperature: 0
m_DefaultRenderingLayerMask: 1
m_LogWhenShaderIsCompiled: 0
@@ -0,0 +1,487 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!13 &1
InputManager:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Axes:
- serializedVersion: 3
m_Name: Horizontal
descriptiveName:
descriptiveNegativeName:
negativeButton: left
positiveButton: right
altNegativeButton: a
altPositiveButton: d
gravity: 3
dead: 0.001
sensitivity: 3
snap: 1
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Vertical
descriptiveName:
descriptiveNegativeName:
negativeButton: down
positiveButton: up
altNegativeButton: s
altPositiveButton: w
gravity: 3
dead: 0.001
sensitivity: 3
snap: 1
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Fire1
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: left ctrl
altNegativeButton:
altPositiveButton: mouse 0
gravity: 1000
dead: 0.001
sensitivity: 1000
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Fire2
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: left alt
altNegativeButton:
altPositiveButton: mouse 1
gravity: 1000
dead: 0.001
sensitivity: 1000
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Fire3
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: left shift
altNegativeButton:
altPositiveButton: mouse 2
gravity: 1000
dead: 0.001
sensitivity: 1000
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Jump
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: space
altNegativeButton:
altPositiveButton:
gravity: 1000
dead: 0.001
sensitivity: 1000
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Mouse X
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton:
altNegativeButton:
altPositiveButton:
gravity: 0
dead: 0
sensitivity: 0.1
snap: 0
invert: 0
type: 1
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Mouse Y
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton:
altNegativeButton:
altPositiveButton:
gravity: 0
dead: 0
sensitivity: 0.1
snap: 0
invert: 0
type: 1
axis: 1
joyNum: 0
- serializedVersion: 3
m_Name: Mouse ScrollWheel
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton:
altNegativeButton:
altPositiveButton:
gravity: 0
dead: 0
sensitivity: 0.1
snap: 0
invert: 0
type: 1
axis: 2
joyNum: 0
- serializedVersion: 3
m_Name: Horizontal
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton:
altNegativeButton:
altPositiveButton:
gravity: 0
dead: 0.19
sensitivity: 1
snap: 0
invert: 0
type: 2
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Vertical
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton:
altNegativeButton:
altPositiveButton:
gravity: 0
dead: 0.19
sensitivity: 1
snap: 0
invert: 1
type: 2
axis: 1
joyNum: 0
- serializedVersion: 3
m_Name: Fire1
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: joystick button 0
altNegativeButton:
altPositiveButton:
gravity: 1000
dead: 0.001
sensitivity: 1000
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Fire2
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: joystick button 1
altNegativeButton:
altPositiveButton:
gravity: 1000
dead: 0.001
sensitivity: 1000
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Fire3
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: joystick button 2
altNegativeButton:
altPositiveButton:
gravity: 1000
dead: 0.001
sensitivity: 1000
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Jump
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: joystick button 3
altNegativeButton:
altPositiveButton:
gravity: 1000
dead: 0.001
sensitivity: 1000
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Submit
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: return
altNegativeButton:
altPositiveButton: joystick button 0
gravity: 1000
dead: 0.001
sensitivity: 1000
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Submit
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: enter
altNegativeButton:
altPositiveButton: space
gravity: 1000
dead: 0.001
sensitivity: 1000
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Cancel
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: escape
altNegativeButton:
altPositiveButton: joystick button 1
gravity: 1000
dead: 0.001
sensitivity: 1000
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Enable Debug Button 1
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: left ctrl
altNegativeButton:
altPositiveButton: joystick button 8
gravity: 0
dead: 0
sensitivity: 0
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Enable Debug Button 2
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: backspace
altNegativeButton:
altPositiveButton: joystick button 9
gravity: 0
dead: 0
sensitivity: 0
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Debug Reset
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: left alt
altNegativeButton:
altPositiveButton: joystick button 1
gravity: 0
dead: 0
sensitivity: 0
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Debug Next
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: page down
altNegativeButton:
altPositiveButton: joystick button 5
gravity: 0
dead: 0
sensitivity: 0
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Debug Previous
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: page up
altNegativeButton:
altPositiveButton: joystick button 4
gravity: 0
dead: 0
sensitivity: 0
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Debug Validate
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: return
altNegativeButton:
altPositiveButton: joystick button 0
gravity: 0
dead: 0
sensitivity: 0
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Debug Persistent
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: right shift
altNegativeButton:
altPositiveButton: joystick button 2
gravity: 0
dead: 0
sensitivity: 0
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Debug Multiplier
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: left shift
altNegativeButton:
altPositiveButton: joystick button 3
gravity: 0
dead: 0
sensitivity: 0
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Debug Horizontal
descriptiveName:
descriptiveNegativeName:
negativeButton: left
positiveButton: right
altNegativeButton:
altPositiveButton:
gravity: 1000
dead: 0.001
sensitivity: 1000
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Debug Vertical
descriptiveName:
descriptiveNegativeName:
negativeButton: down
positiveButton: up
altNegativeButton:
altPositiveButton:
gravity: 1000
dead: 0.001
sensitivity: 1000
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Debug Vertical
descriptiveName:
descriptiveNegativeName:
negativeButton: down
positiveButton: up
altNegativeButton:
altPositiveButton:
gravity: 1000
dead: 0.001
sensitivity: 1000
snap: 0
invert: 0
type: 2
axis: 6
joyNum: 0
- serializedVersion: 3
m_Name: Debug Horizontal
descriptiveName:
descriptiveNegativeName:
negativeButton: left
positiveButton: right
altNegativeButton:
altPositiveButton:
gravity: 1000
dead: 0.001
sensitivity: 1000
snap: 0
invert: 0
type: 2
axis: 5
joyNum: 0
@@ -0,0 +1,35 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!387306366 &1
MemorySettings:
m_ObjectHideFlags: 0
m_EditorMemorySettings:
m_MainAllocatorBlockSize: -1
m_ThreadAllocatorBlockSize: -1
m_MainGfxBlockSize: -1
m_ThreadGfxBlockSize: -1
m_CacheBlockSize: -1
m_TypetreeBlockSize: -1
m_ProfilerBlockSize: -1
m_ProfilerEditorBlockSize: -1
m_BucketAllocatorGranularity: -1
m_BucketAllocatorBucketsCount: -1
m_BucketAllocatorBlockSize: -1
m_BucketAllocatorBlockCount: -1
m_ProfilerBucketAllocatorGranularity: -1
m_ProfilerBucketAllocatorBucketsCount: -1
m_ProfilerBucketAllocatorBlockSize: -1
m_ProfilerBucketAllocatorBlockCount: -1
m_TempAllocatorSizeMain: -1
m_JobTempAllocatorBlockSize: -1
m_BackgroundJobTempAllocatorBlockSize: -1
m_JobTempAllocatorReducedBlockSize: -1
m_TempAllocatorSizeGIBakingWorker: -1
m_TempAllocatorSizeNavMeshWorker: -1
m_TempAllocatorSizeAudioWorker: -1
m_TempAllocatorSizeCloudWorker: -1
m_TempAllocatorSizeGfx: -1
m_TempAllocatorSizeJobWorker: -1
m_TempAllocatorSizeBackgroundWorker: -1
m_TempAllocatorSizePreloadManager: -1
m_PlatformMemorySettings: {}
@@ -0,0 +1,7 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!655991488 &1
MultiplayerManager:
m_ObjectHideFlags: 0
m_EnableMultiplayerRoles: 0
m_StrippingTypes: {}
@@ -0,0 +1,93 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!126 &1
NavMeshProjectSettings:
m_ObjectHideFlags: 0
serializedVersion: 2
areas:
- name: Walkable
cost: 1
- name: Not Walkable
cost: 1
- name: Jump
cost: 2
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
- name:
cost: 1
m_LastAgentTypeID: -887442657
m_Settings:
- serializedVersion: 2
agentTypeID: 0
agentRadius: 0.5
agentHeight: 2
agentSlope: 45
agentClimb: 0.75
ledgeDropHeight: 0
maxJumpAcrossDistance: 0
minRegionArea: 2
manualCellSize: 0
cellSize: 0.16666667
manualTileSize: 0
tileSize: 256
accuratePlacement: 0
maxJobWorkers: 0
preserveTilesOutsideBounds: 0
debug:
m_Flags: 0
m_SettingNames:
- Humanoid
@@ -0,0 +1,8 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!149 &1
NetworkManager:
m_ObjectHideFlags: 0
m_DebugLevel: 0
m_Sendrate: 15
m_AssetToPrefab: {}
@@ -0,0 +1,44 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &1
MonoBehaviour:
m_ObjectHideFlags: 61
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0}
m_Name:
m_EditorClassIdentifier:
m_EnablePreReleasePackages: 0
m_EnablePackageDependencies: 0
m_AdvancedSettingsExpanded: 1
m_ScopedRegistriesSettingsExpanded: 1
m_SeeAllPackageVersions: 0
oneTimeWarningShown: 0
m_Registries:
- m_Id: main
m_Name:
m_Url: https://packages.unity.com
m_Scopes: []
m_IsDefault: 1
m_Capabilities: 7
m_UserSelectedRegistryName:
m_UserAddingNewScopedRegistry: 0
m_RegistryInfoDraft:
m_ErrorMessage:
m_Original:
m_Id:
m_Name:
m_Url:
m_Scopes: []
m_IsDefault: 0
m_Capabilities: 0
m_Modified: 0
m_Name:
m_Url:
m_Scopes:
-
m_SelectedScopeIndex: 0
@@ -0,0 +1,56 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!19 &1
Physics2DSettings:
m_ObjectHideFlags: 0
serializedVersion: 5
m_Gravity: {x: 0, y: -9.81}
m_DefaultMaterial: {fileID: 0}
m_VelocityIterations: 8
m_PositionIterations: 3
m_VelocityThreshold: 1
m_MaxLinearCorrection: 0.2
m_MaxAngularCorrection: 8
m_MaxTranslationSpeed: 100
m_MaxRotationSpeed: 360
m_BaumgarteScale: 0.2
m_BaumgarteTimeOfImpactScale: 0.75
m_TimeToSleep: 0.5
m_LinearSleepTolerance: 0.01
m_AngularSleepTolerance: 2
m_DefaultContactOffset: 0.01
m_JobOptions:
serializedVersion: 2
useMultithreading: 0
useConsistencySorting: 0
m_InterpolationPosesPerJob: 100
m_NewContactsPerJob: 30
m_CollideContactsPerJob: 100
m_ClearFlagsPerJob: 200
m_ClearBodyForcesPerJob: 200
m_SyncDiscreteFixturesPerJob: 50
m_SyncContinuousFixturesPerJob: 50
m_FindNearestContactsPerJob: 100
m_UpdateTriggerContactsPerJob: 100
m_IslandSolverCostThreshold: 100
m_IslandSolverBodyCostScale: 1
m_IslandSolverContactCostScale: 10
m_IslandSolverJointCostScale: 10
m_IslandSolverBodiesPerJob: 50
m_IslandSolverContactsPerJob: 50
m_SimulationMode: 0
m_QueriesHitTriggers: 1
m_QueriesStartInColliders: 1
m_CallbacksOnDisable: 1
m_ReuseCollisionCallbacks: 1
m_AutoSyncTransforms: 0
m_AlwaysShowColliders: 0
m_ShowColliderSleep: 1
m_ShowColliderContacts: 0
m_ShowColliderAABB: 0
m_ContactArrowScale: 0.2
m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412}
m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432}
m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745}
m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804}
m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
@@ -0,0 +1,7 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1386491679 &1
PresetManager:
m_ObjectHideFlags: 0
serializedVersion: 2
m_DefaultPresets: {}
@@ -0,0 +1,737 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!129 &1
PlayerSettings:
m_ObjectHideFlags: 0
serializedVersion: 28
productGUID: 347ef167e38f44dd4ad3618bb9e1a4f9
AndroidProfiler: 0
AndroidFilterTouchesWhenObscured: 0
AndroidEnableSustainedPerformanceMode: 0
defaultScreenOrientation: 4
targetDevice: 2
useOnDemandResources: 0
accelerometerFrequency: 60
companyName: DefaultCompany
productName: unity
defaultCursor: {fileID: 0}
cursorHotspot: {x: 0, y: 0}
m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1}
m_ShowUnitySplashScreen: 1
m_ShowUnitySplashLogo: 1
m_SplashScreenOverlayOpacity: 1
m_SplashScreenAnimation: 1
m_SplashScreenLogoStyle: 1
m_SplashScreenDrawMode: 0
m_SplashScreenBackgroundAnimationZoom: 1
m_SplashScreenLogoAnimationZoom: 1
m_SplashScreenBackgroundLandscapeAspect: 1
m_SplashScreenBackgroundPortraitAspect: 1
m_SplashScreenBackgroundLandscapeUvs:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
m_SplashScreenBackgroundPortraitUvs:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
m_SplashScreenLogos: []
m_VirtualRealitySplashScreen: {fileID: 0}
m_HolographicTrackingLossScreen: {fileID: 0}
defaultScreenWidth: 1920
defaultScreenHeight: 1080
defaultScreenWidthWeb: 960
defaultScreenHeightWeb: 600
m_StereoRenderingPath: 0
m_ActiveColorSpace: 1
unsupportedMSAAFallback: 0
m_SpriteBatchMaxVertexCount: 65535
m_SpriteBatchVertexThreshold: 300
m_MTRendering: 1
mipStripping: 0
numberOfMipsStripped: 0
numberOfMipsStrippedPerMipmapLimitGroup: {}
m_StackTraceTypes: 010000000100000001000000010000000100000001000000
iosShowActivityIndicatorOnLoading: -1
androidShowActivityIndicatorOnLoading: -1
iosUseCustomAppBackgroundBehavior: 0
allowedAutorotateToPortrait: 1
allowedAutorotateToPortraitUpsideDown: 1
allowedAutorotateToLandscapeRight: 1
allowedAutorotateToLandscapeLeft: 1
useOSAutorotation: 1
use32BitDisplayBuffer: 1
preserveFramebufferAlpha: 0
disableDepthAndStencilBuffers: 0
androidStartInFullscreen: 1
androidRenderOutsideSafeArea: 1
androidUseSwappy: 1
androidDisplayOptions: 1
androidBlitType: 0
androidResizeableActivity: 1
androidDefaultWindowWidth: 1920
androidDefaultWindowHeight: 1080
androidMinimumWindowWidth: 400
androidMinimumWindowHeight: 300
androidFullscreenMode: 1
androidAutoRotationBehavior: 1
androidPredictiveBackSupport: 0
androidApplicationEntry: 2
defaultIsNativeResolution: 1
macRetinaSupport: 1
runInBackground: 0
muteOtherAudioSources: 0
Prepare IOS For Recording: 0
Force IOS Speakers When Recording: 0
audioSpatialExperience: 0
deferSystemGesturesMode: 0
hideHomeButton: 0
submitAnalytics: 1
usePlayerLog: 1
dedicatedServerOptimizations: 1
bakeCollisionMeshes: 0
forceSingleInstance: 0
useFlipModelSwapchain: 1
resizableWindow: 0
useMacAppStoreValidation: 0
macAppStoreCategory: public.app-category.games
gpuSkinning: 0
meshDeformation: 0
xboxPIXTextureCapture: 0
xboxEnableAvatar: 0
xboxEnableKinect: 0
xboxEnableKinectAutoTracking: 0
xboxEnableFitness: 0
visibleInBackground: 1
allowFullscreenSwitch: 1
fullscreenMode: 1
xboxSpeechDB: 0
xboxEnableHeadOrientation: 0
xboxEnableGuest: 0
xboxEnablePIXSampling: 0
metalFramebufferOnly: 0
metalUseMetalDisplayLink: 0
xboxOneResolution: 0
xboxOneSResolution: 0
xboxOneXResolution: 3
xboxOneMonoLoggingLevel: 0
xboxOneLoggingLevel: 1
xboxOneDisableEsram: 0
xboxOneEnableTypeOptimization: 0
xboxOnePresentImmediateThreshold: 0
switchQueueCommandMemory: 1048576
switchQueueControlMemory: 16384
switchQueueComputeMemory: 262144
switchNVNShaderPoolsGranularity: 33554432
switchNVNDefaultPoolsGranularity: 16777216
switchNVNOtherPoolsGranularity: 16777216
switchGpuScratchPoolGranularity: 2097152
switchAllowGpuScratchShrinking: 0
switchNVNMaxPublicTextureIDCount: 0
switchNVNMaxPublicSamplerIDCount: 0
switchMaxWorkerMultiple: 8
switchNVNGraphicsFirmwareMemory: 32
switchGraphicsJobsSyncAfterKick: 1
vulkanNumSwapchainBuffers: 3
vulkanEnableSetSRGBWrite: 0
vulkanEnablePreTransform: 0
vulkanEnableLateAcquireNextImage: 0
vulkanEnableCommandBufferRecycling: 1
loadStoreDebugModeEnabled: 0
visionOSBundleVersion: 1.0
tvOSBundleVersion: 1.0
bundleVersion: 1.0
preloadedAssets: []
metroInputSource: 0
wsaTransparentSwapchain: 0
m_HolographicPauseOnTrackingLoss: 1
xboxOneDisableKinectGpuReservation: 1
xboxOneEnable7thCore: 1
vrSettings:
enable360StereoCapture: 0
isWsaHolographicRemotingEnabled: 0
enableFrameTimingStats: 0
enableOpenGLProfilerGPURecorders: 1
allowHDRDisplaySupport: 0
useHDRDisplay: 0
hdrBitDepth: 0
m_ColorGamuts: 00000000
targetPixelDensity: 30
resolutionScalingMode: 0
resetResolutionOnWindowResize: 0
androidSupportedAspectRatio: 1
androidMaxAspectRatio: 2.4
androidMinAspectRatio: 1
applicationIdentifier:
Standalone: com.DefaultCompany.2D-Project
buildNumber:
Standalone: 0
VisionOS: 0
iPhone: 0
tvOS: 0
overrideDefaultApplicationIdentifier: 1
AndroidBundleVersionCode: 1
AndroidMinSdkVersion: 25
AndroidTargetSdkVersion: 0
AndroidPreferredInstallLocation: 1
AndroidPreferredDataLocation: 1
aotOptions:
stripEngineCode: 1
iPhoneStrippingLevel: 0
iPhoneScriptCallOptimization: 0
ForceInternetPermission: 0
ForceSDCardPermission: 0
CreateWallpaper: 0
androidSplitApplicationBinary: 0
keepLoadedShadersAlive: 0
StripUnusedMeshComponents: 0
strictShaderVariantMatching: 0
VertexChannelCompressionMask: 4054
iPhoneSdkVersion: 988
iOSSimulatorArchitecture: 0
iOSTargetOSVersionString: 15.0
tvOSSdkVersion: 0
tvOSSimulatorArchitecture: 0
tvOSRequireExtendedGameController: 0
tvOSTargetOSVersionString: 15.0
VisionOSSdkVersion: 0
VisionOSTargetOSVersionString: 1.0
uIPrerenderedIcon: 0
uIRequiresPersistentWiFi: 0
uIRequiresFullScreen: 1
uIStatusBarHidden: 1
uIExitOnSuspend: 0
uIStatusBarStyle: 0
appleTVSplashScreen: {fileID: 0}
appleTVSplashScreen2x: {fileID: 0}
tvOSSmallIconLayers: []
tvOSSmallIconLayers2x: []
tvOSLargeIconLayers: []
tvOSLargeIconLayers2x: []
tvOSTopShelfImageLayers: []
tvOSTopShelfImageLayers2x: []
tvOSTopShelfImageWideLayers: []
tvOSTopShelfImageWideLayers2x: []
iOSLaunchScreenType: 0
iOSLaunchScreenPortrait: {fileID: 0}
iOSLaunchScreenLandscape: {fileID: 0}
iOSLaunchScreenBackgroundColor:
serializedVersion: 2
rgba: 0
iOSLaunchScreenFillPct: 100
iOSLaunchScreenSize: 100
iOSLaunchScreeniPadType: 0
iOSLaunchScreeniPadImage: {fileID: 0}
iOSLaunchScreeniPadBackgroundColor:
serializedVersion: 2
rgba: 0
iOSLaunchScreeniPadFillPct: 100
iOSLaunchScreeniPadSize: 100
iOSLaunchScreenCustomStoryboardPath:
iOSLaunchScreeniPadCustomStoryboardPath:
iOSDeviceRequirements: []
iOSURLSchemes: []
macOSURLSchemes: []
iOSBackgroundModes: 0
iOSMetalForceHardShadows: 0
metalEditorSupport: 1
metalAPIValidation: 1
metalCompileShaderBinary: 0
iOSRenderExtraFrameOnPause: 0
iosCopyPluginsCodeInsteadOfSymlink: 0
appleDeveloperTeamID:
iOSManualSigningProvisioningProfileID:
tvOSManualSigningProvisioningProfileID:
VisionOSManualSigningProvisioningProfileID:
iOSManualSigningProvisioningProfileType: 0
tvOSManualSigningProvisioningProfileType: 0
VisionOSManualSigningProvisioningProfileType: 0
appleEnableAutomaticSigning: 0
iOSRequireARKit: 0
iOSAutomaticallyDetectAndAddCapabilities: 1
appleEnableProMotion: 0
shaderPrecisionModel: 0
clonedFromGUID: 10ad67313f4034357812315f3c407484
templatePackageId: com.unity.template.2d@11.0.0
templateDefaultScene: Assets/Scenes/SampleScene.unity
useCustomMainManifest: 0
useCustomLauncherManifest: 0
useCustomMainGradleTemplate: 0
useCustomLauncherGradleManifest: 0
useCustomBaseGradleTemplate: 0
useCustomGradlePropertiesTemplate: 0
useCustomGradleSettingsTemplate: 0
useCustomProguardFile: 0
AndroidTargetArchitectures: 2
AndroidAllowedArchitectures: -13
AndroidSplashScreenScale: 0
androidSplashScreen: {fileID: 0}
AndroidKeystoreName:
AndroidKeyaliasName:
AndroidEnableArmv9SecurityFeatures: 0
AndroidEnableArm64MTE: 0
AndroidBuildApkPerCpuArchitecture: 0
AndroidTVCompatibility: 0
AndroidIsGame: 1
androidAppCategory: 3
useAndroidAppCategory: 1
androidAppCategoryOther:
AndroidEnableTango: 0
androidEnableBanner: 1
androidUseLowAccuracyLocation: 0
androidUseCustomKeystore: 0
m_AndroidBanners:
- width: 320
height: 180
banner: {fileID: 0}
androidGamepadSupportLevel: 0
AndroidMinifyRelease: 0
AndroidMinifyDebug: 0
AndroidValidateAppBundleSize: 1
AndroidAppBundleSizeToValidate: 150
AndroidReportGooglePlayAppDependencies: 1
androidSymbolsSizeThreshold: 800
m_BuildTargetIcons: []
m_BuildTargetPlatformIcons: []
m_BuildTargetBatching: []
m_BuildTargetShaderSettings: []
m_BuildTargetGraphicsJobs:
- m_BuildTarget: MacStandaloneSupport
m_GraphicsJobs: 0
- m_BuildTarget: Switch
m_GraphicsJobs: 0
- m_BuildTarget: MetroSupport
m_GraphicsJobs: 0
- m_BuildTarget: AppleTVSupport
m_GraphicsJobs: 0
- m_BuildTarget: BJMSupport
m_GraphicsJobs: 0
- m_BuildTarget: LinuxStandaloneSupport
m_GraphicsJobs: 0
- m_BuildTarget: PS4Player
m_GraphicsJobs: 0
- m_BuildTarget: iOSSupport
m_GraphicsJobs: 0
- m_BuildTarget: WindowsStandaloneSupport
m_GraphicsJobs: 0
- m_BuildTarget: XboxOnePlayer
m_GraphicsJobs: 0
- m_BuildTarget: LuminSupport
m_GraphicsJobs: 0
- m_BuildTarget: AndroidPlayer
m_GraphicsJobs: 0
- m_BuildTarget: WebGLSupport
m_GraphicsJobs: 0
m_BuildTargetGraphicsJobMode: []
m_BuildTargetGraphicsAPIs:
- m_BuildTarget: AndroidPlayer
m_APIs: 150000000b000000
m_Automatic: 1
- m_BuildTarget: iOSSupport
m_APIs: 10000000
m_Automatic: 1
m_BuildTargetVRSettings: []
m_DefaultShaderChunkSizeInMB: 16
m_DefaultShaderChunkCount: 0
openGLRequireES31: 0
openGLRequireES31AEP: 0
openGLRequireES32: 0
m_TemplateCustomTags: {}
mobileMTRendering:
Android: 1
iPhone: 1
tvOS: 1
m_BuildTargetGroupLightmapEncodingQuality: []
m_BuildTargetGroupHDRCubemapEncodingQuality: []
m_BuildTargetGroupLightmapSettings: []
m_BuildTargetGroupLoadStoreDebugModeSettings: []
m_BuildTargetNormalMapEncoding: []
m_BuildTargetDefaultTextureCompressionFormat:
- serializedVersion: 3
m_BuildTarget: Android
m_Formats: 03000000
playModeTestRunnerEnabled: 0
runPlayModeTestAsEditModeTest: 0
actionOnDotNetUnhandledException: 1
editorGfxJobOverride: 1
enableInternalProfiler: 0
logObjCUncaughtExceptions: 1
enableCrashReportAPI: 0
cameraUsageDescription:
locationUsageDescription:
microphoneUsageDescription:
bluetoothUsageDescription:
macOSTargetOSVersion: 12.0
switchNMETAOverride:
switchNetLibKey:
switchSocketMemoryPoolSize: 6144
switchSocketAllocatorPoolSize: 128
switchSocketConcurrencyLimit: 14
switchScreenResolutionBehavior: 2
switchUseCPUProfiler: 0
switchEnableFileSystemTrace: 0
switchLTOSetting: 0
switchApplicationID: 0x01004b9000490000
switchNSODependencies:
switchCompilerFlags:
switchTitleNames_0:
switchTitleNames_1:
switchTitleNames_2:
switchTitleNames_3:
switchTitleNames_4:
switchTitleNames_5:
switchTitleNames_6:
switchTitleNames_7:
switchTitleNames_8:
switchTitleNames_9:
switchTitleNames_10:
switchTitleNames_11:
switchTitleNames_12:
switchTitleNames_13:
switchTitleNames_14:
switchTitleNames_15:
switchPublisherNames_0:
switchPublisherNames_1:
switchPublisherNames_2:
switchPublisherNames_3:
switchPublisherNames_4:
switchPublisherNames_5:
switchPublisherNames_6:
switchPublisherNames_7:
switchPublisherNames_8:
switchPublisherNames_9:
switchPublisherNames_10:
switchPublisherNames_11:
switchPublisherNames_12:
switchPublisherNames_13:
switchPublisherNames_14:
switchPublisherNames_15:
switchIcons_0: {fileID: 0}
switchIcons_1: {fileID: 0}
switchIcons_2: {fileID: 0}
switchIcons_3: {fileID: 0}
switchIcons_4: {fileID: 0}
switchIcons_5: {fileID: 0}
switchIcons_6: {fileID: 0}
switchIcons_7: {fileID: 0}
switchIcons_8: {fileID: 0}
switchIcons_9: {fileID: 0}
switchIcons_10: {fileID: 0}
switchIcons_11: {fileID: 0}
switchIcons_12: {fileID: 0}
switchIcons_13: {fileID: 0}
switchIcons_14: {fileID: 0}
switchIcons_15: {fileID: 0}
switchSmallIcons_0: {fileID: 0}
switchSmallIcons_1: {fileID: 0}
switchSmallIcons_2: {fileID: 0}
switchSmallIcons_3: {fileID: 0}
switchSmallIcons_4: {fileID: 0}
switchSmallIcons_5: {fileID: 0}
switchSmallIcons_6: {fileID: 0}
switchSmallIcons_7: {fileID: 0}
switchSmallIcons_8: {fileID: 0}
switchSmallIcons_9: {fileID: 0}
switchSmallIcons_10: {fileID: 0}
switchSmallIcons_11: {fileID: 0}
switchSmallIcons_12: {fileID: 0}
switchSmallIcons_13: {fileID: 0}
switchSmallIcons_14: {fileID: 0}
switchSmallIcons_15: {fileID: 0}
switchManualHTML:
switchAccessibleURLs:
switchLegalInformation:
switchMainThreadStackSize: 1048576
switchPresenceGroupId:
switchLogoHandling: 0
switchReleaseVersion: 0
switchDisplayVersion: 1.0.0
switchStartupUserAccount: 0
switchSupportedLanguagesMask: 0
switchLogoType: 0
switchApplicationErrorCodeCategory:
switchUserAccountSaveDataSize: 0
switchUserAccountSaveDataJournalSize: 0
switchApplicationAttribute: 0
switchCardSpecSize: -1
switchCardSpecClock: -1
switchRatingsMask: 0
switchRatingsInt_0: 0
switchRatingsInt_1: 0
switchRatingsInt_2: 0
switchRatingsInt_3: 0
switchRatingsInt_4: 0
switchRatingsInt_5: 0
switchRatingsInt_6: 0
switchRatingsInt_7: 0
switchRatingsInt_8: 0
switchRatingsInt_9: 0
switchRatingsInt_10: 0
switchRatingsInt_11: 0
switchRatingsInt_12: 0
switchLocalCommunicationIds_0:
switchLocalCommunicationIds_1:
switchLocalCommunicationIds_2:
switchLocalCommunicationIds_3:
switchLocalCommunicationIds_4:
switchLocalCommunicationIds_5:
switchLocalCommunicationIds_6:
switchLocalCommunicationIds_7:
switchParentalControl: 0
switchAllowsScreenshot: 1
switchAllowsVideoCapturing: 1
switchAllowsRuntimeAddOnContentInstall: 0
switchDataLossConfirmation: 0
switchUserAccountLockEnabled: 0
switchSystemResourceMemory: 16777216
switchSupportedNpadStyles: 22
switchNativeFsCacheSize: 32
switchIsHoldTypeHorizontal: 0
switchSupportedNpadCount: 8
switchEnableTouchScreen: 1
switchSocketConfigEnabled: 0
switchTcpInitialSendBufferSize: 32
switchTcpInitialReceiveBufferSize: 64
switchTcpAutoSendBufferSizeMax: 256
switchTcpAutoReceiveBufferSizeMax: 256
switchUdpSendBufferSize: 9
switchUdpReceiveBufferSize: 42
switchSocketBufferEfficiency: 4
switchSocketInitializeEnabled: 1
switchNetworkInterfaceManagerInitializeEnabled: 1
switchDisableHTCSPlayerConnection: 0
switchUseNewStyleFilepaths: 0
switchUseLegacyFmodPriorities: 0
switchUseMicroSleepForYield: 1
switchEnableRamDiskSupport: 0
switchMicroSleepForYieldTime: 25
switchRamDiskSpaceSize: 12
switchUpgradedPlayerSettingsToNMETA: 0
ps4NPAgeRating: 12
ps4NPTitleSecret:
ps4NPTrophyPackPath:
ps4ParentalLevel: 11
ps4ContentID: ED1633-NPXX51362_00-0000000000000000
ps4Category: 0
ps4MasterVersion: 01.00
ps4AppVersion: 01.00
ps4AppType: 0
ps4ParamSfxPath:
ps4VideoOutPixelFormat: 0
ps4VideoOutInitialWidth: 1920
ps4VideoOutBaseModeInitialWidth: 1920
ps4VideoOutReprojectionRate: 60
ps4PronunciationXMLPath:
ps4PronunciationSIGPath:
ps4BackgroundImagePath:
ps4StartupImagePath:
ps4StartupImagesFolder:
ps4IconImagesFolder:
ps4SaveDataImagePath:
ps4SdkOverride:
ps4BGMPath:
ps4ShareFilePath:
ps4ShareOverlayImagePath:
ps4PrivacyGuardImagePath:
ps4ExtraSceSysFile:
ps4NPtitleDatPath:
ps4RemotePlayKeyAssignment: -1
ps4RemotePlayKeyMappingDir:
ps4PlayTogetherPlayerCount: 0
ps4EnterButtonAssignment: 2
ps4ApplicationParam1: 0
ps4ApplicationParam2: 0
ps4ApplicationParam3: 0
ps4ApplicationParam4: 0
ps4DownloadDataSize: 0
ps4GarlicHeapSize: 2048
ps4ProGarlicHeapSize: 2560
playerPrefsMaxSize: 32768
ps4Passcode: ARLRRL59bcfuU0C9AGuPDYRMsZlDaGMq
ps4pnSessions: 1
ps4pnPresence: 1
ps4pnFriends: 1
ps4pnGameCustomData: 1
playerPrefsSupport: 0
enableApplicationExit: 0
resetTempFolder: 1
restrictedAudioUsageRights: 0
ps4UseResolutionFallback: 0
ps4ReprojectionSupport: 0
ps4UseAudio3dBackend: 0
ps4UseLowGarlicFragmentationMode: 1
ps4SocialScreenEnabled: 0
ps4ScriptOptimizationLevel: 2
ps4Audio3dVirtualSpeakerCount: 14
ps4attribCpuUsage: 0
ps4PatchPkgPath:
ps4PatchLatestPkgPath:
ps4PatchChangeinfoPath:
ps4PatchDayOne: 0
ps4attribUserManagement: 0
ps4attribMoveSupport: 0
ps4attrib3DSupport: 0
ps4attribShareSupport: 0
ps4attribExclusiveVR: 0
ps4disableAutoHideSplash: 0
ps4videoRecordingFeaturesUsed: 0
ps4contentSearchFeaturesUsed: 0
ps4CompatibilityPS5: 0
ps4AllowPS5Detection: 0
ps4GPU800MHz: 1
ps4attribEyeToEyeDistanceSettingVR: 0
ps4IncludedModules: []
ps4attribVROutputEnabled: 0
monoEnv:
splashScreenBackgroundSourceLandscape: {fileID: 0}
splashScreenBackgroundSourcePortrait: {fileID: 0}
blurSplashScreenBackground: 1
spritePackerPolicy:
webGLMemorySize: 32
webGLExceptionSupport: 1
webGLNameFilesAsHashes: 0
webGLShowDiagnostics: 0
webGLDataCaching: 1
webGLDebugSymbols: 0
webGLEmscriptenArgs:
webGLModulesDirectory:
webGLTemplate: APPLICATION:Default
webGLAnalyzeBuildSize: 0
webGLUseEmbeddedResources: 0
webGLCompressionFormat: 0
webGLWasmArithmeticExceptions: 0
webGLLinkerTarget: 1
webGLThreadsSupport: 0
webGLDecompressionFallback: 0
webGLInitialMemorySize: 32
webGLMaximumMemorySize: 2048
webGLMemoryGrowthMode: 2
webGLMemoryLinearGrowthStep: 16
webGLMemoryGeometricGrowthStep: 0.2
webGLMemoryGeometricGrowthCap: 96
webGLPowerPreference: 2
webGLWebAssemblyTable: 0
webGLWebAssemblyBigInt: 0
webGLCloseOnQuit: 0
webWasm2023: 0
webEnableSubmoduleStrippingCompatibility: 0
scriptingDefineSymbols: {}
additionalCompilerArguments: {}
platformArchitecture: {}
scriptingBackend:
Android: 1
Standalone: 1
il2cppCompilerConfiguration: {}
il2cppCodeGeneration: {}
il2cppStacktraceInformation: {}
managedStrippingLevel: {}
incrementalIl2cppBuild: {}
suppressCommonWarnings: 1
allowUnsafeCode: 0
useDeterministicCompilation: 1
additionalIl2CppArgs:
scriptingRuntimeVersion: 1
gcIncremental: 1
gcWBarrierValidation: 0
apiCompatibilityLevelPerPlatform: {}
editorAssembliesCompatibilityLevel: 1
m_RenderingPath: 1
m_MobileRenderingPath: 1
metroPackageName: unity
metroPackageVersion:
metroCertificatePath:
metroCertificatePassword:
metroCertificateSubject:
metroCertificateIssuer:
metroCertificateNotAfter: 0000000000000000
metroApplicationDescription: unity
wsaImages: {}
metroTileShortName:
metroTileShowName: 0
metroMediumTileShowName: 0
metroLargeTileShowName: 0
metroWideTileShowName: 0
metroSupportStreamingInstall: 0
metroLastRequiredScene: 0
metroDefaultTileSize: 1
metroTileForegroundText: 2
metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0}
metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, a: 1}
metroSplashScreenUseBackgroundColor: 0
syncCapabilities: 0
platformCapabilities: {}
metroTargetDeviceFamilies: {}
metroFTAName:
metroFTAFileTypes: []
metroProtocolName:
vcxProjDefaultLanguage:
XboxOneProductId:
XboxOneUpdateKey:
XboxOneSandboxId:
XboxOneContentId:
XboxOneTitleId:
XboxOneSCId:
XboxOneGameOsOverridePath:
XboxOnePackagingOverridePath:
XboxOneAppManifestOverridePath:
XboxOneVersion: 1.0.0.0
XboxOnePackageEncryption: 0
XboxOnePackageUpdateGranularity: 2
XboxOneDescription:
XboxOneLanguage:
- enus
XboxOneCapability: []
XboxOneGameRating: {}
XboxOneIsContentPackage: 0
XboxOneEnhancedXboxCompatibilityMode: 0
XboxOneEnableGPUVariability: 1
XboxOneSockets: {}
XboxOneSplashScreen: {fileID: 0}
XboxOneAllowedProductIds: []
XboxOnePersistentLocalStorageSize: 0
XboxOneXTitleMemory: 8
XboxOneOverrideIdentityName:
XboxOneOverrideIdentityPublisher:
vrEditorSettings: {}
cloudServicesEnabled: {}
luminIcon:
m_Name:
m_ModelFolderPath:
m_PortalFolderPath:
luminCert:
m_CertPath:
m_SignPackage: 1
luminIsChannelApp: 0
luminVersion:
m_VersionCode: 1
m_VersionName:
hmiPlayerDataPath:
hmiForceSRGBBlit: 0
embeddedLinuxEnableGamepadInput: 0
hmiCpuConfiguration:
hmiLogStartupTiming: 0
qnxGraphicConfPath:
apiCompatibilityLevel: 6
captureStartupLogs: {}
activeInputHandler: 1
windowsGamepadBackendHint: 0
cloudProjectId:
framebufferDepthMemorylessMode: 0
qualitySettingsNames: []
projectName:
organizationId:
cloudEnabled: 0
legacyClampBlendShapeWeights: 0
hmiLoadingImage: {fileID: 0}
platformRequiresReadableAssets: 0
virtualTexturingSupportEnabled: 0
insecureHttpOption: 0
androidVulkanDenyFilterList: []
androidVulkanAllowFilterList: []
androidVulkanDeviceFilterListAsset: {fileID: 0}
d3d12DeviceFilterListAsset: {fileID: 0}
allowedHttpConnections: 3
@@ -0,0 +1,2 @@
m_EditorVersion: 6000.3.11f1
m_EditorVersionWithRevision: 6000.3.11f1 (3000ef702840)
@@ -0,0 +1,239 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!47 &1
QualitySettings:
m_ObjectHideFlags: 0
serializedVersion: 5
m_CurrentQuality: 5
m_QualitySettings:
- serializedVersion: 2
name: Very Low
pixelLightCount: 0
shadows: 0
shadowResolution: 0
shadowProjection: 1
shadowCascades: 1
shadowDistance: 15
shadowNearPlaneOffset: 3
shadowCascade2Split: 0.33333334
shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
shadowmaskMode: 0
skinWeights: 1
textureQuality: 1
anisotropicTextures: 0
antiAliasing: 0
softParticles: 0
softVegetation: 0
realtimeReflectionProbes: 0
billboardsFaceCameraPosition: 0
vSyncCount: 0
lodBias: 0.3
maximumLODLevel: 0
streamingMipmapsActive: 0
streamingMipmapsAddAllCameras: 1
streamingMipmapsMemoryBudget: 512
streamingMipmapsRenderersPerFrame: 512
streamingMipmapsMaxLevelReduction: 2
streamingMipmapsMaxFileIORequests: 1024
particleRaycastBudget: 4
asyncUploadTimeSlice: 2
asyncUploadBufferSize: 16
asyncUploadPersistentBuffer: 1
resolutionScalingFixedDPIFactor: 1
customRenderPipeline: {fileID: 0}
excludedTargetPlatforms: []
- serializedVersion: 2
name: Low
pixelLightCount: 0
shadows: 0
shadowResolution: 0
shadowProjection: 1
shadowCascades: 1
shadowDistance: 20
shadowNearPlaneOffset: 3
shadowCascade2Split: 0.33333334
shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
shadowmaskMode: 0
skinWeights: 2
textureQuality: 0
anisotropicTextures: 0
antiAliasing: 0
softParticles: 0
softVegetation: 0
realtimeReflectionProbes: 0
billboardsFaceCameraPosition: 0
vSyncCount: 0
lodBias: 0.4
maximumLODLevel: 0
streamingMipmapsActive: 0
streamingMipmapsAddAllCameras: 1
streamingMipmapsMemoryBudget: 512
streamingMipmapsRenderersPerFrame: 512
streamingMipmapsMaxLevelReduction: 2
streamingMipmapsMaxFileIORequests: 1024
particleRaycastBudget: 16
asyncUploadTimeSlice: 2
asyncUploadBufferSize: 16
asyncUploadPersistentBuffer: 1
resolutionScalingFixedDPIFactor: 1
customRenderPipeline: {fileID: 0}
excludedTargetPlatforms: []
- serializedVersion: 2
name: Medium
pixelLightCount: 1
shadows: 1
shadowResolution: 0
shadowProjection: 1
shadowCascades: 1
shadowDistance: 20
shadowNearPlaneOffset: 3
shadowCascade2Split: 0.33333334
shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
shadowmaskMode: 0
skinWeights: 2
textureQuality: 0
anisotropicTextures: 1
antiAliasing: 0
softParticles: 0
softVegetation: 0
realtimeReflectionProbes: 0
billboardsFaceCameraPosition: 0
vSyncCount: 1
lodBias: 0.7
maximumLODLevel: 0
streamingMipmapsActive: 0
streamingMipmapsAddAllCameras: 1
streamingMipmapsMemoryBudget: 512
streamingMipmapsRenderersPerFrame: 512
streamingMipmapsMaxLevelReduction: 2
streamingMipmapsMaxFileIORequests: 1024
particleRaycastBudget: 64
asyncUploadTimeSlice: 2
asyncUploadBufferSize: 16
asyncUploadPersistentBuffer: 1
resolutionScalingFixedDPIFactor: 1
customRenderPipeline: {fileID: 0}
excludedTargetPlatforms: []
- serializedVersion: 2
name: High
pixelLightCount: 2
shadows: 2
shadowResolution: 1
shadowProjection: 1
shadowCascades: 2
shadowDistance: 40
shadowNearPlaneOffset: 3
shadowCascade2Split: 0.33333334
shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
shadowmaskMode: 1
skinWeights: 2
textureQuality: 0
anisotropicTextures: 1
antiAliasing: 0
softParticles: 0
softVegetation: 1
realtimeReflectionProbes: 1
billboardsFaceCameraPosition: 1
vSyncCount: 1
lodBias: 1
maximumLODLevel: 0
streamingMipmapsActive: 0
streamingMipmapsAddAllCameras: 1
streamingMipmapsMemoryBudget: 512
streamingMipmapsRenderersPerFrame: 512
streamingMipmapsMaxLevelReduction: 2
streamingMipmapsMaxFileIORequests: 1024
particleRaycastBudget: 256
asyncUploadTimeSlice: 2
asyncUploadBufferSize: 16
asyncUploadPersistentBuffer: 1
resolutionScalingFixedDPIFactor: 1
customRenderPipeline: {fileID: 0}
excludedTargetPlatforms: []
- serializedVersion: 2
name: Very High
pixelLightCount: 3
shadows: 2
shadowResolution: 2
shadowProjection: 1
shadowCascades: 2
shadowDistance: 70
shadowNearPlaneOffset: 3
shadowCascade2Split: 0.33333334
shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
shadowmaskMode: 1
skinWeights: 4
textureQuality: 0
anisotropicTextures: 2
antiAliasing: 2
softParticles: 1
softVegetation: 1
realtimeReflectionProbes: 1
billboardsFaceCameraPosition: 1
vSyncCount: 1
lodBias: 1.5
maximumLODLevel: 0
streamingMipmapsActive: 0
streamingMipmapsAddAllCameras: 1
streamingMipmapsMemoryBudget: 512
streamingMipmapsRenderersPerFrame: 512
streamingMipmapsMaxLevelReduction: 2
streamingMipmapsMaxFileIORequests: 1024
particleRaycastBudget: 1024
asyncUploadTimeSlice: 2
asyncUploadBufferSize: 16
asyncUploadPersistentBuffer: 1
resolutionScalingFixedDPIFactor: 1
customRenderPipeline: {fileID: 0}
excludedTargetPlatforms: []
- serializedVersion: 2
name: Ultra
pixelLightCount: 4
shadows: 2
shadowResolution: 2
shadowProjection: 1
shadowCascades: 4
shadowDistance: 150
shadowNearPlaneOffset: 3
shadowCascade2Split: 0.33333334
shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
shadowmaskMode: 1
skinWeights: 255
textureQuality: 0
anisotropicTextures: 2
antiAliasing: 2
softParticles: 1
softVegetation: 1
realtimeReflectionProbes: 1
billboardsFaceCameraPosition: 1
vSyncCount: 1
lodBias: 2
maximumLODLevel: 0
streamingMipmapsActive: 0
streamingMipmapsAddAllCameras: 1
streamingMipmapsMemoryBudget: 512
streamingMipmapsRenderersPerFrame: 512
streamingMipmapsMaxLevelReduction: 2
streamingMipmapsMaxFileIORequests: 1024
particleRaycastBudget: 4096
asyncUploadTimeSlice: 2
asyncUploadBufferSize: 16
asyncUploadPersistentBuffer: 1
resolutionScalingFixedDPIFactor: 1
customRenderPipeline: {fileID: 0}
excludedTargetPlatforms: []
m_PerPlatformDefaultQuality:
Android: 2
Lumin: 5
GameCoreScarlett: 5
GameCoreXboxOne: 5
Nintendo Switch: 5
PS4: 5
PS5: 5
Stadia: 5
Standalone: 5
WebGL: 3
Windows Store Apps: 5
XboxOne: 5
iPhone: 2
tvOS: 2
@@ -0,0 +1,121 @@
{
"templatePinStates": [],
"dependencyTypeInfos": [
{
"userAdded": false,
"type": "UnityEngine.AnimationClip",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEditor.Animations.AnimatorController",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEngine.AnimatorOverrideController",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEditor.Audio.AudioMixerController",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEngine.ComputeShader",
"defaultInstantiationMode": 1
},
{
"userAdded": false,
"type": "UnityEngine.Cubemap",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEngine.GameObject",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEditor.LightingDataAsset",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEngine.LightingSettings",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEngine.Material",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEditor.MonoScript",
"defaultInstantiationMode": 1
},
{
"userAdded": false,
"type": "UnityEngine.PhysicsMaterial",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEngine.PhysicsMaterial2D",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEngine.Rendering.PostProcessing.PostProcessProfile",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEngine.Rendering.PostProcessing.PostProcessResources",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEngine.Rendering.VolumeProfile",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEditor.SceneAsset",
"defaultInstantiationMode": 1
},
{
"userAdded": false,
"type": "UnityEngine.Shader",
"defaultInstantiationMode": 1
},
{
"userAdded": false,
"type": "UnityEngine.ShaderVariantCollection",
"defaultInstantiationMode": 1
},
{
"userAdded": false,
"type": "UnityEngine.Texture",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEngine.Texture2D",
"defaultInstantiationMode": 0
},
{
"userAdded": false,
"type": "UnityEngine.Timeline.TimelineAsset",
"defaultInstantiationMode": 0
}
],
"defaultDependencyTypeInfo": {
"userAdded": false,
"type": "<default_scene_template_dependencies>",
"defaultInstantiationMode": 1
},
"newSceneOverride": 0
}
@@ -0,0 +1,43 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!78 &1
TagManager:
serializedVersion: 2
tags: []
layers:
- Default
- TransparentFX
- Ignore Raycast
-
- Water
- UI
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
m_SortingLayers:
- name: Default
uniqueID: 0
locked: 0
@@ -0,0 +1,9 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!5 &1
TimeManager:
m_ObjectHideFlags: 0
Fixed Timestep: 0.02
Maximum Allowed Timestep: 0.33333334
m_TimeScale: 1
Maximum Particle Timestep: 0.03
@@ -0,0 +1,40 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!310 &1
UnityConnectSettings:
m_ObjectHideFlags: 0
serializedVersion: 1
m_Enabled: 0
m_TestMode: 0
m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events
m_EventUrl: https://cdp.cloud.unity3d.com/v1/events
m_ConfigUrl: https://config.uca.cloud.unity3d.com
m_DashboardUrl: https://dashboard.unity3d.com
m_TestInitMode: 0
InsightsSettings:
m_EngineDiagnosticsEnabled: 1
m_Enabled: 0
CrashReportingSettings:
serializedVersion: 2
m_EventUrl: https://perf-events.cloud.unity3d.com
m_EnableCloudDiagnosticsReporting: 0
m_LogBufferSize: 10
m_CaptureEditorExceptions: 1
UnityPurchasingSettings:
m_Enabled: 0
m_TestMode: 0
UnityAnalyticsSettings:
m_Enabled: 0
m_TestMode: 0
m_InitializeOnStartup: 1
m_PackageRequiringCoreStatsPresent: 0
UnityAdsSettings:
m_Enabled: 0
m_InitializeOnStartup: 1
m_TestMode: 0
m_IosGameId:
m_AndroidGameId:
m_GameIds: {}
m_GameId:
PerformanceReportingSettings:
m_Enabled: 0
@@ -0,0 +1,14 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!937362698 &1
VFXManager:
m_ObjectHideFlags: 0
m_IndirectShader: {fileID: 0}
m_CopyBufferShader: {fileID: 0}
m_SortShader: {fileID: 0}
m_StripUpdateShader: {fileID: 0}
m_RenderPipeSettingsPath:
m_FixedTimeStep: 0.016666668
m_MaxDeltaTime: 0.05
m_CompiledVersion: 0
m_RuntimeVersion: 0
@@ -0,0 +1,8 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!890905787 &1
VersionControlSettings:
m_ObjectHideFlags: 0
m_Mode: Visible Meta Files
m_CollabEditorSettings:
inProgressEnabled: 1
@@ -0,0 +1,10 @@
{
"m_SettingKeys": [
"VR Device Disabled",
"VR Device User Alert"
],
"m_SettingValues": [
"False",
"False"
]
}
+17
View File
@@ -0,0 +1,17 @@
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmarks", "Benchmarks.csproj", "{b6ce87c6-d606-93b9-b8b1-3b520c8d6bae}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{b6ce87c6-d606-93b9-b8b1-3b520c8d6bae}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{b6ce87c6-d606-93b9-b8b1-3b520c8d6bae}.Debug|Any CPU.Build.0 = Debug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
+75 -4
View File
@@ -1,28 +1,32 @@
package main
import (
"github.com/edmand46/arpack/generator"
"github.com/edmand46/arpack/parser"
"flag"
"fmt"
"log"
"os"
"path/filepath"
"strings"
"github.com/edmand46/arpack/generator"
"github.com/edmand46/arpack/parser"
)
func main() {
in := flag.String("in", "", "input Go file with struct definitions")
outGo := flag.String("out-go", "", "output directory for generated Go code")
outCS := flag.String("out-cs", "", "output directory for generated C# code")
outTS := flag.String("out-ts", "", "output directory for generated TypeScript code")
outLua := flag.String("out-lua", "", "output directory for generated Lua code")
namespace := flag.String("cs-namespace", "Arpack.Messages", "C# namespace")
flag.Parse()
if *in == "" {
log.Fatal("arpack: -in is required")
}
if *outGo == "" && *outCS == "" {
log.Fatal("arpack: at least one of -out-go or -out-cs is required")
if *outGo == "" && *outCS == "" && *outTS == "" && *outLua == "" {
log.Fatal("arpack: at least one of -out-go, -out-cs, -out-ts, or -out-lua is required")
}
schema, err := parser.ParseSchemaFile(*in)
@@ -41,6 +45,8 @@ func main() {
if pkgName == "." || pkgName == "" {
pkgName = msgs[0].PackageName
}
// Replace hyphens with underscores for valid Go package names
pkgName = strings.ReplaceAll(pkgName, "-", "_")
src, err := generator.GenerateGoSchema(schema, pkgName)
if err != nil {
@@ -74,8 +80,73 @@ func main() {
fmt.Printf("arpack: wrote %s\n", outPath)
}
if *outTS != "" {
src, err := generator.GenerateTypeScriptSchema(schema, "Arpack.Messages")
if err != nil {
log.Fatalf("arpack: TypeScript generation error: %v", err)
}
outPath := filepath.Join(*outTS, toTitle(baseName)+".gen.ts")
if err := os.MkdirAll(*outTS, 0755); err != nil {
log.Fatalf("arpack: mkdir %s: %v", *outTS, err)
}
if err := os.WriteFile(outPath, src, 0644); err != nil {
log.Fatalf("arpack: write %s: %v", outPath, err)
}
fmt.Printf("arpack: wrote %s\n", outPath)
}
if *outLua != "" {
src, err := generator.GenerateLuaSchema(schema, baseName)
if err != nil {
log.Fatalf("arpack: Lua generation error: %v", err)
}
// Use snake_case filename for Lua require() compatibility
outPath := filepath.Join(*outLua, toSnakeCase(baseName)+"_gen.lua")
if err := os.MkdirAll(*outLua, 0755); err != nil {
log.Fatalf("arpack: mkdir %s: %v", *outLua, err)
}
if err := os.WriteFile(outPath, src, 0644); err != nil {
log.Fatalf("arpack: write %s: %v", outPath, err)
}
fmt.Printf("arpack: wrote %s\n", outPath)
}
}
func toTitle(s string) string {
return strings.ToUpper(s[:1]) + strings.ToLower(s[1:])
}
func toSnakeCase(s string) string {
if s == "" {
return ""
}
var b strings.Builder
var prevUpper bool
for i, c := range s {
isUpper := c >= 'A' && c <= 'Z'
if i > 0 && isUpper {
nextLower := false
if i+1 < len(s) {
nextChar := rune(s[i+1])
nextLower = nextChar >= 'a' && nextChar <= 'z'
}
if !prevUpper || nextLower {
b.WriteByte('_')
}
}
b.WriteRune(c)
prevUpper = isUpper
}
return strings.ToLower(b.String())
}
+466 -43
View File
@@ -2,9 +2,6 @@ package e2e
import (
"bytes"
"github.com/edmand46/arpack/generator"
"github.com/edmand46/arpack/parser"
"fmt"
"math"
"os"
"os/exec"
@@ -12,16 +9,15 @@ import (
"strconv"
"strings"
"testing"
"github.com/edmand46/arpack/generator"
"github.com/edmand46/arpack/parser"
)
const samplePath = "../testdata/sample.go"
// TestE2E_CrossLanguage гоняет сериализацию в обе стороны: Go → C# и C# → Go.
// TestE2E_CrossLanguage
func TestE2E_CrossLanguage(t *testing.T) {
if _, err := exec.LookPath("dotnet"); err != nil {
t.Skip("dotnet not found, skipping cross-language e2e test")
}
schema, err := parser.ParseSchemaFile(samplePath)
if err != nil {
t.Fatalf("parse: %v", err)
@@ -32,13 +28,7 @@ func TestE2E_CrossLanguage(t *testing.T) {
t.Fatalf("GenerateGoSchema: %v", err)
}
csSrc, err := generator.GenerateCSharpSchema(schema, "Ragono.Messages")
if err != nil {
t.Fatalf("GenerateCSharpSchema: %v", err)
}
goDir := buildGoHarness(t, goSrc)
csDir := buildCSHarness(t, csSrc)
cases := []struct {
name string
@@ -51,34 +41,141 @@ func TestE2E_CrossLanguage(t *testing.T) {
{"EnvelopeMessage", "EnvelopeMessage", 0},
}
for _, tc := range cases {
t.Run("Go_to_CS/"+tc.name, func(t *testing.T) {
hex := runHarness(t, goDir, "go", "ser", tc.typ, "")
out := runHarness(t, csDir, "cs", "deser", tc.typ, hex)
checkOutput(t, tc.typ, out, tc.epsilon)
})
t.Run("CS_to_Go/"+tc.name, func(t *testing.T) {
hex := runHarness(t, csDir, "cs", "ser", tc.typ, "")
out := runHarness(t, goDir, "go", "deser", tc.typ, hex)
checkOutput(t, tc.typ, out, tc.epsilon)
})
if _, err := exec.LookPath("dotnet"); err == nil {
csSrc, err := generator.GenerateCSharpSchema(schema, "Ragono.Messages")
if err != nil {
t.Fatalf("GenerateCSharpSchema: %v", err)
}
csDir := buildCSHarness(t, csSrc)
for _, tc := range cases {
t.Run("Go_to_CS/"+tc.name, func(t *testing.T) {
hex := runHarness(t, goDir, "go", "ser", tc.typ, "")
out := runHarness(t, csDir, "cs", "deser", tc.typ, hex)
checkOutput(t, tc.typ, out, tc.epsilon)
})
t.Run("CS_to_Go/"+tc.name, func(t *testing.T) {
hex := runHarness(t, csDir, "cs", "ser", tc.typ, "")
out := runHarness(t, goDir, "go", "deser", tc.typ, hex)
checkOutput(t, tc.typ, out, tc.epsilon)
})
}
} else {
t.Log("dotnet not found, skipping C# cross-language e2e tests")
}
if _, err := exec.LookPath("node"); err == nil {
tsSrc, err := generator.GenerateTypeScriptSchema(schema, "Arpack.Messages")
if err != nil {
t.Fatalf("GenerateTypeScriptSchema: %v", err)
}
tsDir := buildTSHarness(t, tsSrc)
for _, tc := range cases {
t.Run("Go_to_TS/"+tc.name, func(t *testing.T) {
hex := runHarness(t, goDir, "go", "ser", tc.typ, "")
out := runHarness(t, tsDir, "ts", "deser", tc.typ, hex)
checkOutput(t, tc.typ, out, tc.epsilon)
})
t.Run("TS_to_Go/"+tc.name, func(t *testing.T) {
hex := runHarness(t, tsDir, "ts", "ser", tc.typ, "")
out := runHarness(t, goDir, "go", "deser", tc.typ, hex)
checkOutput(t, tc.typ, out, tc.epsilon)
})
}
} else {
t.Log("node not found, skipping TypeScript cross-language e2e tests")
}
if _, err := exec.LookPath("luajit"); err == nil {
// Use a simpler test schema without int64/uint64 for Lua
luaSchema := parser.Schema{
Messages: []parser.Message{
{
Name: "Vector3",
Fields: []parser.Field{
{Name: "X", Kind: parser.KindPrimitive, Primitive: parser.KindFloat32, Quant: &parser.QuantInfo{Min: -500, Max: 500, Bits: 16}},
{Name: "Y", Kind: parser.KindPrimitive, Primitive: parser.KindFloat32, Quant: &parser.QuantInfo{Min: -500, Max: 500, Bits: 16}},
{Name: "Z", Kind: parser.KindPrimitive, Primitive: parser.KindFloat32, Quant: &parser.QuantInfo{Min: -500, Max: 500, Bits: 16}},
},
},
{
Name: "MoveMessage",
Fields: []parser.Field{
{Name: "Position", Kind: parser.KindNested, TypeName: "Vector3"},
{Name: "Velocity", Kind: parser.KindFixedArray, FixedLen: 3, Elem: &parser.Field{Kind: parser.KindPrimitive, Primitive: parser.KindFloat32}},
{Name: "Waypoints", Kind: parser.KindSlice, Elem: &parser.Field{Kind: parser.KindNested, TypeName: "Vector3"}},
{Name: "PlayerID", Kind: parser.KindPrimitive, Primitive: parser.KindUint32},
{Name: "Active", Kind: parser.KindPrimitive, Primitive: parser.KindBool},
{Name: "Visible", Kind: parser.KindPrimitive, Primitive: parser.KindBool},
{Name: "Ghost", Kind: parser.KindPrimitive, Primitive: parser.KindBool},
{Name: "Name", Kind: parser.KindPrimitive, Primitive: parser.KindString},
},
},
{
Name: "EnvelopeMessage",
Fields: []parser.Field{
{Name: "Code", Kind: parser.KindPrimitive, Primitive: parser.KindUint16},
{Name: "Counter", Kind: parser.KindPrimitive, Primitive: parser.KindUint8},
},
},
},
Enums: []parser.Enum{
{
Name: "Opcode",
Primitive: parser.KindUint16,
Values: []parser.EnumValue{
{Name: "Unknown", Value: "0"},
{Name: "Join", Value: "1"},
{Name: "Leave", Value: "2"},
},
},
},
}
luaSrc, err := generator.GenerateLuaSchema(luaSchema, "messages")
if err != nil {
t.Fatalf("GenerateLuaSchema: %v", err)
}
luaDir := buildLuaHarness(t, luaSrc)
luaCases := []struct {
name string
typ string
epsilon float64
}{
{"Vector3", "Vector3", 0.02},
{"MoveMessage", "MoveMessage", 0.02},
{"EnvelopeMessage", "EnvelopeMessage", 0},
}
for _, tc := range luaCases {
t.Run("Go_to_Lua/"+tc.name, func(t *testing.T) {
hex := runHarness(t, goDir, "go", "ser", tc.typ, "")
out := runHarness(t, luaDir, "lua", "deser", tc.typ, hex)
checkOutput(t, tc.typ, out, tc.epsilon)
})
t.Run("Lua_to_Go/"+tc.name, func(t *testing.T) {
hex := runHarness(t, luaDir, "lua", "ser", tc.typ, "")
out := runHarness(t, goDir, "go", "deser", tc.typ, hex)
checkOutput(t, tc.typ, out, tc.epsilon)
})
}
} else {
t.Log("luajit not found, skipping Lua cross-language e2e tests")
}
}
// --- Build helpers ---
func buildGoHarness(t *testing.T, generatedSrc []byte) string {
t.Helper()
dir := t.TempDir()
// Читаем sample.go и меняем package на main
sampleSrc, err := os.ReadFile(samplePath)
if err != nil {
t.Fatalf("read sample: %v", err)
}
sampleSrc = bytes.Replace(sampleSrc, []byte("package messages"), []byte("package main"), 1)
// Generated код уже имеет package main (мы передали "main" в GenerateGo)
write(t, filepath.Join(dir, "messages.go"), sampleSrc)
write(t, filepath.Join(dir, "messages_arpack.go"), generatedSrc)
write(t, filepath.Join(dir, "main.go"), []byte(goHarnessSource))
@@ -100,23 +197,64 @@ func buildCSHarness(t *testing.T, generatedSrc []byte) string {
return dir
}
// --- Harness runners ---
func buildTSHarness(t *testing.T, generatedSrc []byte) string {
t.Helper()
dir := t.TempDir()
srcDir := filepath.Join(dir, "src")
if err := os.MkdirAll(srcDir, 0755); err != nil {
t.Fatalf("mkdir %s: %v", srcDir, err)
}
write(t, filepath.Join(srcDir, "messages.gen.ts"), generatedSrc)
write(t, filepath.Join(srcDir, "harness.ts"), []byte(tsHarnessSource))
write(t, filepath.Join(dir, "package.json"), []byte(tsPackageSource))
write(t, filepath.Join(dir, "tsconfig.json"), []byte(tsConfigSource))
mustRun(t, dir, "npm", "install")
mustRun(t, dir, "npx", "tsc")
return dir
}
func buildLuaHarness(t *testing.T, generatedSrc []byte) string {
t.Helper()
dir := t.TempDir()
write(t, filepath.Join(dir, "messages_gen.lua"), generatedSrc)
write(t, filepath.Join(dir, "harness.lua"), []byte(luaHarnessSource))
return dir
}
func runHarness(t *testing.T, dir, lang, op, typ, hexInput string) string {
t.Helper()
var cmd *exec.Cmd
if lang == "go" {
switch lang {
case "go":
args := []string{op, typ}
if hexInput != "" {
args = append(args, hexInput)
}
cmd = exec.Command(filepath.Join(dir, "harness"), args...)
} else {
case "cs":
args := []string{op, typ}
if hexInput != "" {
args = append(args, hexInput)
}
cmd = exec.Command("dotnet", append([]string{filepath.Join(dir, "out", "E2EHarness.dll")}, args...)...)
case "ts":
args := []string{op, typ}
if hexInput != "" {
args = append(args, hexInput)
}
cmd = exec.Command("node", append([]string{filepath.Join(dir, "dist", "harness.js")}, args...)...)
case "lua":
args := []string{filepath.Join(dir, "harness.lua"), op, typ}
if hexInput != "" {
args = append(args, hexInput)
}
cmd = exec.Command("luajit", args...)
}
cmd.Dir = dir
out, err := cmd.CombinedOutput()
@@ -126,9 +264,6 @@ func runHarness(t *testing.T, dir, lang, op, typ, hexInput string) string {
return strings.TrimSpace(string(out))
}
// --- Output verification ---
// checkOutput парсит key=value вывод и сравнивает с ожидаемыми значениями.
func checkOutput(t *testing.T, typ, output string, epsilon float64) {
t.Helper()
t.Logf("output for %s:\n%s", typ, output)
@@ -222,8 +357,6 @@ func assertStr(t *testing.T, kv map[string]string, key, want string) {
}
}
// --- Utilities ---
func write(t *testing.T, path string, data []byte) {
t.Helper()
if err := os.WriteFile(path, data, 0644); err != nil {
@@ -240,8 +373,6 @@ func mustRun(t *testing.T, dir string, name string, args ...string) {
}
}
// --- Go harness source ---
const goHarnessSource = `package main
import (
@@ -337,8 +468,6 @@ func main() {
}
`
// --- C# harness source ---
const csHarnessSource = `using System;
using System.Globalization;
using System.Text;
@@ -509,7 +638,7 @@ unsafe class Program
}
`
var csProjSource = fmt.Sprintf(`<Project Sdk="Microsoft.NET.Sdk">
var csProjSource = `<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
@@ -518,4 +647,298 @@ var csProjSource = fmt.Sprintf(`<Project Sdk="Microsoft.NET.Sdk">
<ImplicitUsings>disable</ImplicitUsings>
</PropertyGroup>
</Project>
`)
`
const tsPackageSource = `{
"name": "arpack-e2e-harness",
"version": "1.0.0",
"type": "module",
"scripts": {
"build": "tsc"
},
"devDependencies": {
"typescript": "^5.3.0",
"@types/node": "^20.0.0"
}
}
`
const tsConfigSource = `{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"lib": ["ES2022", "DOM"],
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
`
const tsHarnessSource = `import { readFileSync } from 'fs';
import { argv } from 'process';
// Import generated messages
import { Vector3, MoveMessage, SpawnMessage, EnvelopeMessage, Opcode } from './messages.gen.js';
// Hex encoding/decoding utilities
function encodeHex(data: Uint8Array): string {
return Array.from(data)
.map(b => b.toString(16).padStart(2, '0'))
.join('');
}
function decodeHex(hex: string): Uint8Array {
const bytes = new Uint8Array(hex.length / 2);
for (let i = 0; i < hex.length; i += 2) {
bytes[i / 2] = parseInt(hex.substr(i, 2), 16);
}
return bytes;
}
// Main harness
function main() {
const args = argv.slice(2);
const op = args[0]; // 'ser' or 'deser'
const typ = args[1]; // message type
const hexInput = args[2]; // for deser
switch (` + "`${op}:${typ}`" + `) {
case 'ser:Vector3': {
const msg = new Vector3();
msg.x = 123.45;
msg.y = -200.0;
msg.z = 0.0;
const buf = new ArrayBuffer(64);
const view = new DataView(buf);
const n = msg.serialize(view, 0);
const bytes = new Uint8Array(buf, 0, n);
console.log(encodeHex(bytes));
break;
}
case 'deser:Vector3': {
const data = decodeHex(hexInput);
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
const [msg] = Vector3.deserialize(view, 0);
console.log(` + "`X=${msg.x.toPrecision(9)}`" + `);
console.log(` + "`Y=${msg.y.toPrecision(9)}`" + `);
console.log(` + "`Z=${msg.z.toPrecision(9)}`" + `);
break;
}
case 'ser:SpawnMessage': {
const msg = new SpawnMessage();
msg.entityID = 42n;
msg.position = new Vector3();
msg.position.x = 10.0;
msg.position.y = 20.0;
msg.position.z = 30.0;
msg.health = -100;
msg.tags = ['hero', 'player'];
msg.data = [1, 2, 3];
const buf = new ArrayBuffer(512);
const view = new DataView(buf);
const n = msg.serialize(view, 0);
const bytes = new Uint8Array(buf, 0, n);
console.log(encodeHex(bytes));
break;
}
case 'deser:SpawnMessage': {
const data = decodeHex(hexInput);
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
const [msg] = SpawnMessage.deserialize(view, 0);
console.log(` + "`EntityID=${msg.entityID.toString()}`" + `);
console.log(` + "`Position.X=${msg.position.x.toPrecision(9)}`" + `);
console.log(` + "`Position.Y=${msg.position.y.toPrecision(9)}`" + `);
console.log(` + "`Position.Z=${msg.position.z.toPrecision(9)}`" + `);
console.log(` + "`Health=${msg.health}`" + `);
for (let i = 0; i < msg.tags.length; i++) {
console.log(` + "`Tags[${i}]=${msg.tags[i]}`" + `);
}
for (let i = 0; i < msg.data.length; i++) {
console.log(` + "`Data[${i}]=${msg.data[i]}`" + `);
}
break;
}
case 'ser:MoveMessage': {
const msg = new MoveMessage();
msg.position = new Vector3();
msg.position.x = 50.0;
msg.position.y = -100.0;
msg.position.z = 0.0;
msg.velocity = [1.5, -2.5, 0.0];
msg.waypoints = [new Vector3()];
msg.waypoints[0].x = 10.0;
msg.waypoints[0].y = 20.0;
msg.waypoints[0].z = 0.0;
msg.playerID = 777;
msg.active = true;
msg.visible = false;
msg.ghost = true;
msg.name = 'TestPlayer';
const buf = new ArrayBuffer(512);
const view = new DataView(buf);
const n = msg.serialize(view, 0);
const bytes = new Uint8Array(buf, 0, n);
console.log(encodeHex(bytes));
break;
}
case 'deser:MoveMessage': {
const data = decodeHex(hexInput);
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
const [msg] = MoveMessage.deserialize(view, 0);
console.log(` + "`PlayerID=${msg.playerID}`" + `);
console.log(` + "`Active=${msg.active.toString().toLowerCase()}`" + `);
console.log(` + "`Visible=${msg.visible.toString().toLowerCase()}`" + `);
console.log(` + "`Ghost=${msg.ghost.toString().toLowerCase()}`" + `);
console.log(` + "`Name=${msg.name}`" + `);
break;
}
case 'ser:EnvelopeMessage': {
const msg = new EnvelopeMessage();
msg.code = 2; // Opcode.JoinRoom
msg.counter = 7;
const buf = new ArrayBuffer(64);
const view = new DataView(buf);
const n = msg.serialize(view, 0);
const bytes = new Uint8Array(buf, 0, n);
console.log(encodeHex(bytes));
break;
}
case 'deser:EnvelopeMessage': {
const data = decodeHex(hexInput);
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
const [msg] = EnvelopeMessage.deserialize(view, 0);
console.log(` + "`Code=${msg.code}`" + `);
console.log(` + "`Counter=${msg.counter}`" + `);
break;
}
default:
console.error(` + "`Unknown op:type ${op}:${typ}`" + `);
process.exit(1);
}
}
main();
`
const luaHarnessSource = `-- Lua E2E Harness
-- Usage: luajit harness.lua <op> <type> [hex_input]
-- op: 'ser' or 'deser'
-- type: message type name
local messages = require("messages_gen")
local function hexToBytes(hex)
local bytes = {}
for i = 1, #hex, 2 do
local byte = tonumber(hex:sub(i, i+1), 16)
table.insert(bytes, string.char(byte))
end
return table.concat(bytes)
end
local function bytesToHex(data)
local hex = {}
for i = 1, #data do
table.insert(hex, string.format("%02x", string.byte(data, i)))
end
return table.concat(hex)
end
local function serializeVector3()
local msg = messages.new_vector3()
msg.x = 123.45
msg.y = -200.0
msg.z = 0.0
return bytesToHex(messages.serialize_vector3(msg))
end
local function deserializeVector3(hex)
local data = hexToBytes(hex)
local msg = messages.deserialize_vector3(data, 1)
print(string.format("X=%.10g", msg.x))
print(string.format("Y=%.10g", msg.y))
print(string.format("Z=%.10g", msg.z))
end
local function serializeMoveMessage()
local msg = messages.new_move_message()
msg.position = messages.new_vector3()
msg.position.x = 10.0
msg.position.y = 20.0
msg.position.z = 30.0
msg.velocity = {1.0, 2.0, 3.0}
msg.waypoints = {}
local wp = messages.new_vector3()
wp.x = 10.0
wp.y = 20.0
wp.z = 0.0
table.insert(msg.waypoints, wp)
msg.player_id = 777
msg.active = true
msg.visible = false
msg.ghost = true
msg.name = "TestPlayer"
return bytesToHex(messages.serialize_move_message(msg))
end
local function deserializeMoveMessage(hex)
local data = hexToBytes(hex)
local msg = messages.deserialize_move_message(data, 1)
print(string.format("PlayerID=%d", msg.player_id))
print(string.format("Active=%s", tostring(msg.active)))
print(string.format("Visible=%s", tostring(msg.visible)))
print(string.format("Ghost=%s", tostring(msg.ghost)))
print(string.format("Name=%s", msg.name))
end
local function serializeEnvelopeMessage()
local msg = messages.new_envelope_message()
msg.code = 2 -- Join
msg.counter = 7
return bytesToHex(messages.serialize_envelope_message(msg))
end
local function deserializeEnvelopeMessage(hex)
local data = hexToBytes(hex)
local msg = messages.deserialize_envelope_message(data, 1)
print(string.format("Code=%d", msg.code))
print(string.format("Counter=%d", msg.counter))
end
local op = arg[1]
local typ = arg[2]
local hexInput = arg[3]
local key = op .. ":" .. typ
if key == "ser:Vector3" then
print(serializeVector3())
elseif key == "deser:Vector3" then
deserializeVector3(hexInput)
elseif key == "ser:MoveMessage" then
print(serializeMoveMessage())
elseif key == "deser:MoveMessage" then
deserializeMoveMessage(hexInput)
elseif key == "ser:EnvelopeMessage" then
print(serializeEnvelopeMessage())
elseif key == "deser:EnvelopeMessage" then
deserializeEnvelopeMessage(hexInput)
else
error("Unknown op:type " .. key)
end
`
+3 -2
View File
@@ -1,9 +1,10 @@
package generator
import (
"github.com/edmand46/arpack/parser"
"fmt"
"strings"
"github.com/edmand46/arpack/parser"
)
func GenerateCSharp(messages []parser.Message, namespace string) ([]byte, error) {
@@ -455,7 +456,7 @@ func csharpEnumValueName(enumName, valueName string) string {
}
first := suffix[0]
if !((first >= 'A' && first <= 'Z') || (first >= '0' && first <= '9') || first == '_') {
if (first < 'A' || first > 'Z') && (first < '0' || first > '9') && first != '_' {
return valueName
}
+2 -1
View File
@@ -1,12 +1,13 @@
package generator
import (
"github.com/edmand46/arpack/parser"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
"github.com/edmand46/arpack/parser"
)
const samplePath = "../testdata/sample.go"
+2 -1
View File
@@ -1,10 +1,11 @@
package generator
import (
"github.com/edmand46/arpack/parser"
"fmt"
"go/format"
"strings"
"github.com/edmand46/arpack/parser"
)
func GenerateGo(messages []parser.Message, pkgName string) ([]byte, error) {
+776
View File
@@ -0,0 +1,776 @@
package generator
import (
"fmt"
"strings"
"github.com/edmand46/arpack/parser"
)
func GenerateLuaSchema(schema parser.Schema, moduleName string) ([]byte, error) {
if err := checkLuaUnsupportedTypes(schema); err != nil {
return nil, err
}
messages := schema.Messages
var b strings.Builder
b.WriteString("-- <auto-generated> arpack </auto-generated>\n")
b.WriteString("-- Code generated by arpack. DO NOT EDIT.\n\n")
b.WriteString("local M = {}\n\n")
b.WriteString("-- Load BitOp library for bit operations (Defold/LuaJIT)\n")
b.WriteString("local bit = require('bit')\n\n")
writeLuaHelpers(&b)
enumNames := make(map[string]struct{}, len(schema.Enums))
for _, enum := range schema.Enums {
enumNames[enum.Name] = struct{}{}
}
for _, enum := range schema.Enums {
writeLuaEnum(&b, enum)
b.WriteString("\n")
}
for _, msg := range messages {
writeLuaConstructor(&b, msg, enumNames)
b.WriteString("\n")
}
for _, msg := range messages {
if err := writeLuaSerializer(&b, msg, enumNames); err != nil {
return nil, fmt.Errorf("message %s: %w", msg.Name, err)
}
b.WriteString("\n")
}
for _, msg := range messages {
if err := writeLuaDeserializer(&b, msg, enumNames); err != nil {
return nil, fmt.Errorf("message %s: %w", msg.Name, err)
}
b.WriteString("\n")
}
b.WriteString("return M\n")
return []byte(b.String()), nil
}
func writeLuaHelpers(b *strings.Builder) {
b.WriteString("-- Inline helpers for little-endian byte operations\n\n")
b.WriteString("-- Error handling for truncated data\n")
b.WriteString("local function check_bounds(data, offset, needed, context)\n")
b.WriteString(" local available = #data - offset + 1\n")
b.WriteString(" if available < needed then\n")
b.WriteString(" error(string.format(\"arpack: buffer too short for %s: need %d bytes, have %d\", context, needed, available))\n")
b.WriteString(" end\n")
b.WriteString("end\n\n")
b.WriteString("local function read_u8(data, offset)\n")
b.WriteString(" if offset > #data then error(\"arpack: buffer too short for u8\") end\n")
b.WriteString(" return string.byte(data, offset), 1\n")
b.WriteString("end\n\n")
b.WriteString("local function write_u8(n)\n")
b.WriteString(" return string.char(n)\n")
b.WriteString("end\n\n")
b.WriteString("local function read_u16_le(data, offset)\n")
b.WriteString(" local b1, b2 = string.byte(data, offset, offset + 1)\n")
b.WriteString(" if not b2 then error(\"arpack: buffer too short for u16\") end\n")
b.WriteString(" return b1 + b2 * 256, 2\n")
b.WriteString("end\n\n")
b.WriteString("local function write_u16_le(n)\n")
b.WriteString(" return string.char(n % 256, math.floor(n / 256))\n")
b.WriteString("end\n\n")
b.WriteString("local function read_u32_le(data, offset)\n")
b.WriteString(" local b1, b2, b3, b4 = string.byte(data, offset, offset + 3)\n")
b.WriteString(" if not b4 then error(\"arpack: buffer too short for u32\") end\n")
b.WriteString(" return b1 + b2 * 256 + b3 * 65536 + b4 * 16777216, 4\n")
b.WriteString("end\n\n")
b.WriteString("local function write_u32_le(n)\n")
b.WriteString(" return string.char(\n")
b.WriteString(" n % 256,\n")
b.WriteString(" math.floor(n / 256) % 256,\n")
b.WriteString(" math.floor(n / 65536) % 256,\n")
b.WriteString(" math.floor(n / 16777216) % 256\n")
b.WriteString(" )\n")
b.WriteString("end\n\n")
b.WriteString("local function read_i8(data, offset)\n")
b.WriteString(" if offset > #data then error(\"arpack: buffer too short for i8\") end\n")
b.WriteString(" local v = string.byte(data, offset)\n")
b.WriteString(" if v >= 128 then v = v - 256 end\n")
b.WriteString(" return v, 1\n")
b.WriteString("end\n\n")
b.WriteString("local function write_i8(n)\n")
b.WriteString(" if n < 0 then n = n + 256 end\n")
b.WriteString(" return string.char(n)\n")
b.WriteString("end\n\n")
b.WriteString("local function read_i16_le(data, offset)\n")
b.WriteString(" local v = read_u16_le(data, offset)\n")
b.WriteString(" if v >= 32768 then v = v - 65536 end\n")
b.WriteString(" return v, 2\n")
b.WriteString("end\n\n")
b.WriteString("local function write_i16_le(n)\n")
b.WriteString(" if n < 0 then n = n + 65536 end\n")
b.WriteString(" return write_u16_le(n)\n")
b.WriteString("end\n\n")
b.WriteString("local function read_i32_le(data, offset)\n")
b.WriteString(" local v = read_u32_le(data, offset)\n")
b.WriteString(" if v >= 2147483648 then v = v - 4294967296 end\n")
b.WriteString(" return v, 4\n")
b.WriteString("end\n\n")
b.WriteString("local function write_i32_le(n)\n")
b.WriteString(" if n < 0 then n = n + 4294967296 end\n")
b.WriteString(" return write_u32_le(n)\n")
b.WriteString("end\n\n")
b.WriteString("local function read_f32_le(data, offset)\n")
b.WriteString(" local u32 = read_u32_le(data, offset)\n")
b.WriteString(" if u32 == 0 then return 0.0, 4 end\n")
b.WriteString(" local sign = (u32 >= 2147483648) and -1 or 1\n")
b.WriteString(" if sign < 0 then u32 = u32 - 2147483648 end\n")
b.WriteString(" local exp = math.floor(u32 / 8388608) % 256\n")
b.WriteString(" local mant = u32 % 8388608\n")
b.WriteString(" if exp == 0 then\n")
b.WriteString(" if mant == 0 then\n")
b.WriteString(" return sign < 0 and (-1 / math.huge) or 0.0, 4\n")
b.WriteString(" end\n")
b.WriteString(" return sign * (mant / 8388608) * math.pow(2, -126), 4\n")
b.WriteString(" elseif exp == 255 then\n")
b.WriteString(" if mant == 0 then return sign * math.huge, 4\n")
b.WriteString(" else return 0.0 / 0.0, 4 end\n")
b.WriteString(" end\n")
b.WriteString(" return sign * (1 + mant / 8388608) * math.pow(2, exp - 127), 4\n")
b.WriteString("end\n\n")
b.WriteString("local function write_f32_le(n)\n")
b.WriteString(" if n ~= n then return write_u32_le(2143289344) end\n")
b.WriteString(" if n == math.huge then return write_u32_le(2139095040) end\n")
b.WriteString(" if n == -math.huge then return write_u32_le(4286578688) end\n")
b.WriteString(" -- Check for negative zero: 1/-0.0 == -math.huge\n")
b.WriteString(" if n == 0 then\n")
b.WriteString(" if 1/n == -math.huge then return write_u32_le(2147483648) end\n")
b.WriteString(" return write_u32_le(0)\n")
b.WriteString(" end\n")
b.WriteString(" local sign = 0\n")
b.WriteString(" if n < 0 then sign = 2147483648; n = -n end\n")
b.WriteString(" local exp\n")
b.WriteString(" local mant\n")
b.WriteString(" if n < math.pow(2, -126) then\n")
b.WriteString(" mant = math.floor(n / math.pow(2, -149) + 0.5)\n")
b.WriteString(" if mant <= 0 then return write_u32_le(sign) end\n")
b.WriteString(" if mant >= 8388608 then\n")
b.WriteString(" exp = 1\n")
b.WriteString(" mant = 0\n")
b.WriteString(" else\n")
b.WriteString(" exp = 0\n")
b.WriteString(" end\n")
b.WriteString(" else\n")
b.WriteString(" exp = math.floor(math.log(n, 2))\n")
b.WriteString(" mant = math.floor((n / math.pow(2, exp) - 1) * 8388608 + 0.5)\n")
b.WriteString(" if mant >= 8388608 then\n")
b.WriteString(" exp = exp + 1\n")
b.WriteString(" mant = 0\n")
b.WriteString(" end\n")
b.WriteString(" exp = exp + 127\n")
b.WriteString(" if exp >= 255 then\n")
b.WriteString(" return write_u32_le(sign + 2139095040)\n")
b.WriteString(" end\n")
b.WriteString(" end\n")
b.WriteString(" return write_u32_le(sign + exp * 8388608 + mant)\n")
b.WriteString("end\n\n")
b.WriteString("local function read_f64_le(data, offset)\n")
b.WriteString(" -- Read 8 bytes directly to avoid precision loss from 64-bit arithmetic\n")
b.WriteString(" local b1, b2, b3, b4, b5, b6, b7, b8 = string.byte(data, offset, offset + 7)\n")
b.WriteString(" if not b8 then error(\"arpack: buffer too short for f64\") end\n")
b.WriteString(" local low = b1 + b2 * 256 + b3 * 65536 + b4 * 16777216\n")
b.WriteString(" local high = b5 + b6 * 256 + b7 * 65536 + b8 * 16777216\n")
b.WriteString(" -- Decode IEEE 754 double from low/high parts separately\n")
b.WriteString(" if low == 0 and high == 0 then return 0.0, 8 end\n")
b.WriteString(" local sign = (high >= 2147483648) and -1 or 1\n")
b.WriteString(" if sign < 0 then high = high - 2147483648 end\n")
b.WriteString(" local exp = math.floor(high / 1048576) % 2048\n")
b.WriteString(" local high_mant = high % 1048576\n")
b.WriteString(" if exp == 0 then\n")
b.WriteString(" local mant = high_mant * 4294967296 + low\n")
b.WriteString(" if mant == 0 then\n")
b.WriteString(" return sign < 0 and (-1 / math.huge) or 0.0, 8\n")
b.WriteString(" end\n")
b.WriteString(" return sign * (mant / 4503599627370496) * math.pow(2, -1022), 8\n")
b.WriteString(" elseif exp == 2047 then\n")
b.WriteString(" if high_mant == 0 and low == 0 then return sign * math.huge, 8\n")
b.WriteString(" else return 0.0 / 0.0, 8 end\n")
b.WriteString(" end\n")
b.WriteString(" local mant = high_mant * 4294967296 + low\n")
b.WriteString(" return sign * (1 + mant / 4503599627370496) * math.pow(2, exp - 1023), 8\n")
b.WriteString("end\n\n")
b.WriteString("local function write_f64_le(n)\n")
b.WriteString(" -- Handle special values\n")
b.WriteString(" if n ~= n then -- NaN\n")
b.WriteString(" return string.char(0, 0, 0, 0, 0, 0, 248, 127)\n")
b.WriteString(" end\n")
b.WriteString(" if n == math.huge then\n")
b.WriteString(" return string.char(0, 0, 0, 0, 0, 0, 240, 127)\n")
b.WriteString(" end\n")
b.WriteString(" if n == -math.huge then\n")
b.WriteString(" return string.char(0, 0, 0, 0, 0, 0, 240, 255)\n")
b.WriteString(" end\n")
b.WriteString(" -- Check for negative zero: 1/-0.0 == -math.huge\n")
b.WriteString(" if n == 0 then\n")
b.WriteString(" if 1/n == -math.huge then\n")
b.WriteString(" return string.char(0, 0, 0, 0, 0, 0, 0, 128)\n")
b.WriteString(" end\n")
b.WriteString(" return string.char(0, 0, 0, 0, 0, 0, 0, 0)\n")
b.WriteString(" end\n")
b.WriteString(" local sign = 0\n")
b.WriteString(" if n < 0 then sign = 2147483648; n = -n end\n")
b.WriteString(" local exp\n")
b.WriteString(" local mant\n")
b.WriteString(" if n < math.pow(2, -1022) then\n")
b.WriteString(" mant = math.floor(n / math.pow(2, -1074) + 0.5)\n")
b.WriteString(" if mant <= 0 then\n")
b.WriteString(" local high = sign\n")
b.WriteString(" return string.char(0, 0, 0, 0, high % 256, math.floor(high / 256) % 256, math.floor(high / 65536) % 256, math.floor(high / 16777216) % 256)\n")
b.WriteString(" end\n")
b.WriteString(" if mant >= 4503599627370496 then\n")
b.WriteString(" exp = 1\n")
b.WriteString(" mant = 0\n")
b.WriteString(" else\n")
b.WriteString(" exp = 0\n")
b.WriteString(" end\n")
b.WriteString(" else\n")
b.WriteString(" exp = math.floor(math.log(n, 2))\n")
b.WriteString(" mant = (n / math.pow(2, exp) - 1) * 4503599627370496\n")
b.WriteString(" mant = math.floor(mant + 0.5)\n")
b.WriteString(" if mant >= 4503599627370496 then\n")
b.WriteString(" exp = exp + 1\n")
b.WriteString(" mant = 0\n")
b.WriteString(" end\n")
b.WriteString(" exp = exp + 1023\n")
b.WriteString(" if exp >= 2047 then\n")
b.WriteString(" exp = 2047\n")
b.WriteString(" mant = 0\n")
b.WriteString(" end\n")
b.WriteString(" end\n")
b.WriteString(" local high_mant = math.floor(mant / 4294967296)\n")
b.WriteString(" local low = mant % 4294967296\n")
b.WriteString(" local high = sign + exp * 1048576 + high_mant\n")
b.WriteString(" return string.char(\n")
b.WriteString(" low % 256,\n")
b.WriteString(" math.floor(low / 256) % 256,\n")
b.WriteString(" math.floor(low / 65536) % 256,\n")
b.WriteString(" math.floor(low / 16777216) % 256,\n")
b.WriteString(" high % 256,\n")
b.WriteString(" math.floor(high / 256) % 256,\n")
b.WriteString(" math.floor(high / 65536) % 256,\n")
b.WriteString(" math.floor(high / 16777216) % 256\n")
b.WriteString(" )\n")
b.WriteString("end\n\n")
b.WriteString("local function read_bool(data, offset)\n")
b.WriteString(" if offset > #data then error(\"arpack: buffer too short for bool\") end\n")
b.WriteString(" return string.byte(data, offset) ~= 0, 1\n")
b.WriteString("end\n\n")
b.WriteString("local function write_bool(v)\n")
b.WriteString(" return string.char(v and 1 or 0)\n")
b.WriteString("end\n\n")
b.WriteString("local function read_string(data, offset)\n")
b.WriteString(" local len, header_bytes = read_u16_le(data, offset)\n")
b.WriteString(" if len == 0 then return '', header_bytes end\n")
b.WriteString(" local available = #data - offset - header_bytes + 1\n")
b.WriteString(" if available < len then\n")
b.WriteString(" error(string.format(\"arpack: buffer too short for string: need %d bytes, have %d\", len, available))\n")
b.WriteString(" end\n")
b.WriteString(" -- string.sub is 1-based; data starts at offset + header_bytes\n")
b.WriteString(" return string.sub(data, offset + header_bytes, offset + header_bytes + len - 1), header_bytes + len\n")
b.WriteString("end\n\n")
b.WriteString("local function write_string(s)\n")
b.WriteString(" local len = #s\n")
b.WriteString(" return write_u16_le(len) .. s\n")
b.WriteString("end\n\n")
}
func writeLuaEnum(b *strings.Builder, enum parser.Enum) {
fmt.Fprintf(b, "M.%s = {\n", enum.Name)
for i, value := range enum.Values {
fmt.Fprintf(b, " %s = %s", value.Name, value.Value)
if i < len(enum.Values)-1 {
b.WriteString(",")
}
b.WriteString("\n")
}
b.WriteString("}\n")
}
func writeLuaConstructor(b *strings.Builder, msg parser.Message, enumNames map[string]struct{}) {
fmt.Fprintf(b, "function M.new_%s()\n", toSnakeCase(msg.Name))
b.WriteString(" return {\n")
for _, f := range msg.Fields {
defaultValue := luaDefaultValue(f, enumNames)
fmt.Fprintf(b, " %s = %s,\n", luaFieldName(f.Name), defaultValue)
}
b.WriteString(" }\n")
b.WriteString("end\n")
}
func writeLuaSerializer(b *strings.Builder, msg parser.Message, enumNames map[string]struct{}) error {
segs := segmentFields(msg.Fields)
fmt.Fprintf(b, "function M.serialize_%s(msg)\n", toSnakeCase(msg.Name))
b.WriteString(" local parts = {}\n")
b.WriteString(" local part_idx = 0\n")
for i, seg := range segs {
if seg.single != nil {
if err := writeLuaSerializeField(b, "msg", *seg.single, " ", enumNames); err != nil {
return err
}
} else {
writeLuaBoolGroupSerialize(b, "msg", seg.bools, i, " ")
}
}
b.WriteString(" return table.concat(parts)\n")
b.WriteString("end\n")
return nil
}
func writeLuaDeserializer(b *strings.Builder, msg parser.Message, enumNames map[string]struct{}) error {
segs := segmentFields(msg.Fields)
minSize := packedMinWireSize(msg.Fields)
fmt.Fprintf(b, "function M.deserialize_%s(data, offset)\n", toSnakeCase(msg.Name))
b.WriteString(" offset = offset or 1\n")
fmt.Fprintf(b, " local msg = M.new_%s()\n", toSnakeCase(msg.Name))
b.WriteString(" local start_offset = offset\n")
b.WriteString(" local bytes_read = 0\n")
fmt.Fprintf(b, " if #data < offset + %d - 1 then\n", minSize)
fmt.Fprintf(b, " error(\"arpack: buffer too short for %s\")\n", msg.Name)
b.WriteString(" end\n")
for i, seg := range segs {
if seg.single != nil {
if err := writeLuaDeserializeField(b, "msg", *seg.single, " ", enumNames); err != nil {
return err
}
} else {
writeLuaBoolGroupDeserialize(b, "msg", seg.bools, i, " ")
}
}
b.WriteString(" return msg, offset - start_offset\n")
b.WriteString("end\n")
return nil
}
func writeLuaBoolGroupSerialize(b *strings.Builder, recv string, bools []parser.Field, groupIdx int, indent string) {
varName := fmt.Sprintf("_bool_byte_%d", groupIdx)
fmt.Fprintf(b, "%slocal %s = 0\n", indent, varName)
for bit, f := range bools {
fmt.Fprintf(b, "%sif %s.%s then %s = bit.bor(%s, %d) end\n",
indent, recv, luaFieldName(f.Name), varName, varName, 1<<bit)
}
fmt.Fprintf(b, "%spart_idx = part_idx + 1; parts[part_idx] = write_u8(%s)\n", indent, varName)
}
func writeLuaBoolGroupDeserialize(b *strings.Builder, recv string, bools []parser.Field, groupIdx int, indent string) {
varName := fmt.Sprintf("_bool_byte_%d", groupIdx)
fmt.Fprintf(b, "%sif #data < offset then error(\"arpack: buffer too short for bool group\") end\n", indent)
fmt.Fprintf(b, "%slocal %s = string.byte(data, offset)\n", indent, varName)
fmt.Fprintf(b, "%soffset = offset + 1\n", indent)
for bit, f := range bools {
fmt.Fprintf(b, "%s%s.%s = bit.band(%s, %d) ~= 0\n",
indent, recv, luaFieldName(f.Name), varName, 1<<bit)
}
}
func writeLuaSerializeField(b *strings.Builder, recv string, f parser.Field, indent string, enumNames map[string]struct{}) error {
access := recv + "." + luaFieldName(f.Name)
switch f.Kind {
case parser.KindPrimitive:
return writeLuaSerializePrimitive(b, access, f, indent, enumNames)
case parser.KindNested:
fmt.Fprintf(b, "%slocal _nested_%s = M.serialize_%s(%s)\n", indent, f.Name, toSnakeCase(f.TypeName), access)
fmt.Fprintf(b, "%spart_idx = part_idx + 1; parts[part_idx] = _nested_%s\n", indent, f.Name)
case parser.KindFixedArray:
iVar := "_i_" + strings.ToLower(f.Name)
fmt.Fprintf(b, "%sfor %s = 1, %d do\n", indent, iVar, f.FixedLen)
elemField := parser.Field{
Name: f.Name + "[" + iVar + "]",
Kind: f.Elem.Kind,
Primitive: f.Elem.Primitive,
NamedType: f.Elem.NamedType,
Quant: f.Elem.Quant,
TypeName: f.Elem.TypeName,
Elem: f.Elem.Elem,
FixedLen: f.Elem.FixedLen,
}
if err := writeLuaSerializeField(b, recv, elemField, indent+" ", enumNames); err != nil {
return err
}
fmt.Fprintf(b, "%send\n", indent)
case parser.KindSlice:
lenVar := "_len_" + strings.ToLower(f.Name)
fmt.Fprintf(b, "%slocal %s = #(%s or {})\n", indent, lenVar, access)
fmt.Fprintf(b, "%spart_idx = part_idx + 1; parts[part_idx] = write_u16_le(%s)\n", indent, lenVar)
iVar := "_i_" + strings.ToLower(f.Name)
fmt.Fprintf(b, "%sfor %s = 1, %s do\n", indent, iVar, lenVar)
if f.Elem.Kind == parser.KindNested {
// For nested types in slices, serialize directly
fmt.Fprintf(b, "%slocal _nested_%s = M.serialize_%s(%s[%s])\n",
indent, f.Name, toSnakeCase(f.Elem.TypeName), access, iVar)
fmt.Fprintf(b, "%spart_idx = part_idx + 1; parts[part_idx] = _nested_%s\n",
indent, f.Name)
} else {
elemField := parser.Field{
Name: f.Name + "[" + iVar + "]",
Kind: f.Elem.Kind,
Primitive: f.Elem.Primitive,
NamedType: f.Elem.NamedType,
Quant: f.Elem.Quant,
TypeName: f.Elem.TypeName,
Elem: f.Elem.Elem,
FixedLen: f.Elem.FixedLen,
}
if err := writeLuaSerializeField(b, recv, elemField, indent+" ", enumNames); err != nil {
return err
}
}
fmt.Fprintf(b, "%send\n", indent)
}
return nil
}
func writeLuaSerializePrimitive(b *strings.Builder, access string, f parser.Field, indent string, enumNames map[string]struct{}) error {
if f.Quant != nil {
return writeLuaSerializeQuant(b, access, f, indent)
}
valueExpr := luaSerializeValueExpr(access, f, enumNames)
switch f.Primitive {
case parser.KindFloat32:
fmt.Fprintf(b, "%spart_idx = part_idx + 1; parts[part_idx] = write_f32_le(%s)\n", indent, valueExpr)
case parser.KindFloat64:
fmt.Fprintf(b, "%spart_idx = part_idx + 1; parts[part_idx] = write_f64_le(%s)\n", indent, valueExpr)
case parser.KindInt8:
fmt.Fprintf(b, "%spart_idx = part_idx + 1; parts[part_idx] = write_i8(%s)\n", indent, valueExpr)
case parser.KindUint8:
fmt.Fprintf(b, "%spart_idx = part_idx + 1; parts[part_idx] = write_u8(%s)\n", indent, valueExpr)
case parser.KindBool:
fmt.Fprintf(b, "%spart_idx = part_idx + 1; parts[part_idx] = write_bool(%s)\n", indent, valueExpr)
case parser.KindInt16:
fmt.Fprintf(b, "%spart_idx = part_idx + 1; parts[part_idx] = write_i16_le(%s)\n", indent, valueExpr)
case parser.KindUint16:
fmt.Fprintf(b, "%spart_idx = part_idx + 1; parts[part_idx] = write_u16_le(%s)\n", indent, valueExpr)
case parser.KindInt32:
fmt.Fprintf(b, "%spart_idx = part_idx + 1; parts[part_idx] = write_i32_le(%s)\n", indent, valueExpr)
case parser.KindUint32:
fmt.Fprintf(b, "%spart_idx = part_idx + 1; parts[part_idx] = write_u32_le(%s)\n", indent, valueExpr)
case parser.KindInt64, parser.KindUint64:
return fmt.Errorf("int64/uint64 serialization not supported in Lua")
case parser.KindString:
fmt.Fprintf(b, "%spart_idx = part_idx + 1; parts[part_idx] = write_string(%s or '')\n", indent, valueExpr)
}
return nil
}
func writeLuaSerializeQuant(b *strings.Builder, access string, f parser.Field, indent string) error {
q := f.Quant
maxUint := q.MaxUint()
varName := "_q_" + sanitizeLuaVarName(access)
fmt.Fprintf(b, "%slocal %s = math.floor(((%s - (%g)) / (%g - (%g))) * %g + 0.5)\n",
indent, varName, access, q.Min, q.Max, q.Min, maxUint)
if q.Bits == 8 {
fmt.Fprintf(b, "%spart_idx = part_idx + 1; parts[part_idx] = write_u8(%s)\n", indent, varName)
} else {
fmt.Fprintf(b, "%spart_idx = part_idx + 1; parts[part_idx] = write_u16_le(%s)\n", indent, varName)
}
return nil
}
func writeLuaDeserializeField(b *strings.Builder, recv string, f parser.Field, indent string, enumNames map[string]struct{}) error {
access := recv + "." + luaFieldName(f.Name)
switch f.Kind {
case parser.KindPrimitive:
return writeLuaDeserializePrimitive(b, access, f, indent, enumNames)
case parser.KindNested:
fmt.Fprintf(b, "%slocal _nested_%s, _n_%s = M.deserialize_%s(data, offset)\n", indent, f.Name, f.Name, toSnakeCase(f.TypeName))
fmt.Fprintf(b, "%s%s = _nested_%s\n", indent, access, f.Name)
fmt.Fprintf(b, "%soffset = offset + _n_%s\n", indent, f.Name)
case parser.KindFixedArray:
iVar := "_i_" + strings.ToLower(f.Name)
fmt.Fprintf(b, "%s%s = {}\n", indent, access)
fmt.Fprintf(b, "%sfor %s = 1, %d do\n", indent, iVar, f.FixedLen)
elemField := parser.Field{
Name: f.Name + "[" + iVar + "]",
Kind: f.Elem.Kind,
Primitive: f.Elem.Primitive,
NamedType: f.Elem.NamedType,
Quant: f.Elem.Quant,
TypeName: f.Elem.TypeName,
Elem: f.Elem.Elem,
FixedLen: f.Elem.FixedLen,
}
if err := writeLuaDeserializeField(b, recv, elemField, indent+" ", enumNames); err != nil {
return err
}
fmt.Fprintf(b, "%send\n", indent)
case parser.KindSlice:
lenVar := "_len_" + strings.ToLower(f.Name)
fmt.Fprintf(b, "%slocal %s = read_u16_le(data, offset)\n", indent, lenVar)
fmt.Fprintf(b, "%soffset = offset + 2\n", indent)
fmt.Fprintf(b, "%s%s = {}\n", indent, access)
iVar := "_i_" + strings.ToLower(f.Name)
fmt.Fprintf(b, "%sfor %s = 1, %s do\n", indent, iVar, lenVar)
if f.Elem.Kind == parser.KindNested {
// For nested types in slices, deserialize directly
fmt.Fprintf(b, "%slocal _nested_%s, _n_%s = M.deserialize_%s(data, offset)\n",
indent, f.Name, f.Name, toSnakeCase(f.Elem.TypeName))
fmt.Fprintf(b, "%s%s[%s] = _nested_%s\n",
indent, access, iVar, f.Name)
fmt.Fprintf(b, "%soffset = offset + _n_%s\n",
indent, f.Name)
} else {
elemField := parser.Field{
Name: f.Name + "[" + iVar + "]",
Kind: f.Elem.Kind,
Primitive: f.Elem.Primitive,
NamedType: f.Elem.NamedType,
Quant: f.Elem.Quant,
TypeName: f.Elem.TypeName,
Elem: f.Elem.Elem,
FixedLen: f.Elem.FixedLen,
}
if err := writeLuaDeserializeField(b, recv, elemField, indent+" ", enumNames); err != nil {
return err
}
}
fmt.Fprintf(b, "%send\n", indent)
}
return nil
}
func writeLuaDeserializePrimitive(b *strings.Builder, access string, f parser.Field, indent string, enumNames map[string]struct{}) error {
if f.Quant != nil {
return writeLuaDeserializeQuant(b, access, f, indent, enumNames)
}
varName := "_v_" + sanitizeLuaVarName(access)
switch f.Primitive {
case parser.KindFloat32:
fmt.Fprintf(b, "%slocal %s, _n = read_f32_le(data, offset)\n", indent, varName)
fmt.Fprintf(b, "%s%s = %s\n", indent, access, luaDeserializeValueExpr(varName, f, enumNames))
fmt.Fprintf(b, "%soffset = offset + _n\n", indent)
case parser.KindFloat64:
fmt.Fprintf(b, "%slocal %s, _n = read_f64_le(data, offset)\n", indent, varName)
fmt.Fprintf(b, "%s%s = %s\n", indent, access, luaDeserializeValueExpr(varName, f, enumNames))
fmt.Fprintf(b, "%soffset = offset + _n\n", indent)
case parser.KindInt8:
fmt.Fprintf(b, "%slocal %s, _n = read_i8(data, offset)\n", indent, varName)
fmt.Fprintf(b, "%s%s = %s\n", indent, access, luaDeserializeValueExpr(varName, f, enumNames))
fmt.Fprintf(b, "%soffset = offset + _n\n", indent)
case parser.KindUint8:
fmt.Fprintf(b, "%slocal %s, _n = read_u8(data, offset)\n", indent, varName)
fmt.Fprintf(b, "%s%s = %s\n", indent, access, luaDeserializeValueExpr(varName, f, enumNames))
fmt.Fprintf(b, "%soffset = offset + _n\n", indent)
case parser.KindBool:
fmt.Fprintf(b, "%slocal %s, _n = read_bool(data, offset)\n", indent, varName)
fmt.Fprintf(b, "%s%s = %s\n", indent, access, luaDeserializeValueExpr(varName, f, enumNames))
fmt.Fprintf(b, "%soffset = offset + _n\n", indent)
case parser.KindInt16:
fmt.Fprintf(b, "%slocal %s, _n = read_i16_le(data, offset)\n", indent, varName)
fmt.Fprintf(b, "%s%s = %s\n", indent, access, luaDeserializeValueExpr(varName, f, enumNames))
fmt.Fprintf(b, "%soffset = offset + _n\n", indent)
case parser.KindUint16:
fmt.Fprintf(b, "%slocal %s, _n = read_u16_le(data, offset)\n", indent, varName)
fmt.Fprintf(b, "%s%s = %s\n", indent, access, luaDeserializeValueExpr(varName, f, enumNames))
fmt.Fprintf(b, "%soffset = offset + _n\n", indent)
case parser.KindInt32:
fmt.Fprintf(b, "%slocal %s, _n = read_i32_le(data, offset)\n", indent, varName)
fmt.Fprintf(b, "%s%s = %s\n", indent, access, luaDeserializeValueExpr(varName, f, enumNames))
fmt.Fprintf(b, "%soffset = offset + _n\n", indent)
case parser.KindUint32:
fmt.Fprintf(b, "%slocal %s, _n = read_u32_le(data, offset)\n", indent, varName)
fmt.Fprintf(b, "%s%s = %s\n", indent, access, luaDeserializeValueExpr(varName, f, enumNames))
fmt.Fprintf(b, "%soffset = offset + _n\n", indent)
case parser.KindInt64, parser.KindUint64:
return fmt.Errorf("int64/uint64 deserialization not supported in Lua")
case parser.KindString:
fmt.Fprintf(b, "%slocal %s, _n = read_string(data, offset)\n", indent, varName)
fmt.Fprintf(b, "%s%s = %s\n", indent, access, luaDeserializeValueExpr(varName, f, enumNames))
fmt.Fprintf(b, "%soffset = offset + _n\n", indent)
}
return nil
}
func writeLuaDeserializeQuant(b *strings.Builder, access string, f parser.Field, indent string, enumNames map[string]struct{}) error {
q := f.Quant
maxUint := q.MaxUint()
varName := "_q_" + sanitizeLuaVarName(access)
if q.Bits == 8 {
fmt.Fprintf(b, "%slocal %s = read_u8(data, offset)\n", indent, varName)
fmt.Fprintf(b, "%soffset = offset + 1\n", indent)
} else {
fmt.Fprintf(b, "%slocal %s = read_u16_le(data, offset)\n", indent, varName)
fmt.Fprintf(b, "%soffset = offset + 2\n", indent)
}
expr := fmt.Sprintf("%s / %g * (%g - (%g)) + (%g)", varName, maxUint, q.Max, q.Min, q.Min)
fmt.Fprintf(b, "%s%s = %s\n", indent, access, luaDeserializeValueExpr(expr, f, enumNames))
return nil
}
func luaFieldName(name string) string {
return toSnakeCase(name)
}
func toSnakeCase(s string) string {
if s == "" {
return ""
}
var b strings.Builder
var prevUpper bool
for i, c := range s {
isUpper := c >= 'A' && c <= 'Z'
// Add underscore before uppercase letter if:
// - It's not the first character
// - Previous character was lowercase, OR
// - Previous character was uppercase AND next character (if exists) is lowercase
// (this handles cases like "PlayerID" -> "player_id", not "player_i_d")
if i > 0 && isUpper {
nextLower := false
if i+1 < len(s) {
nextChar := rune(s[i+1])
nextLower = nextChar >= 'a' && nextChar <= 'z'
}
if !prevUpper || nextLower {
b.WriteByte('_')
}
}
b.WriteRune(c)
prevUpper = isUpper
}
return strings.ToLower(b.String())
}
func luaDefaultValue(f parser.Field, enumNames map[string]struct{}) string {
switch f.Kind {
case parser.KindPrimitive:
if luaIsEnumType(f, enumNames) {
return "0"
}
switch f.Primitive {
case parser.KindFloat32, parser.KindFloat64, parser.KindInt8, parser.KindInt16, parser.KindInt32,
parser.KindUint8, parser.KindUint16, parser.KindUint32, parser.KindInt64, parser.KindUint64:
return "0"
case parser.KindBool:
return "false"
case parser.KindString:
return "''"
}
case parser.KindNested:
return fmt.Sprintf("M.new_%s()", toSnakeCase(f.TypeName))
case parser.KindFixedArray, parser.KindSlice:
return "{}"
}
return "nil"
}
func luaTypeName(f parser.Field, enumNames map[string]struct{}) string {
switch f.Kind {
case parser.KindPrimitive:
if luaIsEnumType(f, enumNames) {
return "number"
}
return "number"
case parser.KindNested:
return f.TypeName
case parser.KindFixedArray, parser.KindSlice:
return "table"
}
return "any"
}
func luaSerializeValueExpr(access string, f parser.Field, enumNames map[string]struct{}) string {
if !luaIsEnumType(f, enumNames) {
return access
}
return access
}
func luaDeserializeValueExpr(expr string, f parser.Field, enumNames map[string]struct{}) string {
if !luaIsEnumType(f, enumNames) {
return expr
}
return expr
}
func luaIsEnumType(f parser.Field, enumNames map[string]struct{}) bool {
if f.NamedType == "" || enumNames == nil {
return false
}
_, ok := enumNames[f.NamedType]
return ok
}
func sanitizeLuaVarName(s string) string {
var b strings.Builder
for _, c := range s {
if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') {
b.WriteRune(c)
} else {
b.WriteRune('_')
}
}
return strings.ToLower(b.String())
}
func checkLuaUnsupportedTypes(schema parser.Schema) error {
for _, msg := range schema.Messages {
for _, f := range msg.Fields {
if err := checkFieldLuaSupport(msg.Name, f); err != nil {
return err
}
}
}
return nil
}
func checkFieldLuaSupport(msgName string, f parser.Field) error {
switch f.Kind {
case parser.KindPrimitive:
if f.Primitive == parser.KindInt64 || f.Primitive == parser.KindUint64 {
return fmt.Errorf("Lua target does not support int64/uint64: field %s in message %s (LuaJIT/Defold uses double-precision floats which can only safely represent integers up to 2^53)", f.Name, msgName)
}
case parser.KindFixedArray, parser.KindSlice:
if f.Elem != nil {
return checkFieldLuaSupport(msgName, *f.Elem)
}
}
return nil
}
+557
View File
@@ -0,0 +1,557 @@
package generator
import (
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
"github.com/edmand46/arpack/parser"
)
func TestGenerateLua_BasicTypes(t *testing.T) {
schema := parser.Schema{
Messages: []parser.Message{
{
Name: "BasicTypes",
Fields: []parser.Field{
{Name: "Int8Field", Kind: parser.KindPrimitive, Primitive: parser.KindInt8},
{Name: "Int16Field", Kind: parser.KindPrimitive, Primitive: parser.KindInt16},
{Name: "Int32Field", Kind: parser.KindPrimitive, Primitive: parser.KindInt32},
{Name: "Uint8Field", Kind: parser.KindPrimitive, Primitive: parser.KindUint8},
{Name: "Uint16Field", Kind: parser.KindPrimitive, Primitive: parser.KindUint16},
{Name: "Uint32Field", Kind: parser.KindPrimitive, Primitive: parser.KindUint32},
{Name: "Float32Field", Kind: parser.KindPrimitive, Primitive: parser.KindFloat32},
{Name: "Float64Field", Kind: parser.KindPrimitive, Primitive: parser.KindFloat64},
{Name: "BoolField", Kind: parser.KindPrimitive, Primitive: parser.KindBool},
{Name: "StringField", Kind: parser.KindPrimitive, Primitive: parser.KindString},
},
},
},
}
lua, err := GenerateLuaSchema(schema, "test")
if err != nil {
t.Fatalf("GenerateLuaSchema failed: %v", err)
}
luaStr := string(lua)
if !strings.Contains(luaStr, "function M.new_basic_types()") {
t.Error("Missing constructor for BasicTypes")
}
if !strings.Contains(luaStr, "function M.serialize_basic_types(msg)") {
t.Error("Missing serializer for BasicTypes")
}
if !strings.Contains(luaStr, "function M.deserialize_basic_types(data, offset)") {
t.Error("Missing deserializer for BasicTypes")
}
if !strings.Contains(luaStr, "int8_field = 0") {
t.Error("Missing int8_field in constructor")
}
if !strings.Contains(luaStr, "string_field = ''") {
t.Error("Missing string_field default value")
}
if !strings.Contains(luaStr, "bool_field = false") {
t.Error("Missing bool_field default value")
}
}
func TestGenerateLua_Enum(t *testing.T) {
schema := parser.Schema{
Enums: []parser.Enum{
{
Name: "Opcode",
Primitive: parser.KindUint16,
Values: []parser.EnumValue{
{Name: "Unknown", Value: "0"},
{Name: "Join", Value: "1"},
{Name: "Leave", Value: "2"},
},
},
},
Messages: []parser.Message{
{
Name: "MessageWithEnum",
Fields: []parser.Field{
{Name: "Op", Kind: parser.KindPrimitive, Primitive: parser.KindUint16, NamedType: "Opcode"},
},
},
},
}
enumNames := map[string]struct{}{"Opcode": {}}
_ = enumNames
lua, err := GenerateLuaSchema(schema, "test")
if err != nil {
t.Fatalf("GenerateLuaSchema failed: %v", err)
}
luaStr := string(lua)
if !strings.Contains(luaStr, "M.Opcode = {") {
t.Error("Missing Opcode enum table")
}
if !strings.Contains(luaStr, "Unknown = 0") {
t.Error("Missing Unknown enum value")
}
if !strings.Contains(luaStr, "Join = 1") {
t.Error("Missing Join enum value")
}
}
func TestGenerateLua_NestedMessage(t *testing.T) {
schema := parser.Schema{
Messages: []parser.Message{
{
Name: "Vector3",
Fields: []parser.Field{
{Name: "X", Kind: parser.KindPrimitive, Primitive: parser.KindFloat32},
{Name: "Y", Kind: parser.KindPrimitive, Primitive: parser.KindFloat32},
{Name: "Z", Kind: parser.KindPrimitive, Primitive: parser.KindFloat32},
},
},
{
Name: "Player",
Fields: []parser.Field{
{Name: "Position", Kind: parser.KindNested, TypeName: "Vector3"},
{Name: "Health", Kind: parser.KindPrimitive, Primitive: parser.KindInt32},
},
},
},
}
lua, err := GenerateLuaSchema(schema, "test")
if err != nil {
t.Fatalf("GenerateLuaSchema failed: %v", err)
}
luaStr := string(lua)
if !strings.Contains(luaStr, "function M.new_vector3()") {
t.Error("Missing constructor for Vector3")
}
if !strings.Contains(luaStr, "function M.new_player()") {
t.Error("Missing constructor for Player")
}
if !strings.Contains(luaStr, "position = M.new_vector3()") {
t.Error("Missing nested initialization in Player constructor")
}
if !strings.Contains(luaStr, "M.serialize_vector3") {
t.Error("Missing Vector3 serializer call")
}
}
func TestGenerateLua_FixedArray(t *testing.T) {
schema := parser.Schema{
Messages: []parser.Message{
{
Name: "WithFixedArray",
Fields: []parser.Field{
{
Name: "Values",
Kind: parser.KindFixedArray,
FixedLen: 3,
Elem: &parser.Field{
Kind: parser.KindPrimitive,
Primitive: parser.KindFloat32,
},
},
},
},
},
}
lua, err := GenerateLuaSchema(schema, "test")
if err != nil {
t.Fatalf("GenerateLuaSchema failed: %v", err)
}
luaStr := string(lua)
if !strings.Contains(luaStr, "values = {}") {
t.Error("Missing values array initialization")
}
if !strings.Contains(luaStr, "for _i_values = 1, 3 do") {
t.Error("Missing fixed array loop in serializer")
}
}
func TestGenerateLua_Slice(t *testing.T) {
schema := parser.Schema{
Messages: []parser.Message{
{
Name: "WithSlice",
Fields: []parser.Field{
{
Name: "Items",
Kind: parser.KindSlice,
Elem: &parser.Field{
Kind: parser.KindPrimitive,
Primitive: parser.KindInt32,
},
},
},
},
},
}
lua, err := GenerateLuaSchema(schema, "test")
if err != nil {
t.Fatalf("GenerateLuaSchema failed: %v", err)
}
luaStr := string(lua)
if !strings.Contains(luaStr, "items = {}") {
t.Error("Missing items slice initialization")
}
if !strings.Contains(luaStr, "local _len_items = #(msg.items or {})") {
t.Error("Missing slice length serialization")
}
if !strings.Contains(luaStr, "for _i_items = 1, _len_items do") {
t.Error("Missing slice iteration in serializer")
}
}
func TestGenerateLua_BoolPacking(t *testing.T) {
schema := parser.Schema{
Messages: []parser.Message{
{
Name: "WithBools",
Fields: []parser.Field{
{Name: "A", Kind: parser.KindPrimitive, Primitive: parser.KindBool},
{Name: "B", Kind: parser.KindPrimitive, Primitive: parser.KindBool},
{Name: "C", Kind: parser.KindPrimitive, Primitive: parser.KindBool},
{Name: "Value", Kind: parser.KindPrimitive, Primitive: parser.KindInt32},
},
},
},
}
lua, err := GenerateLuaSchema(schema, "test")
if err != nil {
t.Fatalf("GenerateLuaSchema failed: %v", err)
}
luaStr := string(lua)
if !strings.Contains(luaStr, "local _bool_byte_0 = 0") {
t.Error("Missing bool byte packing variable")
}
if !strings.Contains(luaStr, "if msg.a then _bool_byte_0 = bit.bor(_bool_byte_0, 1) end") {
t.Error("Missing first bool packing check with bit.bor")
}
if !strings.Contains(luaStr, "if msg.b then _bool_byte_0 = bit.bor(_bool_byte_0, 2) end") {
t.Error("Missing second bool packing check with bit.bor")
}
if !strings.Contains(luaStr, "msg.a = bit.band(_bool_byte_0, 1) ~= 0") {
t.Error("Missing bit.band for bool deserialization")
}
}
func TestGenerateLua_QuantizedFloat(t *testing.T) {
schema := parser.Schema{
Messages: []parser.Message{
{
Name: "WithQuantized",
Fields: []parser.Field{
{
Name: "Position",
Kind: parser.KindPrimitive,
Primitive: parser.KindFloat32,
Quant: &parser.QuantInfo{
Min: -500,
Max: 500,
Bits: 16,
},
},
},
},
},
}
lua, err := GenerateLuaSchema(schema, "test")
if err != nil {
t.Fatalf("GenerateLuaSchema failed: %v", err)
}
luaStr := string(lua)
if !strings.Contains(luaStr, "math.floor") {
t.Error("Missing math.floor for quantization")
}
if !strings.Contains(luaStr, "write_u16_le") {
t.Error("Missing u16 write for 16-bit quantization")
}
}
func TestToSnakeCase(t *testing.T) {
tests := []struct {
input string
expected string
}{
{"", ""},
{"A", "a"},
{"AB", "ab"},
{"AbCd", "ab_cd"},
{"ABC", "abc"},
{"PlayerID", "player_id"},
{"HTTPResponse", "http_response"},
{"XMLHttpRequest", "xml_http_request"},
{"getHTTPResponse", "get_http_response"},
}
for _, tt := range tests {
result := toSnakeCase(tt.input)
if result != tt.expected {
t.Errorf("toSnakeCase(%q) = %q, want %q", tt.input, result, tt.expected)
}
}
}
func TestLuaHelpersGenerated(t *testing.T) {
schema := parser.Schema{
Messages: []parser.Message{
{
Name: "Empty",
Fields: []parser.Field{},
},
},
}
lua, err := GenerateLuaSchema(schema, "test")
if err != nil {
t.Fatalf("GenerateLuaSchema failed: %v", err)
}
luaStr := string(lua)
helpers := []string{
"local bit = require('bit')",
"buffer too short for u8",
"buffer too short for bool",
"local function write_u8(n)",
"buffer too short for u16",
"local function write_u16_le(n)",
"buffer too short for u32",
"local function write_u32_le(n)",
"local function read_f32_le(data, offset)",
"local function write_f32_le(n)",
"local function read_f64_le(data, offset)",
"local function write_f64_le(n)",
"local function write_bool(v)",
"buffer too short for string",
"local function write_string(s)",
}
for _, helper := range helpers {
if !strings.Contains(luaStr, helper) {
t.Errorf("Missing helper: %s", helper)
}
}
}
func TestGenerateLua_Int64NotSupported(t *testing.T) {
schema := parser.Schema{
Messages: []parser.Message{
{
Name: "WithInt64",
Fields: []parser.Field{
{Name: "Value", Kind: parser.KindPrimitive, Primitive: parser.KindInt64},
},
},
},
}
_, err := GenerateLuaSchema(schema, "test")
if err == nil {
t.Fatal("Expected error for int64 field, got nil")
}
if !strings.Contains(err.Error(), "int64/uint64") {
t.Errorf("Expected error mentioning int64/uint64, got: %v", err)
}
if !strings.Contains(err.Error(), "LuaJIT/Defold") {
t.Errorf("Expected error mentioning LuaJIT/Defold, got: %v", err)
}
}
func TestGenerateLua_Uint64NotSupported(t *testing.T) {
schema := parser.Schema{
Messages: []parser.Message{
{
Name: "WithUint64",
Fields: []parser.Field{
{Name: "Value", Kind: parser.KindPrimitive, Primitive: parser.KindUint64},
},
},
},
}
_, err := GenerateLuaSchema(schema, "test")
if err == nil {
t.Fatal("Expected error for uint64 field, got nil")
}
if !strings.Contains(err.Error(), "int64/uint64") {
t.Errorf("Expected error mentioning int64/uint64, got: %v", err)
}
}
func TestGenerateLua_Int64InSliceNotSupported(t *testing.T) {
schema := parser.Schema{
Messages: []parser.Message{
{
Name: "WithInt64Slice",
Fields: []parser.Field{
{
Name: "Values",
Kind: parser.KindSlice,
Elem: &parser.Field{
Kind: parser.KindPrimitive,
Primitive: parser.KindInt64,
},
},
},
},
},
}
_, err := GenerateLuaSchema(schema, "test")
if err == nil {
t.Fatal("Expected error for int64 in slice, got nil")
}
if !strings.Contains(err.Error(), "int64/uint64") {
t.Errorf("Expected error mentioning int64/uint64, got: %v", err)
}
}
func TestGenerateLua_BoundsChecks(t *testing.T) {
schema := parser.Schema{
Messages: []parser.Message{
{
Name: "SimpleMessage",
Fields: []parser.Field{
{Name: "ID", Kind: parser.KindPrimitive, Primitive: parser.KindUint32},
{Name: "Name", Kind: parser.KindPrimitive, Primitive: parser.KindString},
},
},
},
}
lua, err := GenerateLuaSchema(schema, "test")
if err != nil {
t.Fatalf("GenerateLuaSchema failed: %v", err)
}
luaStr := string(lua)
// Check that bounds check function exists
if !strings.Contains(luaStr, "check_bounds") {
t.Error("Missing check_bounds function")
}
// Check that read_u16_le has bounds check
if !strings.Contains(luaStr, "buffer too short for u16") {
t.Error("Missing bounds check in read_u16_le")
}
// Check that read_u32_le has bounds check
if !strings.Contains(luaStr, "buffer too short for u32") {
t.Error("Missing bounds check in read_u32_le")
}
// Check that read_string has bounds check
if !strings.Contains(luaStr, "buffer too short for string") {
t.Error("Missing bounds check in read_string")
}
// Check that deserialize function has min size check (message name is preserved in error)
if !strings.Contains(luaStr, "buffer too short for SimpleMessage") {
t.Error("Missing min size check in deserialize function")
}
// Check that read_u8 has bounds check
if !strings.Contains(luaStr, "buffer too short for u8") {
t.Error("Missing bounds check in read_u8")
}
// Check that read_bool has bounds check
if !strings.Contains(luaStr, "buffer too short for bool") {
t.Error("Missing bounds check in read_bool")
}
// Check that read_i8 has bounds check
if !strings.Contains(luaStr, "buffer too short for i8") {
t.Error("Missing bounds check in read_i8")
}
}
func TestGenerateLua_RuntimeFloatEdgeCases(t *testing.T) {
if _, err := exec.LookPath("luajit"); err != nil {
t.Skip("luajit not found")
}
schema := parser.Schema{
Messages: []parser.Message{
{
Name: "FloatEdges",
Fields: []parser.Field{
{Name: "F32", Kind: parser.KindPrimitive, Primitive: parser.KindFloat32},
{Name: "F64", Kind: parser.KindPrimitive, Primitive: parser.KindFloat64},
},
},
},
}
lua, err := GenerateLuaSchema(schema, "messages")
if err != nil {
t.Fatalf("GenerateLuaSchema failed: %v", err)
}
dir := t.TempDir()
modulePath := filepath.Join(dir, "messages_gen.lua")
if err := os.WriteFile(modulePath, lua, 0o600); err != nil {
t.Fatalf("write module: %v", err)
}
scriptPath := filepath.Join(dir, "check.lua")
script := `local messages = require("messages_gen")
local function bytes_to_hex(s)
return (s:gsub(".", function(c) return string.format("%02x", string.byte(c)) end))
end
local neg_zero = string.char(0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 128)
local msg = messages.deserialize_float_edges(neg_zero, 1)
print(bytes_to_hex(messages.serialize_float_edges(msg)))
local subnormal = string.char(1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0)
msg = messages.deserialize_float_edges(subnormal, 1)
print(bytes_to_hex(messages.serialize_float_edges(msg)))
`
if err := os.WriteFile(scriptPath, []byte(script), 0o600); err != nil {
t.Fatalf("write script: %v", err)
}
cmd := exec.Command("luajit", "check.lua")
cmd.Dir = dir
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("luajit failed: %v\n%s", err, out)
}
lines := strings.Split(strings.TrimSpace(string(out)), "\n")
if len(lines) != 2 {
t.Fatalf("expected 2 output lines, got %d: %q", len(lines), string(out))
}
if lines[0] != "000000800000000000000080" {
t.Fatalf("negative zero roundtrip mismatch: %s", lines[0])
}
if lines[1] != "010000000100000000000000" {
t.Fatalf("subnormal roundtrip mismatch: %s", lines[1])
}
}
+635
View File
@@ -0,0 +1,635 @@
package generator
import (
"fmt"
"strings"
"github.com/edmand46/arpack/parser"
)
// GenerateTypeScript generates TypeScript code for the given messages
func GenerateTypeScript(messages []parser.Message, namespace string) ([]byte, error) {
return GenerateTypeScriptSchema(parser.Schema{Messages: messages}, namespace)
}
// GenerateTypeScriptSchema generates TypeScript code from a schema
func GenerateTypeScriptSchema(schema parser.Schema, namespace string) ([]byte, error) {
messages := schema.Messages
var b strings.Builder
b.WriteString("// <auto-generated> arpack </auto-generated>\n")
b.WriteString("// Code generated by arpack. DO NOT EDIT.\n\n")
enumNames := make(map[string]struct{}, len(schema.Enums))
for _, enum := range schema.Enums {
enumNames[enum.Name] = struct{}{}
}
// Generate enums
for _, enum := range schema.Enums {
writeTSEnum(&b, enum)
b.WriteString("\n")
}
// Generate messages
for i, msg := range messages {
if err := writeTSMessage(&b, msg, enumNames); err != nil {
return nil, fmt.Errorf("message %s: %w", msg.Name, err)
}
if i < len(messages)-1 {
b.WriteString("\n")
}
}
return []byte(b.String()), nil
}
func writeTSEnum(b *strings.Builder, enum parser.Enum) {
fmt.Fprintf(b, "export enum %s {\n", enum.Name)
for i, value := range enum.Values {
fmt.Fprintf(b, " %s = %s", value.Name, value.Value)
if i < len(enum.Values)-1 {
b.WriteString(",")
}
b.WriteString("\n")
}
b.WriteString("}\n")
}
func writeTSMessage(b *strings.Builder, msg parser.Message, enumNames map[string]struct{}) error {
segs := segmentFields(msg.Fields)
fmt.Fprintf(b, "export class %s {\n", msg.Name)
// Field declarations with defaults
for _, f := range msg.Fields {
defaultValue := tsDefaultValue(f)
fmt.Fprintf(b, " %s: %s = %s;\n", toCamelCase(f.Name), tsTypeName(f, enumNames), defaultValue)
}
b.WriteString("\n")
// Serialize method
b.WriteString(" serialize(view: DataView, offset: number): number {\n")
b.WriteString(" let pos = offset;\n")
for i, seg := range segs {
if seg.single != nil {
if err := writeTSSerializeField(b, "this", *seg.single, " ", enumNames); err != nil {
return err
}
} else {
writeTSBoolGroupSerialize(b, "this", seg.bools, i, " ")
}
}
b.WriteString(" return pos - offset;\n")
b.WriteString(" }\n\n")
// Deserialize method
fmt.Fprintf(b, " static deserialize(view: DataView, offset: number): [%s, number] {\n", msg.Name)
b.WriteString(" let pos = offset;\n")
fmt.Fprintf(b, " const msg = new %s();\n", msg.Name)
for i, seg := range segs {
if seg.single != nil {
if err := writeTSDeserializeField(b, "msg", *seg.single, " ", enumNames); err != nil {
return err
}
} else {
writeTSBoolGroupDeserialize(b, "msg", seg.bools, i, " ")
}
}
b.WriteString(" return [msg, pos - offset];\n")
b.WriteString(" }\n")
b.WriteString("}\n")
return nil
}
func writeTSBoolGroupSerialize(b *strings.Builder, recv string, bools []parser.Field, groupIdx int, indent string) {
varName := fmt.Sprintf("_boolByte%d", groupIdx)
fmt.Fprintf(b, "%slet %s = 0;\n", indent, varName)
for bit, f := range bools {
fmt.Fprintf(b, "%sif (%s.%s) %s |= 1 << %d;\n", indent, recv, toCamelCase(f.Name), varName, bit)
}
fmt.Fprintf(b, "%sview.setUint8(pos, %s);\n", indent, varName)
fmt.Fprintf(b, "%spos += 1;\n", indent)
}
func writeTSBoolGroupDeserialize(b *strings.Builder, recv string, bools []parser.Field, groupIdx int, indent string) {
varName := fmt.Sprintf("_boolByte%d", groupIdx)
fmt.Fprintf(b, "%sconst %s = view.getUint8(pos);\n", indent, varName)
fmt.Fprintf(b, "%spos += 1;\n", indent)
for bit, f := range bools {
fmt.Fprintf(b, "%s%s.%s = (%s & (1 << %d)) !== 0;\n", indent, recv, toCamelCase(f.Name), varName, bit)
}
}
func writeTSSerializeField(b *strings.Builder, recv string, f parser.Field, indent string, enumNames map[string]struct{}) error {
access := recv + "." + toCamelCase(f.Name)
switch f.Kind {
case parser.KindPrimitive:
return writeTSSerializePrimitive(b, access, f, indent, enumNames)
case parser.KindNested:
fmt.Fprintf(b, "%spos += %s.serialize(view, pos);\n", indent, access)
case parser.KindFixedArray:
iVar := "_i" + f.Name
fmt.Fprintf(b, "%sfor (let %s = 0; %s < %d; %s++) {\n",
indent, iVar, iVar, f.FixedLen, iVar)
elemField := parser.Field{
Name: f.Name + "[" + iVar + "]",
Kind: f.Elem.Kind,
Primitive: f.Elem.Primitive,
NamedType: f.Elem.NamedType,
Quant: f.Elem.Quant,
TypeName: f.Elem.TypeName,
Elem: f.Elem.Elem,
FixedLen: f.Elem.FixedLen,
}
if err := writeTSSerializeField(b, recv, elemField, indent+" ", enumNames); err != nil {
return err
}
fmt.Fprintf(b, "%s}\n", indent)
case parser.KindSlice:
fmt.Fprintf(b, "%sview.setUint16(pos, %s.length, true);\n", indent, access)
fmt.Fprintf(b, "%spos += 2;\n", indent)
iVar := "_i" + f.Name
fmt.Fprintf(b, "%sfor (const %s of %s) {\n", indent, iVar, access)
elemField := parser.Field{
Name: iVar,
Kind: f.Elem.Kind,
Primitive: f.Elem.Primitive,
NamedType: f.Elem.NamedType,
Quant: f.Elem.Quant,
TypeName: f.Elem.TypeName,
Elem: f.Elem.Elem,
FixedLen: f.Elem.FixedLen,
}
if err := writeTSSerializeFieldElement(b, iVar, elemField, indent+" ", enumNames); err != nil {
return err
}
fmt.Fprintf(b, "%s}\n", indent)
}
return nil
}
func writeTSSerializeFieldElement(b *strings.Builder, access string, f parser.Field, indent string, enumNames map[string]struct{}) error {
switch f.Kind {
case parser.KindPrimitive:
return writeTSSerializePrimitiveElement(b, access, f, indent, enumNames)
case parser.KindNested:
fmt.Fprintf(b, "%spos += %s.serialize(view, pos);\n", indent, access)
}
return nil
}
func writeTSSerializePrimitiveElement(b *strings.Builder, access string, f parser.Field, indent string, enumNames map[string]struct{}) error {
if f.Quant != nil {
return writeTSSerializeQuantElement(b, access, f, indent)
}
valueExpr := tsSerializeValueExpr(access, f, enumNames)
switch f.Primitive {
case parser.KindFloat32:
fmt.Fprintf(b, "%sview.setFloat32(pos, %s, true);\n", indent, valueExpr)
fmt.Fprintf(b, "%spos += 4;\n", indent)
case parser.KindFloat64:
fmt.Fprintf(b, "%sview.setFloat64(pos, %s, true);\n", indent, valueExpr)
fmt.Fprintf(b, "%spos += 8;\n", indent)
case parser.KindInt8:
fmt.Fprintf(b, "%sview.setInt8(pos, %s);\n", indent, valueExpr)
fmt.Fprintf(b, "%spos += 1;\n", indent)
case parser.KindUint8:
fmt.Fprintf(b, "%sview.setUint8(pos, %s);\n", indent, valueExpr)
fmt.Fprintf(b, "%spos += 1;\n", indent)
case parser.KindBool:
fmt.Fprintf(b, "%sview.setUint8(pos, %s ? 1 : 0);\n", indent, valueExpr)
fmt.Fprintf(b, "%spos += 1;\n", indent)
case parser.KindInt16:
fmt.Fprintf(b, "%sview.setInt16(pos, %s, true);\n", indent, valueExpr)
fmt.Fprintf(b, "%spos += 2;\n", indent)
case parser.KindUint16:
fmt.Fprintf(b, "%sview.setUint16(pos, %s, true);\n", indent, valueExpr)
fmt.Fprintf(b, "%spos += 2;\n", indent)
case parser.KindInt32:
fmt.Fprintf(b, "%sview.setInt32(pos, %s, true);\n", indent, valueExpr)
fmt.Fprintf(b, "%spos += 4;\n", indent)
case parser.KindUint32:
fmt.Fprintf(b, "%sview.setUint32(pos, %s, true);\n", indent, valueExpr)
fmt.Fprintf(b, "%spos += 4;\n", indent)
case parser.KindInt64:
fmt.Fprintf(b, "%sview.setBigInt64(pos, %s, true);\n", indent, valueExpr)
fmt.Fprintf(b, "%spos += 8;\n", indent)
case parser.KindUint64:
fmt.Fprintf(b, "%sview.setBigUint64(pos, %s, true);\n", indent, valueExpr)
fmt.Fprintf(b, "%spos += 8;\n", indent)
case parser.KindString:
lenVar := "_slen" + sanitizeVarName(access)
fmt.Fprintf(b, "%sconst %s = new TextEncoder().encode(%s);\n", indent, lenVar, valueExpr)
fmt.Fprintf(b, "%sview.setUint16(pos, %s.length, true);\n", indent, lenVar)
fmt.Fprintf(b, "%spos += 2;\n", indent)
fmt.Fprintf(b, "%snew Uint8Array(view.buffer, pos, %s.length).set(%s);\n", indent, lenVar, lenVar)
fmt.Fprintf(b, "%spos += %s.length;\n", indent, lenVar)
}
return nil
}
func writeTSSerializePrimitive(b *strings.Builder, access string, f parser.Field, indent string, enumNames map[string]struct{}) error {
if f.Quant != nil {
return writeTSSerializeQuant(b, access, f, indent)
}
valueExpr := tsSerializeValueExpr(access, f, enumNames)
switch f.Primitive {
case parser.KindFloat32:
fmt.Fprintf(b, "%sview.setFloat32(pos, %s, true);\n", indent, valueExpr)
fmt.Fprintf(b, "%spos += 4;\n", indent)
case parser.KindFloat64:
fmt.Fprintf(b, "%sview.setFloat64(pos, %s, true);\n", indent, valueExpr)
fmt.Fprintf(b, "%spos += 8;\n", indent)
case parser.KindInt8:
fmt.Fprintf(b, "%sview.setInt8(pos, %s);\n", indent, valueExpr)
fmt.Fprintf(b, "%spos += 1;\n", indent)
case parser.KindUint8:
fmt.Fprintf(b, "%sview.setUint8(pos, %s);\n", indent, valueExpr)
fmt.Fprintf(b, "%spos += 1;\n", indent)
case parser.KindBool:
fmt.Fprintf(b, "%sview.setUint8(pos, %s ? 1 : 0);\n", indent, valueExpr)
fmt.Fprintf(b, "%spos += 1;\n", indent)
case parser.KindInt16:
fmt.Fprintf(b, "%sview.setInt16(pos, %s, true);\n", indent, valueExpr)
fmt.Fprintf(b, "%spos += 2;\n", indent)
case parser.KindUint16:
fmt.Fprintf(b, "%sview.setUint16(pos, %s, true);\n", indent, valueExpr)
fmt.Fprintf(b, "%spos += 2;\n", indent)
case parser.KindInt32:
fmt.Fprintf(b, "%sview.setInt32(pos, %s, true);\n", indent, valueExpr)
fmt.Fprintf(b, "%spos += 4;\n", indent)
case parser.KindUint32:
fmt.Fprintf(b, "%sview.setUint32(pos, %s, true);\n", indent, valueExpr)
fmt.Fprintf(b, "%spos += 4;\n", indent)
case parser.KindInt64:
fmt.Fprintf(b, "%sview.setBigInt64(pos, %s, true);\n", indent, valueExpr)
fmt.Fprintf(b, "%spos += 8;\n", indent)
case parser.KindUint64:
fmt.Fprintf(b, "%sview.setBigUint64(pos, %s, true);\n", indent, valueExpr)
fmt.Fprintf(b, "%spos += 8;\n", indent)
case parser.KindString:
lenVar := "_slen" + sanitizeVarName(access)
fmt.Fprintf(b, "%sconst %s = new TextEncoder().encode(%s);\n", indent, lenVar, valueExpr)
fmt.Fprintf(b, "%sview.setUint16(pos, %s.length, true);\n", indent, lenVar)
fmt.Fprintf(b, "%spos += 2;\n", indent)
fmt.Fprintf(b, "%snew Uint8Array(view.buffer, pos, %s.length).set(%s);\n", indent, lenVar, lenVar)
fmt.Fprintf(b, "%spos += %s.length;\n", indent, lenVar)
}
return nil
}
func writeTSSerializeQuant(b *strings.Builder, access string, f parser.Field, indent string) error {
q := f.Quant
maxUint := q.MaxUint()
varName := "_q" + sanitizeVarName(access)
if q.Bits == 8 {
fmt.Fprintf(b, "%sconst %s = Math.round((%s - (%g)) / (%g - (%g)) * %g);\n",
indent, varName, access, q.Min, q.Max, q.Min, maxUint)
fmt.Fprintf(b, "%sview.setUint8(pos, %s);\n", indent, varName)
fmt.Fprintf(b, "%spos += 1;\n", indent)
} else {
fmt.Fprintf(b, "%sconst %s = Math.round((%s - (%g)) / (%g - (%g)) * %g);\n",
indent, varName, access, q.Min, q.Max, q.Min, maxUint)
fmt.Fprintf(b, "%sview.setUint16(pos, %s, true);\n", indent, varName)
fmt.Fprintf(b, "%spos += 2;\n", indent)
}
return nil
}
func writeTSSerializeQuantElement(b *strings.Builder, access string, f parser.Field, indent string) error {
q := f.Quant
maxUint := q.MaxUint()
varName := "_q" + sanitizeVarName(access)
if q.Bits == 8 {
fmt.Fprintf(b, "%sconst %s = Math.round((%s - (%g)) / (%g - (%g)) * %g);\n",
indent, varName, access, q.Min, q.Max, q.Min, maxUint)
fmt.Fprintf(b, "%sview.setUint8(pos, %s);\n", indent, varName)
fmt.Fprintf(b, "%spos += 1;\n", indent)
} else {
fmt.Fprintf(b, "%sconst %s = Math.round((%s - (%g)) / (%g - (%g)) * %g);\n",
indent, varName, access, q.Min, q.Max, q.Min, maxUint)
fmt.Fprintf(b, "%sview.setUint16(pos, %s, true);\n", indent, varName)
fmt.Fprintf(b, "%spos += 2;\n", indent)
}
return nil
}
func writeTSDeserializeField(b *strings.Builder, recv string, f parser.Field, indent string, enumNames map[string]struct{}) error {
access := recv + "." + toCamelCase(f.Name)
switch f.Kind {
case parser.KindPrimitive:
return writeTSDeserializePrimitive(b, access, f, indent, enumNames)
case parser.KindNested:
fmt.Fprintf(b, "%sconst [_%s, _n%s] = %s.deserialize(view, pos);\n", indent, f.Name, f.Name, f.TypeName)
fmt.Fprintf(b, "%s%s = _%s;\n", indent, access, f.Name)
fmt.Fprintf(b, "%spos += _n%s;\n", indent, f.Name)
case parser.KindFixedArray:
iVar := "_i" + f.Name
fmt.Fprintf(b, "%s%s = new Array(%d);\n", indent, access, f.FixedLen)
fmt.Fprintf(b, "%sfor (let %s = 0; %s < %d; %s++) {\n",
indent, iVar, iVar, f.FixedLen, iVar)
elemField := parser.Field{
Name: f.Name + "[" + iVar + "]",
Kind: f.Elem.Kind,
Primitive: f.Elem.Primitive,
NamedType: f.Elem.NamedType,
Quant: f.Elem.Quant,
TypeName: f.Elem.TypeName,
Elem: f.Elem.Elem,
FixedLen: f.Elem.FixedLen,
}
if err := writeTSDeserializeField(b, recv, elemField, indent+" ", enumNames); err != nil {
return err
}
fmt.Fprintf(b, "%s}\n", indent)
case parser.KindSlice:
lenVar := "_len" + f.Name
fmt.Fprintf(b, "%sconst %s = view.getUint16(pos, true);\n", indent, lenVar)
fmt.Fprintf(b, "%spos += 2;\n", indent)
fmt.Fprintf(b, "%s%s = new Array(%s);\n", indent, access, lenVar)
iVar := "_i" + f.Name
fmt.Fprintf(b, "%sfor (let %s = 0; %s < %s; %s++) {\n", indent, iVar, iVar, lenVar, iVar)
elemField := parser.Field{
Name: f.Name + "[" + iVar + "]",
Kind: f.Elem.Kind,
Primitive: f.Elem.Primitive,
NamedType: f.Elem.NamedType,
Quant: f.Elem.Quant,
TypeName: f.Elem.TypeName,
Elem: f.Elem.Elem,
FixedLen: f.Elem.FixedLen,
}
if err := writeTSDeserializeFieldElement(b, recv, elemField, indent+" ", enumNames); err != nil {
return err
}
fmt.Fprintf(b, "%s}\n", indent)
}
return nil
}
func writeTSDeserializeFieldElement(b *strings.Builder, recv string, f parser.Field, indent string, enumNames map[string]struct{}) error {
access := recv + "." + toCamelCase(f.Name)
switch f.Kind {
case parser.KindPrimitive:
return writeTSDeserializePrimitiveElement(b, access, f, indent, enumNames)
case parser.KindNested:
fmt.Fprintf(b, "%sconst [_elem, _nElem] = %s.deserialize(view, pos);\n", indent, f.TypeName)
fmt.Fprintf(b, "%s%s = _elem;\n", indent, access)
fmt.Fprintf(b, "%spos += _nElem;\n", indent)
}
return nil
}
func writeTSDeserializePrimitiveElement(b *strings.Builder, access string, f parser.Field, indent string, enumNames map[string]struct{}) error {
if f.Quant != nil {
return writeTSDeserializeQuantElement(b, access, f, indent)
}
switch f.Primitive {
case parser.KindFloat32:
expr := "view.getFloat32(pos, true)"
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += 4;\n", indent)
case parser.KindFloat64:
expr := "view.getFloat64(pos, true)"
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += 8;\n", indent)
case parser.KindInt8:
expr := "view.getInt8(pos)"
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += 1;\n", indent)
case parser.KindUint8:
expr := "view.getUint8(pos)"
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += 1;\n", indent)
case parser.KindBool:
expr := "view.getUint8(pos) !== 0"
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += 1;\n", indent)
case parser.KindInt16:
expr := "view.getInt16(pos, true)"
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += 2;\n", indent)
case parser.KindUint16:
expr := "view.getUint16(pos, true)"
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += 2;\n", indent)
case parser.KindInt32:
expr := "view.getInt32(pos, true)"
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += 4;\n", indent)
case parser.KindUint32:
expr := "view.getUint32(pos, true)"
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += 4;\n", indent)
case parser.KindInt64:
expr := "view.getBigInt64(pos, true)"
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += 8;\n", indent)
case parser.KindUint64:
expr := "view.getBigUint64(pos, true)"
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += 8;\n", indent)
case parser.KindString:
lenVar := "_slen" + sanitizeVarName(access)
fmt.Fprintf(b, "%sconst %s = view.getUint16(pos, true);\n", indent, lenVar)
fmt.Fprintf(b, "%spos += 2;\n", indent)
expr := fmt.Sprintf("new TextDecoder().decode(new Uint8Array(view.buffer, pos, %s))", lenVar)
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += %s;\n", indent, lenVar)
}
return nil
}
func writeTSDeserializePrimitive(b *strings.Builder, access string, f parser.Field, indent string, enumNames map[string]struct{}) error {
if f.Quant != nil {
return writeTSDeserializeQuant(b, access, f, indent)
}
switch f.Primitive {
case parser.KindFloat32:
expr := "view.getFloat32(pos, true)"
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += 4;\n", indent)
case parser.KindFloat64:
expr := "view.getFloat64(pos, true)"
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += 8;\n", indent)
case parser.KindInt8:
expr := "view.getInt8(pos)"
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += 1;\n", indent)
case parser.KindUint8:
expr := "view.getUint8(pos)"
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += 1;\n", indent)
case parser.KindBool:
expr := "view.getUint8(pos) !== 0"
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += 1;\n", indent)
case parser.KindInt16:
expr := "view.getInt16(pos, true)"
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += 2;\n", indent)
case parser.KindUint16:
expr := "view.getUint16(pos, true)"
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += 2;\n", indent)
case parser.KindInt32:
expr := "view.getInt32(pos, true)"
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += 4;\n", indent)
case parser.KindUint32:
expr := "view.getUint32(pos, true)"
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += 4;\n", indent)
case parser.KindInt64:
expr := "view.getBigInt64(pos, true)"
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += 8;\n", indent)
case parser.KindUint64:
expr := "view.getBigUint64(pos, true)"
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += 8;\n", indent)
case parser.KindString:
lenVar := "_slen" + sanitizeVarName(access)
fmt.Fprintf(b, "%sconst %s = view.getUint16(pos, true);\n", indent, lenVar)
fmt.Fprintf(b, "%spos += 2;\n", indent)
expr := fmt.Sprintf("new TextDecoder().decode(new Uint8Array(view.buffer, pos, %s))", lenVar)
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, enumNames))
fmt.Fprintf(b, "%spos += %s;\n", indent, lenVar)
}
return nil
}
func writeTSDeserializeQuant(b *strings.Builder, access string, f parser.Field, indent string) error {
q := f.Quant
maxUint := q.MaxUint()
varName := "_q" + sanitizeVarName(access)
if q.Bits == 8 {
fmt.Fprintf(b, "%sconst %s = view.getUint8(pos);\n", indent, varName)
fmt.Fprintf(b, "%spos += 1;\n", indent)
expr := fmt.Sprintf("%s / %g * (%g - (%g)) + (%g)", varName, maxUint, q.Max, q.Min, q.Min)
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, nil))
} else {
fmt.Fprintf(b, "%sconst %s = view.getUint16(pos, true);\n", indent, varName)
fmt.Fprintf(b, "%spos += 2;\n", indent)
expr := fmt.Sprintf("%s / %g * (%g - (%g)) + (%g)", varName, maxUint, q.Max, q.Min, q.Min)
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, nil))
}
return nil
}
func writeTSDeserializeQuantElement(b *strings.Builder, access string, f parser.Field, indent string) error {
q := f.Quant
maxUint := q.MaxUint()
varName := "_q" + sanitizeVarName(access)
if q.Bits == 8 {
fmt.Fprintf(b, "%sconst %s = view.getUint8(pos);\n", indent, varName)
fmt.Fprintf(b, "%spos += 1;\n", indent)
expr := fmt.Sprintf("%s / %g * (%g - (%g)) + (%g)", varName, maxUint, q.Max, q.Min, q.Min)
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, nil))
} else {
fmt.Fprintf(b, "%sconst %s = view.getUint16(pos, true);\n", indent, varName)
fmt.Fprintf(b, "%spos += 2;\n", indent)
expr := fmt.Sprintf("%s / %g * (%g - (%g)) + (%g)", varName, maxUint, q.Max, q.Min, q.Min)
fmt.Fprintf(b, "%s%s = %s;\n", indent, access, tsDeserializeValueExpr(expr, f, nil))
}
return nil
}
func tsTypeName(f parser.Field, enumNames map[string]struct{}) string {
switch f.Kind {
case parser.KindPrimitive:
if tsIsEnumType(f, enumNames) {
return f.NamedType
}
return tsPrimitiveTypeName(f.Primitive)
case parser.KindNested:
return f.TypeName
case parser.KindFixedArray, parser.KindSlice:
return tsTypeName(*f.Elem, enumNames) + "[]"
}
return "unknown"
}
func tsPrimitiveTypeName(k parser.PrimitiveKind) string {
switch k {
case parser.KindFloat32, parser.KindFloat64:
return "number"
case parser.KindInt8, parser.KindInt16, parser.KindInt32, parser.KindUint8, parser.KindUint16, parser.KindUint32:
return "number"
case parser.KindInt64, parser.KindUint64:
return "bigint"
case parser.KindBool:
return "boolean"
case parser.KindString:
return "string"
}
return "unknown"
}
func tsDefaultValue(f parser.Field) string {
switch f.Kind {
case parser.KindPrimitive:
if tsIsEnumType(f, nil) {
return "0"
}
switch f.Primitive {
case parser.KindFloat32, parser.KindFloat64, parser.KindInt8, parser.KindInt16, parser.KindInt32,
parser.KindUint8, parser.KindUint16, parser.KindUint32:
return "0"
case parser.KindInt64, parser.KindUint64:
return "0n"
case parser.KindBool:
return "false"
case parser.KindString:
return `""`
}
case parser.KindNested:
return fmt.Sprintf("new %s()", f.TypeName)
case parser.KindFixedArray:
elemDefault := tsDefaultValue(*f.Elem)
elemType := tsTypeName(*f.Elem, nil)
return fmt.Sprintf("new Array<%s>(%d).fill(%s)", elemType, f.FixedLen, elemDefault)
case parser.KindSlice:
return "[]"
}
return "undefined"
}
func tsSerializeValueExpr(access string, f parser.Field, enumNames map[string]struct{}) string {
if !tsIsEnumType(f, enumNames) {
return access
}
return access + " as " + tsPrimitiveTypeName(f.Primitive)
}
func tsDeserializeValueExpr(expr string, f parser.Field, enumNames map[string]struct{}) string {
if !tsIsEnumType(f, enumNames) {
return expr
}
return "(" + expr + " as " + f.NamedType + ")"
}
func tsIsEnumType(f parser.Field, enumNames map[string]struct{}) bool {
if f.NamedType == "" || enumNames == nil {
return false
}
_, ok := enumNames[f.NamedType]
return ok
}
// toCamelCase converts PascalCase to camelCase (e.g., EntityID -> entityID)
func toCamelCase(s string) string {
if s == "" {
return ""
}
// First character to lowercase
result := strings.ToLower(s[:1]) + s[1:]
return result
}
+401
View File
@@ -0,0 +1,401 @@
package generator
import (
"strings"
"testing"
"github.com/edmand46/arpack/parser"
)
func TestGenerateTypeScript_Primitives(t *testing.T) {
schema := parser.Schema{
Messages: []parser.Message{
{
PackageName: "test",
Name: "PrimitiveMessage",
Fields: []parser.Field{
{Name: "F32", Kind: parser.KindPrimitive, Primitive: parser.KindFloat32},
{Name: "F64", Kind: parser.KindPrimitive, Primitive: parser.KindFloat64},
{Name: "I8", Kind: parser.KindPrimitive, Primitive: parser.KindInt8},
{Name: "I16", Kind: parser.KindPrimitive, Primitive: parser.KindInt16},
{Name: "I32", Kind: parser.KindPrimitive, Primitive: parser.KindInt32},
{Name: "I64", Kind: parser.KindPrimitive, Primitive: parser.KindInt64},
{Name: "U8", Kind: parser.KindPrimitive, Primitive: parser.KindUint8},
{Name: "U16", Kind: parser.KindPrimitive, Primitive: parser.KindUint16},
{Name: "U32", Kind: parser.KindPrimitive, Primitive: parser.KindUint32},
{Name: "U64", Kind: parser.KindPrimitive, Primitive: parser.KindUint64},
{Name: "B", Kind: parser.KindPrimitive, Primitive: parser.KindBool},
{Name: "S", Kind: parser.KindPrimitive, Primitive: parser.KindString},
},
},
},
}
src, err := GenerateTypeScriptSchema(schema, "Test")
if err != nil {
t.Fatalf("GenerateTypeScriptSchema: %v", err)
}
code := string(src)
// Check field declarations (now using camelCase)
if !strings.Contains(code, "f32: number = 0;") {
t.Error("Missing f32 field")
}
if !strings.Contains(code, "i64: bigint = 0n;") {
t.Error("Missing i64 field with bigint type")
}
if !strings.Contains(code, "u64: bigint = 0n;") {
t.Error("Missing u64 field with bigint type")
}
if !strings.Contains(code, "b: boolean = false;") {
t.Error("Missing b field")
}
if !strings.Contains(code, "s: string = \"\";") {
t.Error("Missing s field")
}
// Check serialize method exists
if !strings.Contains(code, "serialize(view: DataView, offset: number): number") {
t.Error("Missing serialize method")
}
// Check deserialize method exists
if !strings.Contains(code, "static deserialize(view: DataView, offset: number): [PrimitiveMessage, number]") {
t.Error("Missing deserialize method")
}
}
func TestGenerateTypeScript_QuantizedFloats(t *testing.T) {
schema := parser.Schema{
Messages: []parser.Message{
{
PackageName: "test",
Name: "QuantMessage",
Fields: []parser.Field{
{
Name: "Q8",
Kind: parser.KindPrimitive,
Primitive: parser.KindFloat32,
Quant: &parser.QuantInfo{Min: 0, Max: 100, Bits: 8},
},
{
Name: "Q16",
Kind: parser.KindPrimitive,
Primitive: parser.KindFloat32,
Quant: &parser.QuantInfo{Min: -500, Max: 500, Bits: 16},
},
},
},
},
}
src, err := GenerateTypeScriptSchema(schema, "Test")
if err != nil {
t.Fatalf("GenerateTypeScriptSchema: %v", err)
}
code := string(src)
// Check 8-bit quantization (using camelCase field names)
if !strings.Contains(code, "Math.round((this.q8 - (0)) / (100 - (0)) * 255)") {
t.Error("Missing 8-bit quantization code")
}
// Check 16-bit quantization (using camelCase field names)
if !strings.Contains(code, "Math.round((this.q16 - (-500)) / (500 - (-500)) * 65535)") {
t.Error("Missing 16-bit quantization code")
}
// Check deserialization with dequantization
if !strings.Contains(code, "/ 255 * (100 - (0)) + (0)") {
t.Error("Missing 8-bit dequantization")
}
if !strings.Contains(code, "/ 65535 * (500 - (-500)) + (-500)") {
t.Error("Missing 16-bit dequantization")
}
}
func TestGenerateTypeScript_BoolPacking(t *testing.T) {
schema := parser.Schema{
Messages: []parser.Message{
{
PackageName: "test",
Name: "BoolMessage",
Fields: []parser.Field{
{Name: "A", Kind: parser.KindPrimitive, Primitive: parser.KindBool},
{Name: "B", Kind: parser.KindPrimitive, Primitive: parser.KindBool},
{Name: "C", Kind: parser.KindPrimitive, Primitive: parser.KindBool},
{Name: "X", Kind: parser.KindPrimitive, Primitive: parser.KindUint32},
{Name: "D", Kind: parser.KindPrimitive, Primitive: parser.KindBool},
{Name: "E", Kind: parser.KindPrimitive, Primitive: parser.KindBool},
},
},
},
}
src, err := GenerateTypeScriptSchema(schema, "Test")
if err != nil {
t.Fatalf("GenerateTypeScriptSchema: %v", err)
}
code := string(src)
// Check that consecutive bools are packed (using camelCase field names)
if !strings.Contains(code, "let _boolByte0 = 0;") {
t.Error("Missing first bool group packing")
}
if !strings.Contains(code, "if (this.a) _boolByte0 |= 1 << 0;") {
t.Error("Missing a bool packing")
}
if !strings.Contains(code, "if (this.b) _boolByte0 |= 1 << 1;") {
t.Error("Missing b bool packing")
}
if !strings.Contains(code, "if (this.c) _boolByte0 |= 1 << 2;") {
t.Error("Missing c bool packing")
}
// Check second bool group after uint32 (index is 2, not 4, based on segment index)
if !strings.Contains(code, "let _boolByte2 = 0;") {
t.Error("Missing second bool group packing")
}
// Check deserialization (using camelCase field names)
if !strings.Contains(code, "msg.a = (_boolByte0 & (1 << 0)) !== 0;") {
t.Error("Missing a bool unpacking")
}
}
func TestGenerateTypeScript_NestedTypes(t *testing.T) {
schema := parser.Schema{
Messages: []parser.Message{
{
PackageName: "test",
Name: "Inner",
Fields: []parser.Field{
{Name: "Value", Kind: parser.KindPrimitive, Primitive: parser.KindInt32},
},
},
{
PackageName: "test",
Name: "Outer",
Fields: []parser.Field{
{Name: "Inner", Kind: parser.KindNested, TypeName: "Inner"},
},
},
},
}
src, err := GenerateTypeScriptSchema(schema, "Test")
if err != nil {
t.Fatalf("GenerateTypeScriptSchema: %v", err)
}
code := string(src)
// Check nested type default value (using camelCase field name)
if !strings.Contains(code, "inner: Inner = new Inner();") {
t.Error("Missing nested type field with default")
}
// Check serialize calls nested serialize (using camelCase field name)
if !strings.Contains(code, "pos += this.inner.serialize(view, pos);") {
t.Error("Missing nested serialize call")
}
// Check deserialize calls nested deserialize
if !strings.Contains(code, "const [_Inner, _nInner] = Inner.deserialize(view, pos);") {
t.Error("Missing nested deserialize call")
}
}
func TestGenerateTypeScript_FixedArrays(t *testing.T) {
schema := parser.Schema{
Messages: []parser.Message{
{
PackageName: "test",
Name: "ArrayMessage",
Fields: []parser.Field{
{
Name: "Values",
Kind: parser.KindFixedArray,
FixedLen: 3,
Elem: &parser.Field{
Kind: parser.KindPrimitive,
Primitive: parser.KindFloat32,
},
},
},
},
},
}
src, err := GenerateTypeScriptSchema(schema, "Test")
if err != nil {
t.Fatalf("GenerateTypeScriptSchema: %v", err)
}
code := string(src)
// Check default value (using camelCase field name)
if !strings.Contains(code, "values: number[] = new Array<number>(3).fill(0);") {
t.Error("Missing fixed array field with default")
}
// Check serialization loop (using camelCase field name)
if !strings.Contains(code, "for (let _iValues = 0; _iValues < 3; _iValues++)") {
t.Error("Missing fixed array serialization loop")
}
// Check deserialization loop (using camelCase field name)
if !strings.Contains(code, "msg.values = new Array(3);") {
t.Error("Missing fixed array allocation in deserialize")
}
}
func TestGenerateTypeScript_Slices(t *testing.T) {
schema := parser.Schema{
Messages: []parser.Message{
{
PackageName: "test",
Name: "SliceMessage",
Fields: []parser.Field{
{
Name: "Items",
Kind: parser.KindSlice,
Elem: &parser.Field{
Kind: parser.KindPrimitive,
Primitive: parser.KindInt32,
},
},
},
},
},
}
src, err := GenerateTypeScriptSchema(schema, "Test")
if err != nil {
t.Fatalf("GenerateTypeScriptSchema: %v", err)
}
code := string(src)
// Check default value (using camelCase field name)
if !strings.Contains(code, "items: number[] = [];") {
t.Error("Missing slice field with default")
}
// Check length prefix in serialize (using camelCase field name)
if !strings.Contains(code, "view.setUint16(pos, this.items.length, true);") {
t.Error("Missing slice length prefix in serialize")
}
// Check length reading in deserialize
if !strings.Contains(code, "const _lenItems = view.getUint16(pos, true);") {
t.Error("Missing slice length reading in deserialize")
}
// Check array allocation in deserialize (using camelCase field name)
if !strings.Contains(code, "msg.items = new Array(_lenItems);") {
t.Error("Missing slice allocation in deserialize")
}
}
func TestGenerateTypeScript_Enums(t *testing.T) {
schema := parser.Schema{
Enums: []parser.Enum{
{
Name: "Status",
Primitive: parser.KindUint16,
Values: []parser.EnumValue{
{Name: "Pending", Value: "0"},
{Name: "Active", Value: "1"},
{Name: "Done", Value: "2"},
},
},
},
Messages: []parser.Message{
{
PackageName: "test",
Name: "EnumMessage",
Fields: []parser.Field{
{
Name: "Status",
Kind: parser.KindPrimitive,
Primitive: parser.KindUint16,
NamedType: "Status",
},
},
},
},
}
src, err := GenerateTypeScriptSchema(schema, "Test")
if err != nil {
t.Fatalf("GenerateTypeScriptSchema: %v", err)
}
code := string(src)
// Check enum definition
if !strings.Contains(code, "export enum Status {") {
t.Error("Missing enum definition")
}
if !strings.Contains(code, "Pending = 0,") {
t.Error("Missing Pending enum value")
}
if !strings.Contains(code, "Active = 1,") {
t.Error("Missing Active enum value")
}
// Check enum field type (using camelCase field name)
if !strings.Contains(code, "status: Status = 0;") {
t.Error("Missing enum field with correct type")
}
// Check enum serialization (cast to number, using camelCase field name)
if !strings.Contains(code, "view.setUint16(pos, this.status as number, true);") {
t.Error("Missing enum cast in serialize")
}
// Check enum deserialization (cast from number, using camelCase field name)
if !strings.Contains(code, "msg.status = (view.getUint16(pos, true) as Status);") {
t.Error("Missing enum cast in deserialize")
}
}
func TestGenerateTypeScript_Strings(t *testing.T) {
schema := parser.Schema{
Messages: []parser.Message{
{
PackageName: "test",
Name: "StringMessage",
Fields: []parser.Field{
{Name: "Name", Kind: parser.KindPrimitive, Primitive: parser.KindString},
},
},
},
}
src, err := GenerateTypeScriptSchema(schema, "Test")
if err != nil {
t.Fatalf("GenerateTypeScriptSchema: %v", err)
}
code := string(src)
// Check TextEncoder usage
if !strings.Contains(code, "new TextEncoder().encode(") {
t.Error("Missing TextEncoder in serialize")
}
// Check length prefix
if !strings.Contains(code, "view.setUint16(pos, _slen") {
t.Error("Missing string length prefix in serialize")
}
// Check TextDecoder usage
if !strings.Contains(code, "new TextDecoder().decode(") {
t.Error("Missing TextDecoder in deserialize")
}
}
+7
View File
@@ -1 +1,8 @@
module github.com/edmand46/arpack
go 1.23
require (
github.com/google/flatbuffers v25.2.10+incompatible
google.golang.org/protobuf v1.36.11
)
+6
View File
@@ -0,0 +1,6 @@
github.com/google/flatbuffers v25.2.10+incompatible h1:F3vclr7C3HpB1k9mxCGRMXq6FdUalZ6H/pNX4FP1v0Q=
github.com/google/flatbuffers v25.2.10+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
+2 -6
View File
@@ -127,9 +127,7 @@ func parseASTFile(fset *token.FileSet, f *ast.File) (Schema, error) {
schema.Messages = append(schema.Messages, msg)
}
case token.CONST:
if err := parseConstDecls(genDecl, info, enumIndex, &schema); err != nil {
return Schema{}, err
}
parseConstDecls(genDecl, info, enumIndex, &schema)
}
}
@@ -152,7 +150,7 @@ func typeCheckFile(fset *token.FileSet, f *ast.File) (*types.Info, error) {
return info, nil
}
func parseConstDecls(genDecl *ast.GenDecl, info *types.Info, enumIndex map[string]int, schema *Schema) error {
func parseConstDecls(genDecl *ast.GenDecl, info *types.Info, enumIndex map[string]int, schema *Schema) {
for _, spec := range genDecl.Specs {
valueSpec, ok := spec.(*ast.ValueSpec)
if !ok {
@@ -181,8 +179,6 @@ func parseConstDecls(genDecl *ast.GenDecl, info *types.Info, enumIndex map[strin
})
}
}
return nil
}
func parseStruct(
+3 -7
View File
@@ -1,6 +1,5 @@
package messages
// Vector3 — трёхмерный вектор с квантизацией.
type Vector3 struct {
X float32 `pack:"min=-500,max=500,bits=16"`
Y float32 `pack:"min=-500,max=500,bits=16"`
@@ -15,20 +14,17 @@ const (
OpcodeJoinRoom
)
// MoveMessage содержит всё многообразие поддерживаемых типов.
type MoveMessage struct {
Position Vector3 // вложенный тип
Velocity [3]float32 // фиксированный массив без квантизации
Waypoints []Vector3 // слайс вложенных типов
Position Vector3
Velocity [3]float32
Waypoints []Vector3
PlayerID uint32
// 3 подряд bool → упаковываются в 1 байт
Active bool
Visible bool
Ghost bool
Name string
}
// SpawnMessage — пример с целочисленными полями и массивами примитивов.
type SpawnMessage struct {
EntityID uint64
Position Vector3