-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
InputSystem.cs
136 lines (125 loc) · 5.66 KB
/
InputSystem.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
using System.Diagnostics;
using UnityEngine;
using Unity.Entities;
using Unity.NetCode;
using Unity.NetCode.Samples.Common;
namespace Asteroids.Client
{
[UpdateInGroup(typeof(GhostInputSystemGroup))]
public partial class InputSystem : SystemBase
{
private BeginSimulationEntityCommandBufferSystem m_Barrier;
protected override void OnCreate()
{
m_Barrier = World.GetOrCreateSystemManaged<BeginSimulationEntityCommandBufferSystem>();
RequireForUpdate<NetworkStreamInGame>();
// Just to make sure this system does not run in other scenes
RequireForUpdate<LevelComponent>();
}
protected override void OnUpdate()
{
byte left, right, thrust, shoot;
left = right = thrust = shoot = 0;
if (Input.GetKey("left") || TouchInput.GetKey(TouchInput.KeyCode.Left))
left = 1;
if (Input.GetKey("right") || TouchInput.GetKey(TouchInput.KeyCode.Right))
right = 1;
if (Input.GetKey("up") || TouchInput.GetKey(TouchInput.KeyCode.Up))
thrust = 1;
if (Input.GetKey("space") || TouchInput.GetKey(TouchInput.KeyCode.Space))
shoot = 1;
var commandBuffer = m_Barrier.CreateCommandBuffer();
var inputFromEntity = GetBufferLookup<ShipCommandData>();
var networkTime = SystemAPI.GetSingleton<NetworkTime>();
var inputTargetTick = networkTime.ServerTick;
SystemAPI.TryGetSingletonEntity<ShipCommandData>(out var targetEntity);
Job.WithCode(() => {
if (targetEntity == Entity.Null)
{
if (shoot != 0)
{
var req = commandBuffer.CreateEntity();
commandBuffer.AddComponent<PlayerSpawnRequest>(req);
commandBuffer.AddComponent(req, new SendRpcCommandRequest());
}
}
else
{
// If ship, store commands in network command buffer
if (inputFromEntity.HasBuffer(targetEntity))
{
var input = inputFromEntity[targetEntity];
input.AddCommandData(new ShipCommandData{Tick = inputTargetTick, left = left, right = right, thrust = thrust, shoot = shoot});
}
}
}).Schedule();
m_Barrier.AddJobHandleForProducer(Dependency);
}
}
[UpdateInGroup(typeof(GhostInputSystemGroup))]
[WorldSystemFilter(WorldSystemFilterFlags.ThinClientSimulation)]
public partial class ThinInputSystem : SystemBase
{
private BeginSimulationEntityCommandBufferSystem m_Barrier;
private int m_FrameCount;
protected override void OnCreate()
{
m_Barrier = World.GetOrCreateSystemManaged<BeginSimulationEntityCommandBufferSystem>();
RequireForUpdate<NetworkStreamInGame>();
// Just to make sure this system does not run in other scenes
RequireForUpdate<LevelComponent>();
// Give every thin client some randomness.
var rand = Unity.Mathematics.Random.CreateFromIndex((uint) Stopwatch.GetTimestamp());
m_FrameCount = rand.NextInt(100);
}
protected override void OnUpdate()
{
if (SystemAPI.TryGetSingleton<CommandTarget>(out var commandTarget))
{
if (commandTarget.targetEntity == Entity.Null ||
!EntityManager.HasComponent<ShipCommandData>(commandTarget.targetEntity))
{
// No ghosts are spawned, so create a placeholder struct to store the commands in
var ent = EntityManager.CreateEntity();
EntityManager.AddBuffer<ShipCommandData>(ent);
SystemAPI.SetSingleton(new CommandTarget{targetEntity = ent});
}
}
byte left, right, thrust, shoot;
left = right = thrust = shoot = 0;
// Spawn and generate some random inputs
var state = (int) SystemAPI.Time.ElapsedTime % 3;
if (state == 0)
left = 1;
else
thrust = 1;
++m_FrameCount;
if (m_FrameCount % 100 == 0)
{
shoot = 1;
m_FrameCount = 0;
}
var commandBuffer = m_Barrier.CreateCommandBuffer();
var inputFromEntity = GetBufferLookup<ShipCommandData>();
var networkTime = SystemAPI.GetSingleton<NetworkTime>();
var inputTargetTick = networkTime.ServerTick;
SystemAPI.TryGetSingletonEntity<ShipCommandData>(out var targetEntity);
Job.WithCode(() => {
if (shoot != 0)
{
// Special handling for thin clients since we can't tell if the ship is spawned or not
var req = commandBuffer.CreateEntity();
commandBuffer.AddComponent<PlayerSpawnRequest>(req);
commandBuffer.AddComponent(req, new SendRpcCommandRequest());
}
// If ship, store commands in network command buffer
if (inputFromEntity.HasBuffer(targetEntity))
{
var input = inputFromEntity[targetEntity];
input.AddCommandData(new ShipCommandData{Tick = inputTargetTick, left = left, right = right, thrust = thrust, shoot = shoot});
}
}).Schedule();
m_Barrier.AddJobHandleForProducer(Dependency);
}
}
}