-
Notifications
You must be signed in to change notification settings - Fork 5
/
OriInput.cs
124 lines (106 loc) · 4.04 KB
/
OriInput.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
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using Terraria.GameInput;
using Terraria.ModLoader;
namespace OriMod;
/// <summary>
/// Net-synced player input, specific to this mod's controls.
/// </summary>
public sealed class OriInput : IEnumerable<Input> {
public readonly Input jump = new(() => PlayerInput.Triggers.Current.Jump && !OriPlayer.Local.controls_blocked);
public readonly Input bash = new(() => OriMod.bashKey.Current && !OriPlayer.Local.controls_blocked);
public readonly Input dash = new(() => OriMod.dashKey.Current && !OriPlayer.Local.controls_blocked);
public readonly Input climb = new(() => OriMod.climbKey.Current && !OriPlayer.Local.controls_blocked);
public readonly Input glide = new(() => OriMod.featherKey.Current && !OriPlayer.Local.controls_blocked);
public readonly Input stomp = new(() => OriMod.stompKey.Current && !OriPlayer.Local.controls_blocked);
public readonly Input charge = new(() => OriMod.chargeKey.Current && !OriPlayer.Local.controls_blocked);
public readonly Input burrow = new(() => OriMod.burrowKey.Current && !OriPlayer.Local.controls_blocked);
public readonly Input leftClick = new(() => PlayerInput.Triggers.Current.MouseLeft && !OriPlayer.Local.controls_blocked);
/// <summary>
/// Read and updates the player's inputs.
/// </summary>
/// <param name="netUpdate"><see langword="true"/> if this would invoke a net update; otherwise, <see langword="false"/></param>
public void Update(out bool netUpdate) {
netUpdate = false;
foreach (Input input in this) {
input.Update(out bool hasChanged);
netUpdate |= hasChanged;
}
}
public void ReadPacket(BinaryReader reader) {
BitVector32 value = new(reader.ReadUInt16());
int i = 0;
foreach (Input input in this) {
input.SetInputValue(value[1 << i++]);
}
}
public void WritePacket(ModPacket packet) {
BitVector32 arr = new();
int i = 0;
foreach (Input input in this) {
arr[1 << i++] = input.GetInputValue();
}
packet.Write((ushort)arr.Data);
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public IEnumerator<Input> GetEnumerator() {
yield return jump;
yield return bash;
yield return dash;
yield return climb;
yield return glide;
yield return stomp;
yield return charge;
yield return burrow;
yield return leftClick;
}
public void ResetInputChangedState() {
foreach (Input input in this) {
input.ResetChanged();
}
}
}
/// <summary>
/// Simplistic OriMod input for syncing between clients
/// </summary>
public class Input {
/// <summary>
/// Create a new <see cref="Input"/> where the read input value is <paramref name="func"/>.
/// </summary>
/// <param name="func">Function to detect a button press as pressed or not</param>
public Input(Func<bool> func) => _func = func ?? throw new ArgumentNullException(nameof(func));
/// <summary>
/// Whether or not the key is currently pressed.
/// </summary>
public bool Current { get; private set; }
/// <summary>
/// Whether or not this is the first frame this key was pressed down.
/// </summary>
public bool JustPressed => Current && _changed;
/// <summary>
/// Whether or not this is the first frame this kew was not pressed down.
/// </summary>
public bool JustReleased => !Current && _changed;
/// <summary>
/// Whether or not the value of <see cref="Current"/> during this frame is different from the previous frame.
/// </summary>
private bool _changed;
/// <summary>
/// Update the values of this input. Returns <see langword="true"/> if the values have changed.
/// </summary>
public void Update(out bool hasChanged) {
SetInputValue(_func());
hasChanged = _changed;
}
private readonly Func<bool> _func;
internal void SetInputValue(bool value) {
bool oldCurrent = Current;
Current = value;
_changed = Current != oldCurrent;
}
internal bool GetInputValue() => Current;
internal bool ResetChanged() => _changed = false;
}