Skip to content

Commit bf4168d

Browse files
committed
Add groundwork for player states.
1 parent bc732d2 commit bf4168d

15 files changed

+520
-4
lines changed

Runtime/Gamelogic/VisualScriptingEventNames.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,7 @@ public static class VisualScriptingEventNames
2222
public const string LampEvent = "LampEvent";
2323
public const string SwitchEvent = "SwitchEvent";
2424
public const string CoilEvent = "CoilEvent";
25+
public const string CurrentPlayerChanged = "CurrentPlayerChanged";
26+
public const string CurrentPlayerStateChanged = "CurrentPlayerStateChanged";
2527
}
2628
}

Runtime/Gamelogic/VisualScriptingGamelogicEngine.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
// ReSharper disable InconsistentNaming
1818

1919
using System;
20+
using System.Collections.Generic;
2021
using System.Linq;
2122
using Unity.VisualScripting;
2223
using UnityEngine;
@@ -30,6 +31,8 @@ public class VisualScriptingGamelogicEngine : MonoBehaviour, IGamelogicEngine
3031
{
3132
public string Name => "Visual Scripting Gamelogic Engine";
3233

34+
public List<VisualScriptingPlayerStatePropertyDefinition> PlayerStateDefinition;
35+
3336
[Tooltip("The switches that are exposed in the Visual Scripting nodes.")]
3437
public VisualScriptingSwitch[] Switches;
3538
public VisualScriptingCoil[] Coils;
@@ -56,6 +59,51 @@ public class VisualScriptingGamelogicEngine : MonoBehaviour, IGamelogicEngine
5659
[NonSerialized] public BallManager BallManager;
5760
[NonSerialized] private Player _player;
5861

62+
[NonSerialized] private int _currentPlayer;
63+
[NonSerialized] private readonly Dictionary<int, VisualScriptingPlayerState> _playerStates = new ();
64+
65+
public VisualScriptingPlayerState CurrentPlayerState {
66+
get {
67+
if (!_playerStates.ContainsKey(_currentPlayer)) {
68+
throw new InvalidOperationException("Must create a player state before accessing it!");
69+
}
70+
return _playerStates[_currentPlayer];
71+
}
72+
}
73+
74+
public int CurrentPlayer {
75+
get => _currentPlayer;
76+
set {
77+
if (!_playerStates.ContainsKey(value)) {
78+
Debug.LogError($"Cannot change to non-existing player {value}.");
79+
return;
80+
}
81+
var previousPlayer = _currentPlayer;
82+
_currentPlayer = value;
83+
if (previousPlayer != _currentPlayer) {
84+
EventBus.Trigger(VisualScriptingEventNames.CurrentPlayerChanged, EventArgs.Empty);
85+
}
86+
}
87+
}
88+
89+
public void CreatePlayerState(int playerId)
90+
{
91+
if (_playerStates.ContainsKey(playerId)) {
92+
Debug.LogWarning($"Tried to create new player state for existing state {playerId}, skipping.");
93+
return;
94+
}
95+
var playerState = new VisualScriptingPlayerState(playerId);
96+
foreach (var propertyDefinition in PlayerStateDefinition) {
97+
playerState.AddProperty(propertyDefinition.Instantiate());
98+
}
99+
_playerStates[playerId] = playerState;
100+
101+
// switch to this state if current state is invalid
102+
if (!_playerStates.ContainsKey(_currentPlayer)) {
103+
CurrentPlayer = playerId;
104+
}
105+
}
106+
59107
public void OnInit(Player player, TableApi tableApi, BallManager ballManager)
60108
{
61109
_player = player;
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// Visual Pinball Engine
2+
// Copyright (C) 2022 freezy and VPE Team
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
17+
using System;
18+
using System.Collections.Generic;
19+
using Unity.VisualScripting;
20+
21+
namespace VisualPinball.Unity.VisualScripting
22+
{
23+
public class VisualScriptingPlayerState
24+
{
25+
public readonly int Id;
26+
27+
private readonly Dictionary<string, VisualScriptingPlayerStateProperty> _properties = new();
28+
29+
public VisualScriptingPlayerState(int id)
30+
{
31+
Id = id;
32+
}
33+
34+
public void AddProperty(VisualScriptingPlayerStateProperty property)
35+
{
36+
_properties[property.Name] = property;
37+
}
38+
39+
public T Get<T>(string propertyName) where T : class
40+
{
41+
if (!_properties.ContainsKey(propertyName)) {
42+
throw new ArgumentException($"No such property name ({propertyName}).", nameof(propertyName));
43+
}
44+
if (_properties[propertyName].Type != typeof(T)) {
45+
throw new InvalidOperationException($"Property \"{propertyName}\" is of type {_properties[propertyName].Type}, but you asked for a {typeof(T)}.");
46+
}
47+
48+
return _properties[propertyName].Get<T>();
49+
}
50+
51+
public void Set<T>(string propertyName, T value) where T : class
52+
{
53+
if (!_properties.ContainsKey(propertyName)) {
54+
throw new ArgumentException($"No such property name ({propertyName}).", nameof(propertyName));
55+
}
56+
if (_properties[propertyName].Type != value.GetType()) {
57+
throw new ArgumentException($"Property \"{propertyName}\" is of type {_properties[propertyName].Type}, but you provided a {value.GetType()}.", nameof(value));
58+
}
59+
60+
var currentValue = _properties[propertyName].Get<T>();
61+
_properties[propertyName].Set(value);
62+
63+
if (currentValue != value) {
64+
EventBus.Trigger(VisualScriptingEventNames.CurrentPlayerStateChanged, new PlayerStateChangedArgs(propertyName));
65+
}
66+
}
67+
68+
internal bool Has<T>(string propertyName) => _properties.ContainsKey(propertyName) && typeof(T) == _properties[propertyName].Type;
69+
}
70+
71+
public class Integer
72+
{
73+
private readonly int _value;
74+
public Integer(int value)
75+
{
76+
_value = value;
77+
}
78+
public static Integer operator +(Integer lhs, Integer rhs) => new(lhs._value + rhs._value);
79+
public static Integer operator -(Integer lhs, Integer rhs) => new(lhs._value - rhs._value);
80+
public static Integer operator *(Integer lhs, Integer rhs) => new(lhs._value * rhs._value);
81+
public static Integer operator /(Integer lhs, Integer rhs) => new(lhs._value / rhs._value);
82+
public static implicit operator int(Integer num) => num._value;
83+
public static implicit operator Integer(int num) => new(num);
84+
}
85+
86+
public class Float
87+
{
88+
private readonly float _value;
89+
public Float(float value)
90+
{
91+
_value = value;
92+
}
93+
public static Float operator +(Float lhs, Float rhs) => new(lhs._value + rhs._value);
94+
public static Float operator -(Float lhs, Float rhs) => new(lhs._value - rhs._value);
95+
public static Float operator *(Float lhs, Float rhs) => new(lhs._value * rhs._value);
96+
public static Float operator /(Float lhs, Float rhs) => new(lhs._value / rhs._value);
97+
public static implicit operator float(Float num) => num._value;
98+
public static implicit operator Float(float num) => new(num);
99+
}
100+
101+
public class Bool
102+
{
103+
private readonly bool _value;
104+
public Bool(bool value)
105+
{
106+
_value = value;
107+
}
108+
public static implicit operator bool(Bool num) => num._value;
109+
public static implicit operator Bool(bool num) => new(num);
110+
}
111+
112+
public readonly struct PlayerStateChangedArgs
113+
{
114+
public readonly string PropertyName;
115+
116+
public PlayerStateChangedArgs(string propertyName)
117+
{
118+
PropertyName = propertyName;
119+
}
120+
}
121+
}

Runtime/Gamelogic/VisualScriptingPlayerState.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Visual Pinball Engine
2+
// Copyright (C) 2022 freezy and VPE Team
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
17+
// ReSharper disable InconsistentNaming
18+
19+
using System;
20+
21+
namespace VisualPinball.Unity.VisualScripting
22+
{
23+
24+
[Serializable]
25+
public class VisualScriptingPlayerStatePropertyDefinition
26+
{
27+
public string Name;
28+
public VisualScriptingPropertyType Type;
29+
30+
public string StringDefaultValue;
31+
public int IntegerDefaultValue;
32+
public float FloatDefaultValue;
33+
public bool BooleanDefaultValue;
34+
35+
public VisualScriptingPlayerStateProperty Instantiate()
36+
{
37+
switch (Type) {
38+
case VisualScriptingPropertyType.String:
39+
return new VisualScriptingPlayerStateProperty(Name, StringDefaultValue);
40+
case VisualScriptingPropertyType.Integer:
41+
return new VisualScriptingPlayerStateProperty(Name, IntegerDefaultValue);
42+
case VisualScriptingPropertyType.Float:
43+
return new VisualScriptingPlayerStateProperty(Name, FloatDefaultValue);
44+
case VisualScriptingPropertyType.Boolean:
45+
return new VisualScriptingPlayerStateProperty(Name, BooleanDefaultValue);
46+
default:
47+
throw new ArgumentOutOfRangeException();
48+
}
49+
}
50+
}
51+
52+
public enum VisualScriptingPropertyType
53+
{
54+
String, Integer, Float, Boolean
55+
}
56+
}

Runtime/Gamelogic/VisualScriptingPlayerStateDefinition.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Visual Pinball Engine
2+
// Copyright (C) 2022 freezy and VPE Team
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
17+
using System;
18+
19+
namespace VisualPinball.Unity.VisualScripting
20+
{
21+
public class VisualScriptingPlayerStateProperty
22+
{
23+
public string Name;
24+
public Type Type;
25+
private object _value;
26+
27+
public VisualScriptingPlayerStateProperty(string name, string initialValue) : this(name, typeof(string), initialValue)
28+
{
29+
}
30+
public VisualScriptingPlayerStateProperty(string name, int initialValue) : this(name, typeof(Integer),new Integer(initialValue))
31+
{
32+
}
33+
public VisualScriptingPlayerStateProperty(string name, float initialValue) : this(name, typeof(Float), new Float(initialValue))
34+
{
35+
}
36+
public VisualScriptingPlayerStateProperty(string name, bool initialValue) : this(name, typeof(Bool), new Bool(initialValue))
37+
{
38+
}
39+
40+
private VisualScriptingPlayerStateProperty(string name, Type type, object initialValue)
41+
{
42+
Name = name;
43+
Type = type;
44+
_value = initialValue;
45+
}
46+
47+
public T Get<T>() where T : class
48+
{
49+
return _value as T;
50+
}
51+
52+
public void Set<T>(T value)
53+
{
54+
_value = value;
55+
}
56+
}
57+
}

Runtime/Gamelogic/VisualScriptingPlayerStateProperty.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Runtime/Nodes/CreateBallUnit.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ namespace VisualPinball.Unity.VisualScripting
2121
{
2222

2323
[UnitTitle("Create Ball")]
24-
[UnitCategory("Events\\Visual Pinball")]
24+
[UnitCategory("Visual Pinball")]
2525
public class CreateBallUnit : GleUnit
2626
{
2727
[DoNotSerialize]

0 commit comments

Comments
 (0)