@leejungkiin/awkit 1.7.1 → 1.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/awk.js +576 -84
- package/core/CLAUDE.md +1 -1
- package/core/GEMINI.md +148 -167
- package/core/GEMINI.md.bak +149 -116
- package/core/skill-runtime-manifest.json +3 -0
- package/docs/Claude Fable 5.md +3826 -0
- package/docs/android_kotlin_system_instruction.md +210 -0
- package/docs/brainstorm_ponytail_integration.md +146 -0
- package/docs/brainstorm_smart_setup.md +113 -0
- package/docs/deep-research-report (1).md +293 -0
- package/docs/history/GEMINI.v1.md +135 -0
- package/docs/history/brainstorm_antigravity_unified_architecture.v1.md +105 -0
- package/docs/history/implementation_plan.v1.md +58 -0
- package/package.json +4 -1
- package/scripts/artifact-storage.js +130 -0
- package/scripts/automation-gate.js +35 -2
- package/scripts/claude-plan.js +76 -0
- package/scripts/dependency-manager.js +210 -0
- package/scripts/exec-rtk.js +11 -5
- package/scripts/i18n-helper.js +381 -0
- package/scripts/multi-model-pipeline.js +144 -0
- package/skill-packs/mobile-ios/pack.json +4 -2
- package/skill-packs/reverse-engineering/pack.json +1 -0
- package/skills/CATALOG.md +20 -0
- package/skills/GEMINI.md +9 -1
- package/skills/TRIGGER_INDEX.md +10 -0
- package/skills/ai-music/SKILL.md +275 -0
- package/skills/android-re-analyzer/SKILL.md +238 -0
- package/skills/android-re-analyzer/references/api-extraction-patterns.md +119 -0
- package/skills/android-re-analyzer/references/call-flow-analysis.md +176 -0
- package/skills/android-re-analyzer/references/fernflower-usage.md +115 -0
- package/skills/android-re-analyzer/references/jadx-usage.md +116 -0
- package/skills/android-re-analyzer/references/setup-guide.md +221 -0
- package/skills/android-re-analyzer/scripts/check-deps.sh +129 -0
- package/skills/android-re-analyzer/scripts/decompile.sh +375 -0
- package/skills/android-re-analyzer/scripts/find-api-calls.sh +118 -0
- package/skills/android-re-analyzer/scripts/install-dep.sh +448 -0
- package/skills/animal-island-ui-style/SKILL.md +1450 -0
- package/skills/app-store-review-agent/SKILL.md +164 -0
- package/skills/app-store-review-agent/references/guidelines/README.md +154 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/ai_apps.md +37 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/all_apps.md +50 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/crypto_finance.md +31 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/games.md +31 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/health_fitness.md +31 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/kids.md +27 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/macos.md +38 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/social_ugc.md +32 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/subscription_iap.md +34 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/vpn.md +18 -0
- package/skills/app-store-review-agent/references/rules/design/minimum_functionality.md +96 -0
- package/skills/app-store-review-agent/references/rules/design/sign_in_with_apple.md +54 -0
- package/skills/app-store-review-agent/references/rules/entitlements/unused_entitlements.md +83 -0
- package/skills/app-store-review-agent/references/rules/metadata/accurate_metadata.md +54 -0
- package/skills/app-store-review-agent/references/rules/metadata/apple_trademark.md +99 -0
- package/skills/app-store-review-agent/references/rules/metadata/china_storefront.md +72 -0
- package/skills/app-store-review-agent/references/rules/metadata/competitor_terms.md +56 -0
- package/skills/app-store-review-agent/references/rules/metadata/subscription_metadata.md +81 -0
- package/skills/app-store-review-agent/references/rules/privacy/privacy_manifest.md +84 -0
- package/skills/app-store-review-agent/references/rules/privacy/unnecessary_data.md +60 -0
- package/skills/app-store-review-agent/references/rules/subscription/misleading_pricing.md +63 -0
- package/skills/app-store-review-agent/references/rules/subscription/missing_tos_pp.md +54 -0
- package/skills/awf-ponytail/SKILL.md +91 -0
- package/skills/awf-ponytail-review/SKILL.md +67 -0
- package/skills/awf-session-restore/SKILL.md +3 -3
- package/skills/brainstorm-agent/SKILL.md +11 -2
- package/skills/brainstorm-agent/templates/brief-template.md +8 -0
- package/skills/claude-planner/SKILL.md +47 -0
- package/skills/code-review/SKILL.md +87 -0
- package/skills/expo-game-development/SKILL.md +163 -0
- package/skills/flutter/LICENSE.txt +202 -0
- package/skills/flutter/SKILL.md +127 -0
- package/skills/flutter-project-creater/LICENSE.txt +202 -0
- package/skills/flutter-project-creater/SKILL.md +106 -0
- package/skills/game-developer/SKILL.md +163 -0
- package/skills/game-developer/references/ecs-patterns.md +501 -0
- package/skills/game-developer/references/multiplayer-networking.md +475 -0
- package/skills/game-developer/references/performance-optimization.md +422 -0
- package/skills/game-developer/references/unity-patterns.md +271 -0
- package/skills/game-developer/references/unreal-cpp.md +352 -0
- package/skills/generate-gui-assets/SKILL.md +305 -0
- package/skills/generate-gui-assets/agents/openai.yaml +4 -0
- package/skills/generate-gui-assets/references/catalog-schema.md +58 -0
- package/skills/generate-gui-assets/references/extraction-techniques.md +21 -0
- package/skills/generate-gui-assets/references/prompt-patterns.md +58 -0
- package/skills/generate-gui-assets/scripts/__pycache__/clean_chroma_edges.cpython-311.pyc +0 -0
- package/skills/generate-gui-assets/scripts/build_gui_contact_sheet.py +51 -0
- package/skills/generate-gui-assets/scripts/clean_chroma_edges.py +262 -0
- package/skills/generate-gui-assets/scripts/copy_approved_icons.py +64 -0
- package/skills/generate-gui-assets/scripts/prepare_gui_asset_run.py +91 -0
- package/skills/generate-gui-assets/scripts/suggest_grid_options.py +63 -0
- package/skills/generate-gui-assets/scripts/validate_gui_catalog.py +50 -0
- package/skills/godot-game-development/SKILL.md +142 -0
- package/skills/hatch-pet/LICENSE.txt +201 -0
- package/skills/hatch-pet/SKILL.md +420 -0
- package/skills/hatch-pet/agents/openai.yaml +4 -0
- package/skills/hatch-pet/references/animation-rows.md +29 -0
- package/skills/hatch-pet/references/codex-pet-contract.md +35 -0
- package/skills/hatch-pet/references/qa-rubric.md +60 -0
- package/skills/hatch-pet/scripts/__pycache__/clean_chroma_edges.cpython-311.pyc +0 -0
- package/skills/hatch-pet/scripts/clean_chroma_edges.py +262 -0
- package/skills/hatch-pet/scripts/compose_atlas.py +150 -0
- package/skills/hatch-pet/scripts/derive_running_left_from_running_right.py +143 -0
- package/skills/hatch-pet/scripts/extract_strip_frames.py +323 -0
- package/skills/hatch-pet/scripts/finalize_pet_run.py +382 -0
- package/skills/hatch-pet/scripts/generate_pet_images.py +287 -0
- package/skills/hatch-pet/scripts/inspect_frames.py +246 -0
- package/skills/hatch-pet/scripts/make_contact_sheet.py +96 -0
- package/skills/hatch-pet/scripts/package_custom_pet.py +108 -0
- package/skills/hatch-pet/scripts/pet_job_status.py +117 -0
- package/skills/hatch-pet/scripts/prepare_pet_run.py +673 -0
- package/skills/hatch-pet/scripts/queue_pet_repairs.py +172 -0
- package/skills/hatch-pet/scripts/record_imagegen_result.py +250 -0
- package/skills/hatch-pet/scripts/render_animation_videos.py +134 -0
- package/skills/hatch-pet/scripts/render_animation_videos.sh +5 -0
- package/skills/hatch-pet/scripts/validate_atlas.py +139 -0
- package/skills/i18n-orchestrator/SKILL.md +37 -0
- package/skills/ios-simulator-skill/SKILL.md +390 -0
- package/skills/ios-simulator-skill/scripts/accessibility_audit.py +300 -0
- package/skills/ios-simulator-skill/scripts/app_launcher.py +326 -0
- package/skills/ios-simulator-skill/scripts/app_state_capture.py +400 -0
- package/skills/ios-simulator-skill/scripts/appearance.py +385 -0
- package/skills/ios-simulator-skill/scripts/build_and_test.py +348 -0
- package/skills/ios-simulator-skill/scripts/clipboard.py +103 -0
- package/skills/ios-simulator-skill/scripts/common/__init__.py +61 -0
- package/skills/ios-simulator-skill/scripts/common/cache_utils.py +289 -0
- package/skills/ios-simulator-skill/scripts/common/device_utils.py +462 -0
- package/skills/ios-simulator-skill/scripts/common/env_config.py +35 -0
- package/skills/ios-simulator-skill/scripts/common/hang_pipeline.py +862 -0
- package/skills/ios-simulator-skill/scripts/common/hang_sessions.py +490 -0
- package/skills/ios-simulator-skill/scripts/common/idb_utils.py +180 -0
- package/skills/ios-simulator-skill/scripts/common/screenshot_utils.py +338 -0
- package/skills/ios-simulator-skill/scripts/container.py +668 -0
- package/skills/ios-simulator-skill/scripts/gesture.py +394 -0
- package/skills/ios-simulator-skill/scripts/hang_watcher.py +1533 -0
- package/skills/ios-simulator-skill/scripts/keyboard.py +391 -0
- package/skills/ios-simulator-skill/scripts/localization_audit.py +483 -0
- package/skills/ios-simulator-skill/scripts/location.py +467 -0
- package/skills/ios-simulator-skill/scripts/log_monitor.py +493 -0
- package/skills/ios-simulator-skill/scripts/model_inspector.py +645 -0
- package/skills/ios-simulator-skill/scripts/navigator.py +461 -0
- package/skills/ios-simulator-skill/scripts/privacy_manager.py +310 -0
- package/skills/ios-simulator-skill/scripts/push_notification.py +240 -0
- package/skills/ios-simulator-skill/scripts/screen_mapper.py +296 -0
- package/skills/ios-simulator-skill/scripts/sim_health_check.sh +245 -0
- package/skills/ios-simulator-skill/scripts/sim_list.py +299 -0
- package/skills/ios-simulator-skill/scripts/simctl_boot.py +312 -0
- package/skills/ios-simulator-skill/scripts/simctl_create.py +316 -0
- package/skills/ios-simulator-skill/scripts/simctl_delete.py +357 -0
- package/skills/ios-simulator-skill/scripts/simctl_erase.py +351 -0
- package/skills/ios-simulator-skill/scripts/simctl_shutdown.py +290 -0
- package/skills/ios-simulator-skill/scripts/simulator_selector.py +375 -0
- package/skills/ios-simulator-skill/scripts/status_bar.py +250 -0
- package/skills/ios-simulator-skill/scripts/test_recorder.py +323 -0
- package/skills/ios-simulator-skill/scripts/visual_diff.py +235 -0
- package/skills/ios-simulator-skill/scripts/xcode/__init__.py +13 -0
- package/skills/ios-simulator-skill/scripts/xcode/builder.py +397 -0
- package/skills/ios-simulator-skill/scripts/xcode/cache.py +204 -0
- package/skills/ios-simulator-skill/scripts/xcode/config.py +178 -0
- package/skills/ios-simulator-skill/scripts/xcode/reporter.py +343 -0
- package/skills/ios-simulator-skill/scripts/xcode/xcresult.py +451 -0
- package/skills/ios-visual-qa-strategist/SKILL.md +111 -0
- package/skills/ios-visual-qa-strategist/agents/openai.yaml +4 -0
- package/skills/ios-visual-qa-strategist/references/ios-tool-selection.md +61 -0
- package/skills/ios-visual-qa-strategist/references/minimal-capture-policy.md +56 -0
- package/skills/ios-visual-qa-strategist/references/visual-reasoning-heuristics.md +53 -0
- package/skills/orchestrator/SKILL.md +0 -20
- package/skills/persistent-storage/SKILL.md +55 -0
- package/skills/short-maker/SKILL.md +23 -0
- package/skills/short-maker/scripts/effects.js +56 -0
- package/skills/short-maker/scripts/shortmaker-bridge.js +332 -0
- package/skills/short-maker/scripts/videomix.js +601 -0
- package/skills/short-maker/templates/hyperframes/cinematic-character.template.html +172 -0
- package/skills/short-maker/templates/hyperframes/index.template.html +194 -0
- package/skills/smali-to-kotlin/SKILL.md +128 -0
- package/skills/smali-to-kotlin/examples/getting-started/tech-stack.md +58 -0
- package/skills/smali-to-kotlin/examples/pipeline/data-ui-parity.md +118 -0
- package/skills/smali-to-kotlin/examples/pipeline/scanner-and-bootstrap.md +106 -0
- package/skills/smali-to-kotlin/library-patterns.md +189 -0
- package/skills/smali-to-kotlin/phase-0-discovery.md +128 -0
- package/skills/smali-to-kotlin/phase-1-architecture.md +166 -0
- package/skills/smali-to-kotlin/phase-2-blueprint-ui.md +347 -0
- package/skills/smali-to-kotlin/phase-2-blueprint.md +228 -0
- package/skills/smali-to-kotlin/phase-3-build.md +248 -0
- package/skills/smali-to-kotlin/phase-3-logic-build.md +268 -0
- package/skills/smali-to-kotlin/smali-reading-guide.md +310 -0
- package/skills/smali-to-kotlin/templates/app-map.md +101 -0
- package/skills/smali-to-kotlin/templates/architecture.md +142 -0
- package/skills/smali-to-kotlin/templates/blueprint.md +145 -0
- package/skills/spec-gate/SKILL.md +6 -2
- package/skills/symphony-enforcer/SKILL.md +8 -0
- package/skills/symphony-enforcer/examples/mindful-stop.md +2 -0
- package/skills/symphony-enforcer/examples/three-phase.md +16 -0
- package/skills/symphony-enforcer/examples/trigger-points.md +7 -1
- package/skills/unity-game-development/SKILL.md +231 -0
- package/skills/video-edit/SKILL.md +36 -0
- package/skills/video-edit/scripts/video_edit.py +324 -0
- package/templates/project-identity/android.json +2 -2
- package/templates/project-identity/backend-nestjs.json +2 -2
- package/templates/project-identity/expo.json +2 -2
- package/templates/project-identity/ios.json +2 -2
- package/templates/project-identity/web-nextjs.json +2 -2
- package/templates/setup-mapping.json +48 -0
- package/templates/specs/design-template.md +161 -71
- package/templates/specs/requirements-template.md +65 -133
- package/templates/specs/task-spec-template.xml +3 -0
- package/workflows/_uncategorized/critic.md +40 -0
- package/workflows/_uncategorized/git-rebase-flow.md +81 -0
- package/workflows/_uncategorized/image-gen.md +118 -0
- package/workflows/_uncategorized/multi-model-pipeline.md +60 -0
- package/workflows/_uncategorized/pixel-gen.md +86 -0
- package/workflows/_uncategorized/pixel-setup.md +90 -0
- package/workflows/_uncategorized/ponytail-review.md +59 -0
- package/workflows/_uncategorized/reverse-android-build.md +222 -0
- package/workflows/_uncategorized/reverse-android-design.md +139 -0
- package/workflows/_uncategorized/reverse-android-discover.md +150 -0
- package/workflows/_uncategorized/reverse-android-scan.md +158 -0
- package/workflows/_uncategorized/reverse-android.md +143 -0
- package/workflows/_uncategorized/reverse-ios-build.md +240 -0
- package/workflows/_uncategorized/reverse-ios-design.md +112 -0
- package/workflows/_uncategorized/reverse-ios-discover.md +120 -0
- package/workflows/_uncategorized/reverse-ios-scan.md +155 -0
- package/workflows/_uncategorized/reverse-ios.md +152 -0
- package/workflows/_uncategorized/safety-router.md +34 -0
- package/workflows/_uncategorized/teach.md +89 -0
- package/workflows/_uncategorized/verify-ui.md +53 -0
- package/workflows/_uncategorized/visualize-screenshots.md +34 -0
- package/workflows/ads/ads-analyst.md +201 -0
- package/workflows/ads/ads-audit.md +106 -0
- package/workflows/ads/ads-optimize.md +97 -0
- package/workflows/ads/ads-targeting.md +241 -0
- package/workflows/ads/adsExpert.md +160 -0
- package/workflows/ads/smali-ads-config.md +400 -0
- package/workflows/ads/smali-ads-flow.md +331 -0
- package/workflows/ads/smali-ads-interstitial.md +377 -0
- package/workflows/ads/smali-ads-native.md +382 -0
- package/workflows/context/teach.md +89 -0
- package/workflows/gitnexus.md +8 -8
- package/workflows/lifecycle/brainstorm.md +43 -0
- package/workflows/lifecycle/code.md +5 -0
- package/workflows/lifecycle/init.md +23 -5
- package/workflows/lifecycle/multi-model-pipeline.md +60 -0
- package/workflows/quality/ponytail-review.md +59 -0
- package/workflows/roles/critic.md +40 -0
- package/workflows/roles/safety-router.md +34 -0
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
# Multiplayer Networking
|
|
2
|
+
|
|
3
|
+
## Client-Server Architecture
|
|
4
|
+
|
|
5
|
+
```csharp
|
|
6
|
+
// Server-authoritative model
|
|
7
|
+
public class NetworkPlayer
|
|
8
|
+
{
|
|
9
|
+
public int PlayerId { get; set; }
|
|
10
|
+
public Vector3 Position { get; set; }
|
|
11
|
+
public Quaternion Rotation { get; set; }
|
|
12
|
+
public float Health { get; set; }
|
|
13
|
+
|
|
14
|
+
// Server validates all actions
|
|
15
|
+
public bool TryMove(Vector3 newPosition, float deltaTime)
|
|
16
|
+
{
|
|
17
|
+
float maxDistance = MoveSpeed * deltaTime * 1.1f; // 10% tolerance
|
|
18
|
+
|
|
19
|
+
if (Vector3.Distance(Position, newPosition) > maxDistance)
|
|
20
|
+
{
|
|
21
|
+
// Client sent invalid movement - possible cheat
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
Position = newPosition;
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Server
|
|
31
|
+
public class GameServer
|
|
32
|
+
{
|
|
33
|
+
private Dictionary<int, NetworkPlayer> players = new();
|
|
34
|
+
|
|
35
|
+
public void ProcessPlayerInput(int playerId, PlayerInput input)
|
|
36
|
+
{
|
|
37
|
+
if (!players.TryGetValue(playerId, out NetworkPlayer player))
|
|
38
|
+
return;
|
|
39
|
+
|
|
40
|
+
// Server processes input
|
|
41
|
+
Vector3 newPosition = player.Position + input.Movement;
|
|
42
|
+
|
|
43
|
+
if (player.TryMove(newPosition, Time.deltaTime))
|
|
44
|
+
{
|
|
45
|
+
// Broadcast to other clients
|
|
46
|
+
BroadcastPlayerState(player);
|
|
47
|
+
}
|
|
48
|
+
else
|
|
49
|
+
{
|
|
50
|
+
// Send authoritative correction
|
|
51
|
+
SendPositionCorrection(playerId, player.Position);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## State Synchronization
|
|
58
|
+
|
|
59
|
+
```csharp
|
|
60
|
+
// Network state with interpolation
|
|
61
|
+
public class NetworkTransform
|
|
62
|
+
{
|
|
63
|
+
// Circular buffer for state history
|
|
64
|
+
private struct State
|
|
65
|
+
{
|
|
66
|
+
public float Timestamp;
|
|
67
|
+
public Vector3 Position;
|
|
68
|
+
public Quaternion Rotation;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private State[] stateBuffer = new State[32];
|
|
72
|
+
private int bufferIndex = 0;
|
|
73
|
+
|
|
74
|
+
public void ReceiveState(float timestamp, Vector3 position, Quaternion rotation)
|
|
75
|
+
{
|
|
76
|
+
stateBuffer[bufferIndex] = new State
|
|
77
|
+
{
|
|
78
|
+
Timestamp = timestamp,
|
|
79
|
+
Position = position,
|
|
80
|
+
Rotation = rotation
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
bufferIndex = (bufferIndex + 1) % stateBuffer.Length;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
public void Interpolate(float renderTime)
|
|
87
|
+
{
|
|
88
|
+
// Find two states to interpolate between
|
|
89
|
+
State from = default;
|
|
90
|
+
State to = default;
|
|
91
|
+
|
|
92
|
+
for (int i = 0; i < stateBuffer.Length; i++)
|
|
93
|
+
{
|
|
94
|
+
if (stateBuffer[i].Timestamp <= renderTime)
|
|
95
|
+
from = stateBuffer[i];
|
|
96
|
+
else
|
|
97
|
+
{
|
|
98
|
+
to = stateBuffer[i];
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (from.Timestamp == 0 || to.Timestamp == 0)
|
|
104
|
+
return;
|
|
105
|
+
|
|
106
|
+
// Interpolate between states
|
|
107
|
+
float t = (renderTime - from.Timestamp) / (to.Timestamp - from.Timestamp);
|
|
108
|
+
t = Mathf.Clamp01(t);
|
|
109
|
+
|
|
110
|
+
transform.position = Vector3.Lerp(from.Position, to.Position, t);
|
|
111
|
+
transform.rotation = Quaternion.Slerp(from.Rotation, to.Rotation, t);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Client-Side Prediction
|
|
117
|
+
|
|
118
|
+
```csharp
|
|
119
|
+
public class PredictivePlayer : MonoBehaviour
|
|
120
|
+
{
|
|
121
|
+
private struct InputState
|
|
122
|
+
{
|
|
123
|
+
public int SequenceNumber;
|
|
124
|
+
public float Timestamp;
|
|
125
|
+
public Vector3 Movement;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
private Queue<InputState> pendingInputs = new Queue<InputState>();
|
|
129
|
+
private int sequenceNumber = 0;
|
|
130
|
+
private Vector3 predictedPosition;
|
|
131
|
+
|
|
132
|
+
void Update()
|
|
133
|
+
{
|
|
134
|
+
// Gather input
|
|
135
|
+
Vector3 movement = new Vector3(
|
|
136
|
+
Input.GetAxis("Horizontal"),
|
|
137
|
+
0,
|
|
138
|
+
Input.GetAxis("Vertical")
|
|
139
|
+
) * moveSpeed * Time.deltaTime;
|
|
140
|
+
|
|
141
|
+
// Create input state
|
|
142
|
+
InputState input = new InputState
|
|
143
|
+
{
|
|
144
|
+
SequenceNumber = sequenceNumber++,
|
|
145
|
+
Timestamp = Time.time,
|
|
146
|
+
Movement = movement
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// Send to server
|
|
150
|
+
SendInputToServer(input);
|
|
151
|
+
|
|
152
|
+
// Apply locally (prediction)
|
|
153
|
+
predictedPosition += movement;
|
|
154
|
+
transform.position = predictedPosition;
|
|
155
|
+
|
|
156
|
+
// Store for reconciliation
|
|
157
|
+
pendingInputs.Enqueue(input);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
public void ReceiveServerState(int lastProcessedInput, Vector3 serverPosition)
|
|
161
|
+
{
|
|
162
|
+
// Remove acknowledged inputs
|
|
163
|
+
while (pendingInputs.Count > 0 && pendingInputs.Peek().SequenceNumber <= lastProcessedInput)
|
|
164
|
+
{
|
|
165
|
+
pendingInputs.Dequeue();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Start from server position
|
|
169
|
+
predictedPosition = serverPosition;
|
|
170
|
+
|
|
171
|
+
// Replay pending inputs (reconciliation)
|
|
172
|
+
foreach (var input in pendingInputs)
|
|
173
|
+
{
|
|
174
|
+
predictedPosition += input.Movement;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Smooth correction if needed
|
|
178
|
+
if (Vector3.Distance(transform.position, predictedPosition) > 0.1f)
|
|
179
|
+
{
|
|
180
|
+
// Snap or smooth based on distance
|
|
181
|
+
transform.position = predictedPosition;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Lag Compensation (Server-Side Rewind)
|
|
188
|
+
|
|
189
|
+
```csharp
|
|
190
|
+
public class LagCompensation
|
|
191
|
+
{
|
|
192
|
+
private struct HistoricalState
|
|
193
|
+
{
|
|
194
|
+
public float Timestamp;
|
|
195
|
+
public Vector3 Position;
|
|
196
|
+
public Quaternion Rotation;
|
|
197
|
+
public Bounds Hitbox;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
private Dictionary<int, Queue<HistoricalState>> playerHistory = new();
|
|
201
|
+
private const float MaxHistoryTime = 1.0f; // 1 second of history
|
|
202
|
+
|
|
203
|
+
public void RecordState(int playerId, Vector3 position, Quaternion rotation, Bounds hitbox)
|
|
204
|
+
{
|
|
205
|
+
if (!playerHistory.ContainsKey(playerId))
|
|
206
|
+
playerHistory[playerId] = new Queue<HistoricalState>();
|
|
207
|
+
|
|
208
|
+
var queue = playerHistory[playerId];
|
|
209
|
+
|
|
210
|
+
// Add current state
|
|
211
|
+
queue.Enqueue(new HistoricalState
|
|
212
|
+
{
|
|
213
|
+
Timestamp = Time.time,
|
|
214
|
+
Position = position,
|
|
215
|
+
Rotation = rotation,
|
|
216
|
+
Hitbox = hitbox
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
// Remove old states
|
|
220
|
+
while (queue.Count > 0 && Time.time - queue.Peek().Timestamp > MaxHistoryTime)
|
|
221
|
+
{
|
|
222
|
+
queue.Dequeue();
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
public bool ProcessHitscan(int shooterPlayerId, float clientTimestamp, Ray ray, out int hitPlayerId)
|
|
227
|
+
{
|
|
228
|
+
// Rewind to client's timestamp
|
|
229
|
+
float targetTime = clientTimestamp; // Shooter's perceived time
|
|
230
|
+
|
|
231
|
+
foreach (var kvp in playerHistory)
|
|
232
|
+
{
|
|
233
|
+
int playerId = kvp.Key;
|
|
234
|
+
if (playerId == shooterPlayerId) continue; // Don't shoot self
|
|
235
|
+
|
|
236
|
+
// Find state at target time
|
|
237
|
+
HistoricalState state = GetStateAtTime(kvp.Value, targetTime);
|
|
238
|
+
|
|
239
|
+
// Check raycast against historical hitbox
|
|
240
|
+
if (state.Hitbox.IntersectRay(ray))
|
|
241
|
+
{
|
|
242
|
+
hitPlayerId = playerId;
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
hitPlayerId = -1;
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
private HistoricalState GetStateAtTime(Queue<HistoricalState> history, float targetTime)
|
|
252
|
+
{
|
|
253
|
+
HistoricalState closest = default;
|
|
254
|
+
float minDelta = float.MaxValue;
|
|
255
|
+
|
|
256
|
+
foreach (var state in history)
|
|
257
|
+
{
|
|
258
|
+
float delta = Mathf.Abs(state.Timestamp - targetTime);
|
|
259
|
+
if (delta < minDelta)
|
|
260
|
+
{
|
|
261
|
+
minDelta = delta;
|
|
262
|
+
closest = state;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return closest;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## Network Message Serialization
|
|
272
|
+
|
|
273
|
+
```csharp
|
|
274
|
+
using System;
|
|
275
|
+
using System.IO;
|
|
276
|
+
|
|
277
|
+
// Efficient binary serialization
|
|
278
|
+
public class NetworkWriter
|
|
279
|
+
{
|
|
280
|
+
private MemoryStream stream = new MemoryStream();
|
|
281
|
+
private BinaryWriter writer;
|
|
282
|
+
|
|
283
|
+
public NetworkWriter()
|
|
284
|
+
{
|
|
285
|
+
writer = new BinaryWriter(stream);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
public void WriteInt(int value) => writer.Write(value);
|
|
289
|
+
public void WriteFloat(float value) => writer.Write(value);
|
|
290
|
+
public void WriteBool(bool value) => writer.Write(value);
|
|
291
|
+
public void WriteString(string value) => writer.Write(value);
|
|
292
|
+
|
|
293
|
+
public void WriteVector3(Vector3 value)
|
|
294
|
+
{
|
|
295
|
+
writer.Write(value.x);
|
|
296
|
+
writer.Write(value.y);
|
|
297
|
+
writer.Write(value.z);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Compressed vector (16-bit per component)
|
|
301
|
+
public void WriteVector3Compressed(Vector3 value, float min, float max)
|
|
302
|
+
{
|
|
303
|
+
writer.Write(CompressFloat(value.x, min, max));
|
|
304
|
+
writer.Write(CompressFloat(value.y, min, max));
|
|
305
|
+
writer.Write(CompressFloat(value.z, min, max));
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
private ushort CompressFloat(float value, float min, float max)
|
|
309
|
+
{
|
|
310
|
+
float normalized = Mathf.Clamp01((value - min) / (max - min));
|
|
311
|
+
return (ushort)(normalized * ushort.MaxValue);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
public byte[] ToArray() => stream.ToArray();
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
public class NetworkReader
|
|
318
|
+
{
|
|
319
|
+
private BinaryReader reader;
|
|
320
|
+
|
|
321
|
+
public NetworkReader(byte[] data)
|
|
322
|
+
{
|
|
323
|
+
reader = new BinaryReader(new MemoryStream(data));
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
public int ReadInt() => reader.ReadInt32();
|
|
327
|
+
public float ReadFloat() => reader.ReadSingle();
|
|
328
|
+
public bool ReadBool() => reader.ReadBoolean();
|
|
329
|
+
public string ReadString() => reader.ReadString();
|
|
330
|
+
|
|
331
|
+
public Vector3 ReadVector3()
|
|
332
|
+
{
|
|
333
|
+
return new Vector3(
|
|
334
|
+
reader.ReadSingle(),
|
|
335
|
+
reader.ReadSingle(),
|
|
336
|
+
reader.ReadSingle()
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
public Vector3 ReadVector3Compressed(float min, float max)
|
|
341
|
+
{
|
|
342
|
+
return new Vector3(
|
|
343
|
+
DecompressFloat(reader.ReadUInt16(), min, max),
|
|
344
|
+
DecompressFloat(reader.ReadUInt16(), min, max),
|
|
345
|
+
DecompressFloat(reader.ReadUInt16(), min, max)
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
private float DecompressFloat(ushort value, float min, float max)
|
|
350
|
+
{
|
|
351
|
+
float normalized = value / (float)ushort.MaxValue;
|
|
352
|
+
return min + normalized * (max - min);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
## Interest Management (Relevancy)
|
|
358
|
+
|
|
359
|
+
```csharp
|
|
360
|
+
public class InterestManager
|
|
361
|
+
{
|
|
362
|
+
private Dictionary<int, Vector3> playerPositions = new();
|
|
363
|
+
private float relevancyRadius = 100f;
|
|
364
|
+
|
|
365
|
+
public HashSet<int> GetRelevantPlayers(int playerId)
|
|
366
|
+
{
|
|
367
|
+
if (!playerPositions.TryGetValue(playerId, out Vector3 playerPos))
|
|
368
|
+
return new HashSet<int>();
|
|
369
|
+
|
|
370
|
+
HashSet<int> relevant = new HashSet<int>();
|
|
371
|
+
|
|
372
|
+
foreach (var kvp in playerPositions)
|
|
373
|
+
{
|
|
374
|
+
if (kvp.Key == playerId) continue;
|
|
375
|
+
|
|
376
|
+
float distance = Vector3.Distance(playerPos, kvp.Value);
|
|
377
|
+
if (distance <= relevancyRadius)
|
|
378
|
+
{
|
|
379
|
+
relevant.Add(kvp.Key);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
return relevant;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
public void BroadcastToRelevant(int senderId, byte[] message)
|
|
387
|
+
{
|
|
388
|
+
var recipients = GetRelevantPlayers(senderId);
|
|
389
|
+
|
|
390
|
+
foreach (int recipientId in recipients)
|
|
391
|
+
{
|
|
392
|
+
SendMessage(recipientId, message);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
## Delta Compression
|
|
399
|
+
|
|
400
|
+
```csharp
|
|
401
|
+
public class DeltaCompressor
|
|
402
|
+
{
|
|
403
|
+
private Dictionary<int, NetworkPlayer> lastSentState = new();
|
|
404
|
+
|
|
405
|
+
public byte[] CompressState(NetworkPlayer current)
|
|
406
|
+
{
|
|
407
|
+
if (!lastSentState.TryGetValue(current.PlayerId, out NetworkPlayer previous))
|
|
408
|
+
{
|
|
409
|
+
// First time - send full state
|
|
410
|
+
return SerializeFullState(current);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
NetworkWriter writer = new NetworkWriter();
|
|
414
|
+
byte flags = 0;
|
|
415
|
+
|
|
416
|
+
// Only send changed fields
|
|
417
|
+
if (Vector3.Distance(current.Position, previous.Position) > 0.01f)
|
|
418
|
+
{
|
|
419
|
+
flags |= 1 << 0; // Position changed
|
|
420
|
+
writer.WriteVector3Compressed(current.Position, -1000f, 1000f);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
if (Quaternion.Angle(current.Rotation, previous.Rotation) > 1f)
|
|
424
|
+
{
|
|
425
|
+
flags |= 1 << 1; // Rotation changed
|
|
426
|
+
writer.WriteQuaternionCompressed(current.Rotation);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (Mathf.Abs(current.Health - previous.Health) > 0.1f)
|
|
430
|
+
{
|
|
431
|
+
flags |= 1 << 2; // Health changed
|
|
432
|
+
writer.WriteFloat(current.Health);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// Prepend flags
|
|
436
|
+
byte[] data = writer.ToArray();
|
|
437
|
+
byte[] result = new byte[data.Length + 1];
|
|
438
|
+
result[0] = flags;
|
|
439
|
+
Array.Copy(data, 0, result, 1, data.Length);
|
|
440
|
+
|
|
441
|
+
// Update last sent state
|
|
442
|
+
lastSentState[current.PlayerId] = current;
|
|
443
|
+
|
|
444
|
+
return result;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
## Network Performance Best Practices
|
|
450
|
+
|
|
451
|
+
**Bandwidth optimization:**
|
|
452
|
+
- Compress position/rotation data
|
|
453
|
+
- Use delta compression
|
|
454
|
+
- Implement relevancy system
|
|
455
|
+
- Limit update rate based on distance
|
|
456
|
+
- Batch multiple updates into single packet
|
|
457
|
+
|
|
458
|
+
**Latency optimization:**
|
|
459
|
+
- Client-side prediction for local player
|
|
460
|
+
- Server reconciliation for corrections
|
|
461
|
+
- Entity interpolation for other players
|
|
462
|
+
- Lag compensation for hitscan weapons
|
|
463
|
+
|
|
464
|
+
**Target metrics:**
|
|
465
|
+
- Latency: < 100ms
|
|
466
|
+
- Tick rate: 20-60 Hz (depends on game type)
|
|
467
|
+
- Packet size: < 1200 bytes (avoid fragmentation)
|
|
468
|
+
- Update rate: 10-20 Hz for distant objects, 60 Hz for nearby
|
|
469
|
+
|
|
470
|
+
**Security considerations:**
|
|
471
|
+
- Server-authoritative for all game logic
|
|
472
|
+
- Validate all client inputs
|
|
473
|
+
- Rate limiting to prevent flooding
|
|
474
|
+
- Encrypt sensitive data
|
|
475
|
+
- Anti-cheat measures (sanity checks, statistical analysis)
|