22 Commits

Author SHA1 Message Date
edmand46 8851908207 chore: remove unused code 2026-04-01 11:24:55 +03:00
edmand46 c1890216c5 v1.0.0 2026-04-01 10:53:51 +03:00
edmand46 281af49d27 fix: tests.yml 2026-03-26 16:03:52 +03:00
edmand46 3b543e9b63 feat: simplify, C is not nessesary 2026-03-26 13:14:08 +03:00
edmand46 cebe84bce1 feat: C 2026-03-25 19:20:25 +03:00
edmand46 433afeaaa3 fix: linter 2026-03-25 13:20:38 +03:00
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
72 changed files with 10570 additions and 107 deletions
+99
View File
@@ -0,0 +1,99 @@
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 full Go test suite
run: make test
- 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
go run ./cmd/arpack -in testdata/lua/sample.go -out-lua /tmp/gen-lua
test -f /tmp/gen-go/sample_gen.go
test -f /tmp/gen-ts/Sample.gen.ts
test -f /tmp/gen-lua/sample_gen.lua
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.
+38
View File
@@ -0,0 +1,38 @@
UNITY_ASSETS := benchmarks/unity/Assets
.PHONY: test bench-image generate bench size gen-unity
IMAGE := arpack-bench
test:
go test ./...
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."
+189 -22
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,26 @@ 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)
## v1 Contract
ArPack `v1` intentionally supports a narrow schema model:
- Input is a single Go source file.
- Message types must be defined in that same file.
- External package types, pointers, and platform-dependent integer aliases (`int`, `uint`, `uintptr`) are not supported.
- Wire format is stable within `v1.x` for unchanged schemas.
This is a deliberate product boundary for predictable code generation and cross-language compatibility.
## Schema Definition
@@ -79,16 +115,21 @@ 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:** platform-dependent `int`, `uint`, and `uintptr` are not supported. Use explicit widths like `int32`, `uint32`, `int64`, or `uint64`.
**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
@@ -107,6 +148,8 @@ Y float32 `pack:"min=0,max=1,bits=8"` // 1 byte instead of 4
Values are linearly mapped: `encoded = (value - min) / (max - min) * maxUint`.
Quantized values must stay within the declared `[min, max]` range. Generated serializers fail fast on out-of-range or `NaN` inputs instead of silently truncating them.
## Generated Code
### Go
@@ -118,6 +161,8 @@ func (m *MoveMessage) Unmarshal(data []byte) (int, error)
`Marshal` appends to the buffer and returns it. `Unmarshal` reads from the buffer and returns bytes consumed.
**Failure behavior:** generated `Marshal` panics if a string/slice exceeds the `uint16` wire limit or if a quantized value is outside its declared range.
### C#
```csharp
@@ -127,6 +172,60 @@ public static unsafe int Deserialize(byte* buffer, out MoveMessage msg)
Uses unsafe pointers for zero-copy serialization. Returns bytes written/consumed.
**Failure behavior:** generated `Serialize` throws if a string/slice exceeds the `uint16` wire limit or if a quantized value is outside its declared range.
### 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`).
**Failure behavior:** generated `serialize(...)` throws `RangeError` if a string/slice exceeds the `uint16` wire limit or if a quantized value is outside its declared range.
### 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.
- Variable-length fields use `uint16` length prefixes, so `string` byte length and `[]T` element count must not exceed `65535`. Serialization raises an error if the limit is exceeded.
- Quantized values must stay within the declared `[min, max]` range. Serialization raises a Lua error on out-of-range or `NaN` inputs.
- Deserialization raises Lua errors on malformed or truncated input. If you need a recoverable boundary, wrap decode calls in `pcall(...)`.
- Generated file uses snake_case naming (e.g., `messages_gen.lua`) for proper Lua `require()` resolution.
## Wire Format
- Little-endian byte order
@@ -135,12 +234,80 @@ 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`
## Compatibility Guarantees
Within `v1.x`, the following are considered compatibility guarantees for a fixed schema:
- Same field declaration order produces the same wire layout.
- Go, C#, TypeScript, and Lua generators produce identical wire bytes for supported types.
- `string` and `[]T` always use `uint16` length prefixes.
- Consecutive `bool` fields are bit-packed in declaration order, least-significant bit first.
- Enum fields use their declared underlying integer type on the wire.
The following are breaking changes:
- changing field order
- changing a field type
- changing quantization parameters
- changing enum underlying types
- changing how booleans are grouped or how lengths are encoded
## 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)
go test ./parser/... ./generator/...
# Full test suite
make test
# End-to-end cross-language tests (requires dotnet SDK)
go test ./e2e/...
# Benchmarks
go test ./benchmarks/... -bench=. -benchmem
```
## Troubleshooting
- `unknown type "..."`
The field type is not a supported primitive and is not defined in the same schema file.
- `external package types not supported`
Copy the wire-facing type definition into the schema file instead of referencing another package.
- `... exceeds uint16 limit`
A `string` encoded to more than `65535` bytes, or a slice contains more than `65535` elements.
- `quantized value out of range`
The runtime value does not satisfy the declared `pack:"min=...,max=..."` bounds.
+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
}
+237
View File
@@ -0,0 +1,237 @@
// Code generated by arpack. DO NOT EDIT.
package arpackmsg
import (
"encoding/binary"
"errors"
"math"
)
func arpackEnsureUint16Length(length int, context string) uint16 {
if length > 65535 {
panic("arpack: " + context + " exceeds uint16 limit")
}
return uint16(length)
}
func arpackEnsureQuantizedRange(value float64, min float64, max float64, context string) {
if value != value || value < min || value > max {
panic("arpack: quantized value out of range for " + context)
}
}
func (m *Vector3) Marshal(buf []byte) []byte {
arpackEnsureQuantizedRange(float64(m.X), -500, 500, "X")
_qm_X := uint16((m.X - (-500)) / (500 - (-500)) * 65535)
buf = binary.LittleEndian.AppendUint16(buf, _qm_X)
arpackEnsureQuantizedRange(float64(m.Y), -500, 500, "Y")
_qm_Y := uint16((m.Y - (-500)) / (500 - (-500)) * 65535)
buf = binary.LittleEndian.AppendUint16(buf, _qm_Y)
arpackEnsureQuantizedRange(float64(m.Z), -500, 500, "Z")
_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, arpackEnsureUint16Length(len(m.Waypoints), "slice length for 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, arpackEnsureUint16Length(len(m.Name), "string length for 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, arpackEnsureUint16Length(len(m.Tags), "slice length for Tags"))
for _iTags := range m.Tags {
buf = binary.LittleEndian.AppendUint16(buf, arpackEnsureUint16Length(len(m.Tags[_iTags]), "string length for Tags[_iTags]"))
buf = append(buf, m.Tags[_iTags]...)
}
buf = binary.LittleEndian.AppendUint16(buf, arpackEnsureUint16Length(len(m.Data), "slice length for 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,229 @@
// <auto-generated> arpack </auto-generated>
// Code generated by arpack. DO NOT EDIT.
#pragma warning disable CS8500
using System;
using System.Text;
namespace Arpack.Messages
{
internal static class ArpackGenerated
{
internal static ushort EnsureU16Length(int length, string context)
{
if (length > 65535)
{
throw new InvalidOperationException("arpack: " + context + " exceeds uint16 limit");
}
return (ushort)length;
}
internal static void EnsureQuantizedRange(double value, double min, double max, string context)
{
if (double.IsNaN(value) || value < min || value > max)
{
throw new ArgumentOutOfRangeException(context, "arpack: quantized value out of range for " + context);
}
}
}
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;
ArpackGenerated.EnsureQuantizedRange(X, -500, 500, "X");
*(ushort*)ptr = (ushort)((X - (-500f)) / (500f - (-500f)) * 65535f); ptr += 2;
ArpackGenerated.EnsureQuantizedRange(Y, -500, 500, "Y");
*(ushort*)ptr = (ushort)((Y - (-500f)) / (500f - (-500f)) * 65535f); ptr += 2;
ArpackGenerated.EnsureQuantizedRange(Z, -500, 500, "Z");
*(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 _lenWaypoints = ArpackGenerated.EnsureU16Length(Waypoints?.Length ?? 0, "slice length for Waypoints"); *(ushort*)ptr = _lenWaypoints; 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 = ArpackGenerated.EnsureU16Length(_slenName, "string length for Name"); 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 _lenTags = ArpackGenerated.EnsureU16Length(Tags?.Length ?? 0, "slice length for Tags"); *(ushort*)ptr = _lenTags; 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 = ArpackGenerated.EnsureU16Length(_slenTags__iTags_, "string length for Tags[_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 _lenData = ArpackGenerated.EnsureU16Length(Data?.Length ?? 0, "slice length for Data"); *(ushort*)ptr = _lenData; 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())
}
+495 -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,14 @@ 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.
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 +27,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 +40,171 @@ 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("Wire/Go_EQ_CS/"+tc.name, func(t *testing.T) {
goHex := strings.TrimSpace(runHarness(t, goDir, "go", "ser", tc.typ, ""))
csHex := strings.TrimSpace(runHarness(t, csDir, "cs", "ser", tc.typ, ""))
if goHex != csHex {
t.Fatalf("wire drift between Go and C# for %s:\ngo=%s\ncs=%s", tc.typ, goHex, csHex)
}
})
}
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("Wire/Go_EQ_TS/"+tc.name, func(t *testing.T) {
goHex := strings.TrimSpace(runHarness(t, goDir, "go", "ser", tc.typ, ""))
tsHex := strings.TrimSpace(runHarness(t, tsDir, "ts", "ser", tc.typ, ""))
if goHex != tsHex {
t.Fatalf("wire drift between Go and TS for %s:\ngo=%s\nts=%s", tc.typ, goHex, tsHex)
}
})
}
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("Wire/Go_EQ_Lua/"+tc.name, func(t *testing.T) {
goHex := strings.TrimSpace(runHarness(t, goDir, "go", "ser", tc.typ, ""))
luaHex := strings.TrimSpace(runHarness(t, luaDir, "lua", "ser", tc.typ, ""))
if goHex != luaHex {
t.Fatalf("wire drift between Go and Lua for %s:\ngo=%s\nlua=%s", tc.typ, goHex, luaHex)
}
})
}
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 +226,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 +293,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 +386,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 +402,6 @@ func mustRun(t *testing.T, dir string, name string, args ...string) {
}
}
// --- Go harness source ---
const goHarnessSource = `package main
import (
@@ -337,8 +497,6 @@ func main() {
}
`
// --- C# harness source ---
const csHarnessSource = `using System;
using System.Globalization;
using System.Text;
@@ -509,7 +667,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 +676,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 = 50.0
msg.position.y = -100.0
msg.position.z = 0.0
msg.velocity = {1.5, -2.5, 0.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
`
+36 -4
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) {
@@ -13,6 +14,8 @@ func GenerateCSharp(messages []parser.Message, namespace string) ([]byte, error)
func GenerateCSharpSchema(schema parser.Schema, namespace string) ([]byte, error) {
messages := schema.Messages
var b strings.Builder
needsLengthGuards := schemaNeedsLengthGuards(messages)
needsQuantGuards := schemaNeedsQuantRangeGuards(messages)
b.WriteString("// <auto-generated> arpack </auto-generated>\n")
b.WriteString("// Code generated by arpack. DO NOT EDIT.\n")
@@ -26,6 +29,30 @@ func GenerateCSharpSchema(schema parser.Schema, namespace string) ([]byte, error
fmt.Fprintf(&b, "namespace %s\n{\n", namespace)
if needsLengthGuards || needsQuantGuards {
b.WriteString(" internal static class ArpackGenerated\n {\n")
if needsLengthGuards {
b.WriteString(" internal static ushort EnsureU16Length(int length, string context)\n")
b.WriteString(" {\n")
b.WriteString(" if (length > 65535)\n")
b.WriteString(" {\n")
b.WriteString(" throw new InvalidOperationException(\"arpack: \" + context + \" exceeds uint16 limit\");\n")
b.WriteString(" }\n")
b.WriteString(" return (ushort)length;\n")
b.WriteString(" }\n\n")
}
if needsQuantGuards {
b.WriteString(" internal static void EnsureQuantizedRange(double value, double min, double max, string context)\n")
b.WriteString(" {\n")
b.WriteString(" if (double.IsNaN(value) || value < min || value > max)\n")
b.WriteString(" {\n")
b.WriteString(" throw new ArgumentOutOfRangeException(context, \"arpack: quantized value out of range for \" + context);\n")
b.WriteString(" }\n")
b.WriteString(" }\n")
}
b.WriteString(" }\n\n")
}
enumNames := make(map[string]struct{}, len(schema.Enums))
for _, enum := range schema.Enums {
enumNames[enum.Name] = struct{}{}
@@ -150,7 +177,9 @@ func writeCSharpSerializeField(b *strings.Builder, f parser.Field, indent string
}
fmt.Fprintf(b, "%s}\n", indent)
case parser.KindSlice:
fmt.Fprintf(b, "%s*(ushort*)ptr = (ushort)(%s?.Length ?? 0); ptr += 2;\n", indent, f.Name)
lenVar := "_len" + sanitizeVarName(f.Name)
fmt.Fprintf(b, "%sushort %s = ArpackGenerated.EnsureU16Length(%s?.Length ?? 0, %q); *(ushort*)ptr = %s; ptr += 2;\n",
indent, lenVar, f.Name, lengthContext(f), lenVar)
fmt.Fprintf(b, "%sif (%s != null)\n%s{\n", indent, f.Name, indent)
iVar := "_i" + f.Name
fmt.Fprintf(b, "%s for (int %s = 0; %s < %s.Length; %s++)\n%s {\n",
@@ -211,7 +240,8 @@ func writeCSharpSerializePrimitive(
lenVar := "_slen" + sanitizeVarName(access)
fmt.Fprintf(b, "%sint %s = %s != null ? Encoding.UTF8.GetByteCount(%s) : 0;\n",
indent, lenVar, valueExpr, valueExpr)
fmt.Fprintf(b, "%s*(ushort*)ptr = (ushort)%s; ptr += 2;\n", indent, lenVar)
fmt.Fprintf(b, "%s*(ushort*)ptr = ArpackGenerated.EnsureU16Length(%s, %q); ptr += 2;\n",
indent, lenVar, lengthContext(f))
fmt.Fprintf(b, "%sif (%s != null && %s > 0)\n%s{\n", indent, valueExpr, lenVar, indent)
fmt.Fprintf(b, "%s fixed (char* _chars%s = %s)\n%s {\n",
indent, sanitizeVarName(access), valueExpr, indent)
@@ -227,6 +257,8 @@ func writeCSharpSerializePrimitive(
func writeCSharpSerializeQuant(b *strings.Builder, access string, f parser.Field, indent string) error {
q := f.Quant
maxUint := q.MaxUint()
fmt.Fprintf(b, "%sArpackGenerated.EnsureQuantizedRange(%s, %g, %g, %q);\n",
indent, access, q.Min, q.Max, quantContext(f))
if q.Bits == 8 {
fmt.Fprintf(b, "%s*ptr = (byte)((%s - (%gf)) / (%gf - (%gf)) * %gf); ptr += 1;\n",
indent, access, q.Min, q.Max, q.Min, maxUint)
@@ -455,7 +487,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
}
+101 -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"
@@ -253,10 +254,109 @@ func TestGenerateCSharp_Output(t *testing.T) {
if !strings.Contains(code, "public Opcode Code;") {
t.Error("EnvelopeMessage.Code should use generated enum type")
}
if !strings.Contains(code, "internal static class ArpackGenerated") {
t.Error("missing shared ArpackGenerated helper class")
}
if !strings.Contains(code, "EnsureU16Length") {
t.Error("missing uint16 length guard helper")
}
if !strings.Contains(code, "EnsureQuantizedRange") {
t.Error("missing quantized range guard helper")
}
t.Logf("Generated C# (%d bytes):\n%s", len(src), code)
}
func TestGenerateGo_RuntimeGuards(t *testing.T) {
schemaSrc := `package messages
type Quantized struct {
Value float32 ` + "`" + `pack:"min=0,max=1,bits=8"` + "`" + `
}
type LengthLimited struct {
Name string
Items []uint8
}
`
schema, err := parser.ParseSchemaSource(schemaSrc)
if err != nil {
t.Fatalf("ParseSchemaSource: %v", err)
}
src, err := GenerateGoSchema(schema, "messages")
if err != nil {
t.Fatalf("GenerateGoSchema: %v", err)
}
dir := t.TempDir()
if err := os.WriteFile(filepath.Join(dir, "messages.go"), []byte(schemaSrc), 0644); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(dir, "messages_arpack.go"), src, 0644); err != nil {
t.Fatal(err)
}
runtimeTests := `package messages
import (
"strings"
"testing"
)
func expectPanicContaining(t *testing.T, want string, fn func()) {
t.Helper()
defer func() {
r := recover()
if r == nil {
t.Fatalf("expected panic containing %q, got nil", want)
}
if !strings.Contains(r.(string), want) {
t.Fatalf("expected panic containing %q, got %v", want, r)
}
}()
fn()
}
func TestLengthGuard_String(t *testing.T) {
expectPanicContaining(t, "string length for Name exceeds uint16 limit", func() {
msg := LengthLimited{Name: strings.Repeat("a", 65536)}
_ = msg.Marshal(nil)
})
}
func TestLengthGuard_Slice(t *testing.T) {
expectPanicContaining(t, "slice length for Items exceeds uint16 limit", func() {
msg := LengthLimited{Items: make([]uint8, 65536)}
_ = msg.Marshal(nil)
})
}
func TestQuantizedRangeGuard(t *testing.T) {
expectPanicContaining(t, "quantized value out of range for Value", func() {
msg := Quantized{Value: 1.5}
_ = msg.Marshal(nil)
})
}
`
if err := os.WriteFile(filepath.Join(dir, "guards_test.go"), []byte(runtimeTests), 0644); err != nil {
t.Fatal(err)
}
goMod := "module messages\n\ngo 1.21\n"
if err := os.WriteFile(filepath.Join(dir, "go.mod"), []byte(goMod), 0644); err != nil {
t.Fatal(err)
}
cmd := exec.Command("go", "test", "./...")
cmd.Dir = dir
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("go test failed:\n%s", out)
}
}
func TestBoolPacking_GoCode(t *testing.T) {
msgs, err := parser.ParseFile(samplePath)
if err != nil {
+27 -3
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) {
@@ -14,6 +15,8 @@ func GenerateGo(messages []parser.Message, pkgName string) ([]byte, error) {
func GenerateGoSchema(schema parser.Schema, pkgName string) ([]byte, error) {
messages := schema.Messages
var b strings.Builder
needsLengthGuards := schemaNeedsLengthGuards(messages)
needsQuantGuards := schemaNeedsQuantRangeGuards(messages)
b.WriteString("// Code generated by arpack. DO NOT EDIT.\n\n")
fmt.Fprintf(&b, "package %s\n\n", pkgName)
@@ -26,6 +29,23 @@ func GenerateGoSchema(schema parser.Schema, pkgName string) ([]byte, error) {
}
b.WriteString(")\n\n")
if needsLengthGuards {
b.WriteString("func arpackEnsureUint16Length(length int, context string) uint16 {\n")
b.WriteString("\tif length > 65535 {\n")
b.WriteString("\t\tpanic(\"arpack: \" + context + \" exceeds uint16 limit\")\n")
b.WriteString("\t}\n")
b.WriteString("\treturn uint16(length)\n")
b.WriteString("}\n\n")
}
if needsQuantGuards {
b.WriteString("func arpackEnsureQuantizedRange(value float64, min float64, max float64, context string) {\n")
b.WriteString("\tif value != value || value < min || value > max {\n")
b.WriteString("\t\tpanic(\"arpack: quantized value out of range for \" + context)\n")
b.WriteString("\t}\n")
b.WriteString("}\n\n")
}
for _, msg := range messages {
if err := writeGoMessage(&b, msg); err != nil {
return nil, fmt.Errorf("message %s: %w", msg.Name, err)
@@ -119,7 +139,8 @@ func writeGoMarshalField(b *strings.Builder, recv string, f parser.Field, indent
}
fmt.Fprintf(b, "%s}\n", indent)
case parser.KindSlice:
fmt.Fprintf(b, "%sbuf = binary.LittleEndian.AppendUint16(buf, uint16(len(%s)))\n", indent, access)
fmt.Fprintf(b, "%sbuf = binary.LittleEndian.AppendUint16(buf, arpackEnsureUint16Length(len(%s), %q))\n",
indent, access, lengthContext(f))
fmt.Fprintf(b, "%sfor _i%s := range %s {\n", indent, f.Name, access)
elemField := parser.Field{
Name: f.Name + "[_i" + f.Name + "]",
@@ -168,7 +189,8 @@ func writeGoMarshalPrimitive(b *strings.Builder, access string, f parser.Field,
case parser.KindUint64:
fmt.Fprintf(b, "%sbuf = binary.LittleEndian.AppendUint64(buf, %s)\n", indent, valueExpr)
case parser.KindString:
fmt.Fprintf(b, "%sbuf = binary.LittleEndian.AppendUint16(buf, uint16(len(%s)))\n", indent, valueExpr)
fmt.Fprintf(b, "%sbuf = binary.LittleEndian.AppendUint16(buf, arpackEnsureUint16Length(len(%s), %q))\n",
indent, valueExpr, lengthContext(f))
fmt.Fprintf(b, "%sbuf = append(buf, %s...)\n", indent, valueExpr)
}
return nil
@@ -178,6 +200,8 @@ func writeGoMarshalQuant(b *strings.Builder, access string, f parser.Field, inde
q := f.Quant
varName := "_q" + sanitizeVarName(access)
valueExpr := goMarshalValueExpr(access, f)
fmt.Fprintf(b, "%sarpackEnsureQuantizedRange(float64(%s), %g, %g, %q)\n",
indent, valueExpr, q.Min, q.Max, quantContext(f))
if q.Bits == 8 {
fmt.Fprintf(b, "%s%s := uint8((%s - (%g)) / (%g - (%g)) * %g)\n",
indent, varName, valueExpr, q.Min, q.Max, q.Min, q.MaxUint())
+780
View File
@@ -0,0 +1,780 @@
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 ensure_u16_limit(n, context)\n")
b.WriteString(" if n < 0 or n > 65535 then\n")
b.WriteString(" error(string.format(\"arpack: %s exceeds uint16 limit: %d\", context, n))\n")
b.WriteString(" end\n")
b.WriteString(" return n\n")
b.WriteString("end\n\n")
b.WriteString("local function ensure_quant_range(value, min, max, context)\n")
b.WriteString(" if value ~= value or value < min or value > max then\n")
b.WriteString(" error(string.format(\"arpack: quantized value out of range for %s\", context))\n")
b.WriteString(" end\n")
b.WriteString(" return value\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(" ensure_u16_limit(len, \"string length\")\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, "%s%s = ensure_u16_limit(%s, %q)\n", indent, lenVar, lenVar, "slice length for "+luaFieldName(f.Name))
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)
valueVar := "_quant_value_" + sanitizeLuaVarName(access)
fmt.Fprintf(b, "%slocal %s = ensure_quant_range(%s, %g, %g, %q)\n",
indent, valueVar, access, q.Min, q.Max, quantContext(f))
fmt.Fprintf(b, "%slocal %s = math.floor(((%s - (%g)) / (%g - (%g))) * %g)\n",
indent, varName, valueVar, 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 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
}
+767
View File
@@ -0,0 +1,767 @@
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(((_quant_value_msg_position - (-500)) / (500 - (-500))) * 65535)") {
t.Error("Missing truncating quantization code for Lua")
}
if !strings.Contains(luaStr, `ensure_quant_range(msg.position, -500, 500, "Position")`) {
t.Error("Missing quantized range guard for Lua")
}
if strings.Contains(luaStr, "math.floor(((msg.position - (-500)) / (500 - (-500))) * 65535 + 0.5)") {
t.Error("Lua quantization should not round to nearest")
}
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 ensure_u16_limit(n, context)",
"local function ensure_quant_range(value, min, max, context)",
"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")
}
if !strings.Contains(luaStr, "ensure_u16_limit") {
t.Error("Missing uint16 overflow helper")
}
// 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_LengthOverflowGuards(t *testing.T) {
schema := parser.Schema{
Messages: []parser.Message{
{
Name: "LengthLimited",
Fields: []parser.Field{
{Name: "Name", Kind: parser.KindPrimitive, Primitive: parser.KindString},
{
Name: "Items",
Kind: parser.KindSlice,
Elem: &parser.Field{
Kind: parser.KindPrimitive,
Primitive: parser.KindUint8,
},
},
},
},
},
}
lua, err := GenerateLuaSchema(schema, "test")
if err != nil {
t.Fatalf("GenerateLuaSchema failed: %v", err)
}
luaStr := string(lua)
if !strings.Contains(luaStr, `ensure_u16_limit(len, "string length")`) {
t.Error("Missing string length overflow guard")
}
if !strings.Contains(luaStr, `ensure_u16_limit(_len_items, "slice length for items")`) {
t.Error("Missing slice length overflow guard")
}
}
func TestGenerateLua_RuntimeLengthLimits(t *testing.T) {
if _, err := exec.LookPath("luajit"); err != nil {
t.Skip("luajit not found")
}
schema := parser.Schema{
Messages: []parser.Message{
{
Name: "LengthLimited",
Fields: []parser.Field{
{Name: "Name", Kind: parser.KindPrimitive, Primitive: parser.KindString},
{
Name: "Items",
Kind: parser.KindSlice,
Elem: &parser.Field{
Kind: parser.KindPrimitive,
Primitive: parser.KindUint8,
},
},
},
},
},
}
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 emit(label, ok, value)
if ok then
print(label .. ":OK")
else
print(label .. ":" .. tostring(value))
end
end
local msg = messages.new_length_limited()
local ok, res = pcall(messages.serialize_length_limited, msg)
emit("EMPTY", ok, res)
msg.name = string.rep("a", 65535)
ok, res = pcall(messages.serialize_length_limited, msg)
emit("STR_MAX", ok, res)
msg.name = string.rep("a", 65536)
ok, res = pcall(messages.serialize_length_limited, msg)
emit("STR_OVER", ok, res)
msg.name = ""
msg.items = {}
for i = 1, 65535 do
msg.items[i] = 0
end
ok, res = pcall(messages.serialize_length_limited, msg)
emit("SLICE_MAX", ok, res)
msg.items[65536] = 0
ok, res = pcall(messages.serialize_length_limited, msg)
emit("SLICE_OVER", ok, res)
`
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) != 5 {
t.Fatalf("expected 5 output lines, got %d: %q", len(lines), string(out))
}
if lines[0] != "EMPTY:OK" {
t.Fatalf("expected empty serialization to succeed, got %q", lines[0])
}
if lines[1] != "STR_MAX:OK" {
t.Fatalf("expected 65535-byte string serialization to succeed, got %q", lines[1])
}
if !strings.Contains(lines[2], "string length exceeds uint16 limit") {
t.Fatalf("expected string overflow guard, got %q", lines[2])
}
if lines[3] != "SLICE_MAX:OK" {
t.Fatalf("expected 65535-element slice serialization to succeed, got %q", lines[3])
}
if !strings.Contains(lines[4], "slice length for items exceeds uint16 limit") {
t.Fatalf("expected slice overflow guard, got %q", lines[4])
}
}
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])
}
}
func TestGenerateLua_RuntimeQuantizedRangeGuard(t *testing.T) {
if _, err := exec.LookPath("luajit"); err != nil {
t.Skip("luajit not found")
}
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, "messages")
if err != nil {
t.Fatalf("GenerateLuaSchema failed: %v", err)
}
dir := t.TempDir()
if err := os.WriteFile(filepath.Join(dir, "messages_gen.lua"), lua, 0o600); err != nil {
t.Fatalf("write module: %v", err)
}
script := `local messages = require("messages_gen")
local msg = messages.new_with_quantized()
msg.position = 501
local ok, res = pcall(messages.serialize_with_quantized, msg)
if ok then
print("OK")
else
print(res)
end
`
if err := os.WriteFile(filepath.Join(dir, "check.lua"), []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)
}
got := strings.TrimSpace(string(out))
if !strings.Contains(got, "quantized value out of range for Position") {
t.Fatalf("expected quantized range guard, got %q", got)
}
}
+76
View File
@@ -0,0 +1,76 @@
package generator
import "github.com/edmand46/arpack/parser"
func lengthContext(f parser.Field) string {
switch {
case f.Kind == parser.KindSlice:
if f.Name != "" {
return "slice length for " + f.Name
}
return "slice length"
case f.Kind == parser.KindPrimitive && f.Primitive == parser.KindString:
if f.Name != "" {
return "string length for " + f.Name
}
return "string length"
default:
return "length"
}
}
func quantContext(f parser.Field) string {
if f.Name != "" {
return f.Name
}
return "value"
}
func schemaNeedsLengthGuards(messages []parser.Message) bool {
for _, msg := range messages {
for _, f := range msg.Fields {
if fieldNeedsLengthGuard(f) {
return true
}
}
}
return false
}
func fieldNeedsLengthGuard(f parser.Field) bool {
switch f.Kind {
case parser.KindPrimitive:
return f.Primitive == parser.KindString
case parser.KindFixedArray, parser.KindSlice:
if f.Kind == parser.KindSlice {
return true
}
if f.Elem != nil {
return fieldNeedsLengthGuard(*f.Elem)
}
}
return false
}
func schemaNeedsQuantRangeGuards(messages []parser.Message) bool {
for _, msg := range messages {
for _, f := range msg.Fields {
if fieldNeedsQuantRangeGuard(f) {
return true
}
}
}
return false
}
func fieldNeedsQuantRangeGuard(f parser.Field) bool {
switch f.Kind {
case parser.KindPrimitive:
return f.Quant != nil
case parser.KindFixedArray, parser.KindSlice:
if f.Elem != nil {
return fieldNeedsQuantRangeGuard(*f.Elem)
}
}
return false
}
+669
View File
@@ -0,0 +1,669 @@
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
needsLengthGuards := schemaNeedsLengthGuards(messages)
needsQuantGuards := schemaNeedsQuantRangeGuards(messages)
b.WriteString("// <auto-generated> arpack </auto-generated>\n")
b.WriteString("// Code generated by arpack. DO NOT EDIT.\n\n")
if needsLengthGuards {
b.WriteString("const arpackTextEncoder = new TextEncoder();\n")
b.WriteString("const arpackTextDecoder = new TextDecoder();\n\n")
b.WriteString("function arpackEnsureUint16Length(length: number, context: string): number {\n")
b.WriteString(" if (length > 65535) {\n")
b.WriteString(" throw new RangeError(\"arpack: \" + context + \" exceeds uint16 limit\");\n")
b.WriteString(" }\n")
b.WriteString(" return length;\n")
b.WriteString("}\n\n")
}
if needsQuantGuards {
b.WriteString("function arpackEnsureQuantizedRange(value: number, min: number, max: number, context: string): void {\n")
b.WriteString(" if (Number.isNaN(value) || value < min || value > max) {\n")
b.WriteString(" throw new RangeError(\"arpack: quantized value out of range for \" + context);\n")
b.WriteString(" }\n")
b.WriteString("}\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:
lenVar := "_len" + sanitizeVarName(access)
fmt.Fprintf(b, "%sconst %s = arpackEnsureUint16Length(%s.length, %q);\n",
indent, lenVar, access, lengthContext(f))
fmt.Fprintf(b, "%sview.setUint16(pos, %s, true);\n", indent, lenVar)
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)
guardVar := "_slenChecked" + sanitizeVarName(access)
fmt.Fprintf(b, "%sconst %s = arpackTextEncoder.encode(%s);\n", indent, lenVar, valueExpr)
fmt.Fprintf(b, "%sconst %s = arpackEnsureUint16Length(%s.length, %q);\n",
indent, guardVar, lenVar, lengthContext(f))
fmt.Fprintf(b, "%sview.setUint16(pos, %s, true);\n", indent, guardVar)
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)
guardVar := "_slenChecked" + sanitizeVarName(access)
fmt.Fprintf(b, "%sconst %s = arpackTextEncoder.encode(%s);\n", indent, lenVar, valueExpr)
fmt.Fprintf(b, "%sconst %s = arpackEnsureUint16Length(%s.length, %q);\n",
indent, guardVar, lenVar, lengthContext(f))
fmt.Fprintf(b, "%sview.setUint16(pos, %s, true);\n", indent, guardVar)
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)
fmt.Fprintf(b, "%sarpackEnsureQuantizedRange(%s, %g, %g, %q);\n",
indent, access, q.Min, q.Max, quantContext(f))
if q.Bits == 8 {
fmt.Fprintf(b, "%sconst %s = Math.trunc((%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.trunc((%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)
fmt.Fprintf(b, "%sarpackEnsureQuantizedRange(%s, %g, %g, %q);\n",
indent, access, q.Min, q.Max, quantContext(f))
if q.Bits == 8 {
fmt.Fprintf(b, "%sconst %s = Math.trunc((%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.trunc((%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("arpackTextDecoder.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("arpackTextDecoder.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
}
+467
View File
@@ -0,0 +1,467 @@
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.trunc((this.q8 - (0)) / (100 - (0)) * 255)") {
t.Error("Missing 8-bit quantization code")
}
if !strings.Contains(code, `arpackEnsureQuantizedRange(this.q8, 0, 100, "Q8");`) {
t.Error("Missing 8-bit quantized range guard")
}
// Check 16-bit quantization (using camelCase field names)
if !strings.Contains(code, "Math.trunc((this.q16 - (-500)) / (500 - (-500)) * 65535)") {
t.Error("Missing 16-bit quantization code")
}
if !strings.Contains(code, `arpackEnsureQuantizedRange(this.q16, -500, 500, "Q16");`) {
t.Error("Missing 16-bit quantized range guard")
}
// 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, `arpackEnsureUint16Length(this.items.length, "slice length for Items")`) {
t.Error("Missing slice length guard in serialize")
}
if !strings.Contains(code, "view.setUint16(pos, _lenthis_items, true);") {
t.Error("Missing guarded 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, "const arpackTextEncoder = new TextEncoder();") {
t.Error("Missing shared TextEncoder helper")
}
// Check length prefix
if !strings.Contains(code, "view.setUint16(pos, _slen") {
t.Error("Missing string length prefix in serialize")
}
if !strings.Contains(code, `arpackEnsureUint16Length(_slen`) {
t.Error("Missing string length guard in serialize")
}
// Check TextDecoder usage
if !strings.Contains(code, "const arpackTextDecoder = new TextDecoder();") {
t.Error("Missing shared TextDecoder helper")
}
if !strings.Contains(code, "arpackTextDecoder.decode(") {
t.Error("Missing shared TextDecoder in deserialize")
}
}
func TestGenerateTypeScript_LengthAndRangeHelpers(t *testing.T) {
schema := parser.Schema{
Messages: []parser.Message{
{
PackageName: "test",
Name: "LengthAndQuant",
Fields: []parser.Field{
{Name: "Name", Kind: parser.KindPrimitive, Primitive: parser.KindString},
{
Name: "Items",
Kind: parser.KindSlice,
Elem: &parser.Field{
Kind: parser.KindPrimitive,
Primitive: parser.KindUint8,
},
},
{
Name: "Ratio",
Kind: parser.KindPrimitive,
Primitive: parser.KindFloat32,
Quant: &parser.QuantInfo{Min: 0, Max: 1, Bits: 8},
},
},
},
},
}
src, err := GenerateTypeScriptSchema(schema, "Test")
if err != nil {
t.Fatalf("GenerateTypeScriptSchema: %v", err)
}
code := string(src)
if !strings.Contains(code, "function arpackEnsureUint16Length(length: number, context: string): number") {
t.Error("Missing uint16 length helper")
}
if !strings.Contains(code, "function arpackEnsureQuantizedRange(value: number, min: number, max: number, context: string): void") {
t.Error("Missing quantized range helper")
}
if !strings.Contains(code, `arpackEnsureUint16Length(this.items.length, "slice length for Items")`) {
t.Error("Missing slice length guard")
}
if !strings.Contains(code, `arpackEnsureUint16Length(_slen`) {
t.Error("Missing string length helper call")
}
if !strings.Contains(code, `arpackEnsureQuantizedRange(this.ratio, 0, 1, "Ratio");`) {
t.Error("Missing quantized range helper call")
}
}
+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=
+69 -13
View File
@@ -55,6 +55,8 @@ func parseASTFile(fset *token.FileSet, f *ast.File) (Schema, error) {
knownStructs := map[string]bool{}
namedPrimitives := map[string]PrimitiveKind{}
unsupportedNamedPrimitives := map[string]string{}
unresolvedNamedPrimitives := map[string]string{}
var enumOrder []string
for _, decl := range f.Decls {
@@ -73,8 +75,14 @@ func parseASTFile(fset *token.FileSet, f *ast.File) (Schema, error) {
case *ast.StructType:
knownStructs[typeSpec.Name.Name] = true
case *ast.Ident:
switch t.Name {
case "int", "uint", "uintptr":
unsupportedNamedPrimitives[typeSpec.Name.Name] = t.Name
continue
}
primKind, isPrimitive := goPrimitiveKind(t.Name)
if !isPrimitive {
unresolvedNamedPrimitives[typeSpec.Name.Name] = t.Name
continue
}
namedPrimitives[typeSpec.Name.Name] = primKind
@@ -85,6 +93,19 @@ func parseASTFile(fset *token.FileSet, f *ast.File) (Schema, error) {
}
}
for changed := true; changed; {
changed = false
for name, target := range unresolvedNamedPrimitives {
if _, ok := unsupportedNamedPrimitives[name]; ok {
continue
}
if baseType, ok := unsupportedNamedPrimitives[target]; ok {
unsupportedNamedPrimitives[name] = baseType
changed = true
}
}
}
info, err := typeCheckFile(fset, f)
if err != nil {
return Schema{}, err
@@ -119,7 +140,14 @@ func parseASTFile(fset *token.FileSet, f *ast.File) (Schema, error) {
continue
}
msg, err := parseStruct(pkgName, typeSpec.Name.Name, structType, knownStructs, namedPrimitives)
msg, err := parseStruct(
pkgName,
typeSpec.Name.Name,
structType,
knownStructs,
namedPrimitives,
unsupportedNamedPrimitives,
)
if err != nil {
return Schema{}, fmt.Errorf("struct %s: %w", typeSpec.Name.Name, err)
}
@@ -127,9 +155,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 +178,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 +207,6 @@ func parseConstDecls(genDecl *ast.GenDecl, info *types.Info, enumIndex map[strin
})
}
}
return nil
}
func parseStruct(
@@ -191,6 +215,7 @@ func parseStruct(
st *ast.StructType,
knownStructs map[string]bool,
namedPrimitives map[string]PrimitiveKind,
unsupportedNamedPrimitives map[string]string,
) (Message, error) {
msg := Message{PackageName: pkg, Name: name}
@@ -206,7 +231,14 @@ func parseStruct(
}
for _, fieldName := range astField.Names {
field, err := parseFieldType(fieldName.Name, astField.Type, rawTag, knownStructs, namedPrimitives)
field, err := parseFieldType(
fieldName.Name,
astField.Type,
rawTag,
knownStructs,
namedPrimitives,
unsupportedNamedPrimitives,
)
if err != nil {
return Message{}, fmt.Errorf("field %s: %w", fieldName.Name, err)
}
@@ -223,14 +255,22 @@ func parseFieldType(
rawTag string,
knownStructs map[string]bool,
namedPrimitives map[string]PrimitiveKind,
unsupportedNamedPrimitives map[string]string,
) (Field, error) {
switch t := expr.(type) {
case *ast.Ident:
return parsePrimitiveOrNested(name, t.Name, rawTag, knownStructs, namedPrimitives)
return parsePrimitiveOrNested(
name,
t.Name,
rawTag,
knownStructs,
namedPrimitives,
unsupportedNamedPrimitives,
)
case *ast.ArrayType:
if t.Len == nil {
elem, err := parseFieldType("", t.Elt, rawTag, knownStructs, namedPrimitives)
elem, err := parseFieldType("", t.Elt, rawTag, knownStructs, namedPrimitives, unsupportedNamedPrimitives)
if err != nil {
return Field{}, fmt.Errorf("slice element: %w", err)
}
@@ -247,7 +287,7 @@ func parseFieldType(
return Field{}, fmt.Errorf("array length: %w", err)
}
elem, err := parseFieldType("", t.Elt, rawTag, knownStructs, namedPrimitives)
elem, err := parseFieldType("", t.Elt, rawTag, knownStructs, namedPrimitives, unsupportedNamedPrimitives)
if err != nil {
return Field{}, fmt.Errorf("array element: %w", err)
}
@@ -275,9 +315,25 @@ func parsePrimitiveOrNested(
rawTag string,
knownStructs map[string]bool,
namedPrimitives map[string]PrimitiveKind,
unsupportedNamedPrimitives map[string]string,
) (Field, error) {
switch typeName {
case "int", "uint", "uintptr":
return Field{}, fmt.Errorf(
"platform-dependent type %q is not supported; use int32/int64, uint32/uint64, or fixed-size integer IDs instead",
typeName,
)
}
primKind, isPrimitive := goPrimitiveKind(typeName)
if !isPrimitive {
if baseType, ok := unsupportedNamedPrimitives[typeName]; ok {
return Field{}, fmt.Errorf(
"type %q aliases unsupported platform-dependent %q; use int32/int64, uint32/uint64, or fixed-size integer IDs instead",
typeName,
baseType,
)
}
if namedPrimitive, ok := namedPrimitives[typeName]; ok {
return buildPrimitiveField(name, typeName, namedPrimitive, rawTag)
}
@@ -389,7 +445,7 @@ func goPrimitiveKind(name string) (PrimitiveKind, bool) {
return KindInt8, true
case "int16":
return KindInt16, true
case "int32", "int":
case "int32":
return KindInt32, true
case "int64":
return KindInt64, true
@@ -397,7 +453,7 @@ func goPrimitiveKind(name string) (PrimitiveKind, bool) {
return KindUint8, true
case "uint16":
return KindUint16, true
case "uint32", "uint":
case "uint32":
return KindUint32, true
case "uint64":
return KindUint64, true
+90
View File
@@ -1,6 +1,7 @@
package parser
import (
"strings"
"testing"
)
@@ -266,3 +267,92 @@ type Msg struct {
t.Fatal("expected error for unknown nested type, got nil")
}
}
func TestUnsupportedPlatformDependentIntTypes(t *testing.T) {
cases := []struct {
name string
src string
wantErr string
}{
{
name: "direct int field",
src: `package p
type Msg struct {
X int
}
`,
wantErr: `platform-dependent type "int" is not supported`,
},
{
name: "direct uint field",
src: `package p
type Msg struct {
X uint
}
`,
wantErr: `platform-dependent type "uint" is not supported`,
},
{
name: "direct uintptr field",
src: `package p
type Msg struct {
X uintptr
}
`,
wantErr: `platform-dependent type "uintptr" is not supported`,
},
{
name: "alias of int",
src: `package p
type Counter int
type Msg struct {
X Counter
}
`,
wantErr: `type "Counter" aliases unsupported platform-dependent "int"`,
},
{
name: "alias of uint",
src: `package p
type Counter uint
type Msg struct {
X Counter
}
`,
wantErr: `type "Counter" aliases unsupported platform-dependent "uint"`,
},
{
name: "alias of uintptr",
src: `package p
type Handle uintptr
type Msg struct {
X Handle
}
`,
wantErr: `type "Handle" aliases unsupported platform-dependent "uintptr"`,
},
{
name: "transitive alias of int",
src: `package p
type Base int
type Counter Base
type Msg struct {
X Counter
}
`,
wantErr: `type "Counter" aliases unsupported platform-dependent "int"`,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
_, err := ParseSource(tc.src)
if err == nil {
t.Fatal("expected error, got nil")
}
if !strings.Contains(err.Error(), tc.wantErr) {
t.Fatalf("expected error containing %q, got %v", tc.wantErr, err)
}
})
}
}
+39
View File
@@ -0,0 +1,39 @@
package lua
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 uint32
Position Vector3
Health int16
Tags []string
Data []uint8
}
type EnvelopeMessage struct {
Code Opcode
Counter uint8
}
+7 -11
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
Active bool
Visible bool
Ghost bool
Name string
}
// SpawnMessage — пример с целочисленными полями и массивами примитивов.
type SpawnMessage struct {
EntityID uint64
Position Vector3