merge rec_manager and mp_manager into present_manager and add event handler

This commit is contained in:
yyc12345 2022-09-08 17:11:45 +08:00
parent 21ff253337
commit 7b72480bcd
13 changed files with 235 additions and 296 deletions

View File

@ -1,6 +1,6 @@
[gd_scene load_steps=2 format=2] [gd_scene load_steps=2 format=2]
[ext_resource path="res://scripts/scenes/entities/ShadowBallManager.cs" type="Script" id=1] [ext_resource path="res://scripts/scenes/entities/SBallManager.cs" type="Script" id=1]
[node name="ShadowBallManager" type="Spatial"] [node name="ShadowBallManager" type="Spatial"]
script = ExtResource( 1 ) script = ExtResource( 1 )

View File

@ -3,7 +3,7 @@
[ext_resource path="res://scenes/levels/test.escn" type="PackedScene" id=1] [ext_resource path="res://scenes/levels/test.escn" type="PackedScene" id=1]
[ext_resource path="res://scripts/scenes/entities/StalkerCore.cs" type="Script" id=2] [ext_resource path="res://scripts/scenes/entities/StalkerCore.cs" type="Script" id=2]
[ext_resource path="res://scenes/entities/StalkerCamera.tscn" type="PackedScene" id=3] [ext_resource path="res://scenes/entities/StalkerCamera.tscn" type="PackedScene" id=3]
[ext_resource path="res://scenes/entities/ShadowBallManager.tscn" type="PackedScene" id=4] [ext_resource path="res://scenes/entities/SBallManager.tscn" type="PackedScene" id=4]
[node name="StalkerCore" type="Spatial"] [node name="StalkerCore" type="Spatial"]
script = ExtResource( 2 ) script = ExtResource( 2 )

View File

@ -16,13 +16,18 @@ namespace BallanceStalker.Cores {
private BStalkerContext() { private BStalkerContext() {
mLogManager = new Managers.LogManager(); mLogManager = new Managers.LogManager();
mPresentManager = new Managers.PresentManager(mLogManager);
} }
public void Dispose() { public void Dispose() {
mPresentManager.Dispose();
// logger will be released at the last position
mLogManager.Dispose(); mLogManager.Dispose();
} }
public Managers.LogManager mLogManager; public Managers.LogManager mLogManager;
public Managers.PresentManager mPresentManager;
} }
} }

View File

@ -1,10 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BallanceStalker.Cores.Managers {
public class MultiplayManager {
}
}

View File

@ -0,0 +1,55 @@
using BallanceStalker.Cores.Rec;
using BallanceStalker.Cores.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BallanceStalker.Cores.Managers {
public class PresentManager : IDisposable {
public PresentManager(LogManager logger) {
mLogger = logger;
}
private LogManager mLogger;
public event Action<Guid, IRec> RecAdded;
public event Action<Guid, IRec> RecRemoved;
public event Action<Guid, IMultiplay> MultiplayAdded;
public event Action<Guid, IMultiplay> MultiplayRemoved;
private Dictionary<Guid, IRec> mRecDict = new Dictionary<Guid, IRec>();
private Dictionary<Guid, IMultiplay> mMultiplayDict = new Dictionary<Guid, IMultiplay>();
public void AddSpiritTrailRec(string rec_folder, SpiritTrailRecType t) {
Guid g = Guid.NewGuid();
var entity = new SpiritTrailRec(rec_folder, t);
entity.RecSetGuid(g);
mRecDict.Add(g, entity);
RecAdded?.Invoke(g, entity);
}
public IRec GetRec(Guid uuid) {
if (mRecDict.TryGetValue(uuid, out IRec v)) {
return v;
} else return null;
}
public void RemoveRec(Guid uuid) {
if (mRecDict.TryGetValue(uuid, out IRec v)) {
mRecDict.Remove(uuid);
RecRemoved?.Invoke(uuid, v);
}
}
public void Dispose() {
// free rec
foreach(var pair in mRecDict) {
RecRemoved?.Invoke(pair.Key, pair.Value);
}
mRecDict.Clear();
// todo: add multiplay free here
}
}
}

View File

@ -1,29 +0,0 @@
using BallanceStalker.Cores.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BallanceStalker.Cores.Managers {
public class RecManager {
public event Action<Guid, IRec> RecAdded;
public event Action<Guid, IRec> RecRemoved;
private Dictionary<Guid, IRec> mRecDict = new Dictionary<Guid, IRec>();
public Guid AddSpiritTrailRec(string rec_folder) {
}
public void RemoveRec(Guid uuid) {
}
public void Tick(float delta) {
}
}
}

View File

@ -36,10 +36,20 @@ namespace BallanceStalker.Cores.Rec {
mRecStateCursor = mRecTrafoCursor = 0; mRecStateCursor = mRecTrafoCursor = 0;
mRecRemainDelta = 0f; mRecRemainDelta = 0f;
mGuid = Guid.Empty;
} }
public event Action<long, string> RecRegisterBall; Guid mGuid;
public event Action<long> RecUnregisterBall; public Guid RecGetGuid() {
return mGuid;
}
public void RecSetGuid(Guid g) {
mGuid = g;
}
public event Action<ulong, string> RecRegisterBall;
public event Action<ulong> RecUnregisterBall;
public event Action<RecBallStateReport> RecNewBallState; public event Action<RecBallStateReport> RecNewBallState;
public event Action<List<RecBallStateReport>> RecNewBallStates; public event Action<List<RecBallStateReport>> RecNewBallStates;
@ -134,7 +144,7 @@ namespace BallanceStalker.Cores.Rec {
public void Startup() { public void Startup() {
RecRegisterBall?.Invoke(0, Path.GetFileName(mFileFolder)); RecRegisterBall?.Invoke(0uL, Path.GetFileName(mFileFolder));
Task.Run(() => { Task.Run(() => {
LoadData(); LoadData();
@ -142,7 +152,7 @@ namespace BallanceStalker.Cores.Rec {
} }
public void Shutdown() { public void Shutdown() {
RecUnregisterBall?.Invoke(0); RecUnregisterBall?.Invoke(0uL);
} }
public void Pause() { public void Pause() {
@ -203,7 +213,7 @@ namespace BallanceStalker.Cores.Rec {
RecNewBallState?.Invoke(new RecBallStateReport() { RecNewBallState?.Invoke(new RecBallStateReport() {
BallState = mRecStates[mRecStateCursor].Slerp(mRecStates[mRecStateCursor + 1], mRecRemainDelta / REC_DELTA), BallState = mRecStates[mRecStateCursor].Slerp(mRecStates[mRecStateCursor + 1], mRecRemainDelta / REC_DELTA),
BallType = mRecTrafos[mRecTrafoCursor].TrafoType, BallType = mRecTrafos[mRecTrafoCursor].TrafoType,
Identifier = 0 Identifier = 0uL
}); });
} }
@ -217,5 +227,6 @@ SubRec HS/SR: {mRecHSScore}/{mRecSRScore}
SubRec state/trafo size: {mRecStates?.Length}/{mRecTrafos?.Length}"; SubRec state/trafo size: {mRecStates?.Length}/{mRecTrafos?.Length}";
} }
} }
} }
} }

View File

@ -136,7 +136,7 @@ namespace BallanceStalker.Cores.Utils {
} }
public struct RecBallStateReport { public struct RecBallStateReport {
public long Identifier; public ulong Identifier;
public VxBallType BallType; public VxBallType BallType;
public VxBallState BallState; public VxBallState BallState;
} }

View File

@ -1,182 +0,0 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BallanceStalker.Cores.Utils {
public class CmdLexer {
public static List<string> DoLexer(string command) {
var result = new List<string>();
CmdLexerState current = CmdLexerState.Space, previous = CmdLexerState.Space;
StringBuilder itemCache = new StringBuilder();
#region processor
void SpaceProcessor(char chr) {
switch (chr) {
case '\'':
current = CmdLexerState.Single;
break;
case '"':
current = CmdLexerState.Double;
break;
case '\\':
current = CmdLexerState.Shift;
previous = CmdLexerState.Normal;
break;
case ' ':
;//keep
break;
default:
itemCache.Append(chr);
current = CmdLexerState.Normal;
break;
}
}
void NormalProcessor(char chr) {
switch (chr) {
case '\'':
itemCache.Append('\'');
break;
case '"':
itemCache.Append('"');
break;
case '\\':
previous = CmdLexerState.Normal;
current = CmdLexerState.Shift;
break;
case ' ':
result.Add(itemCache.ToString());
itemCache.Clear();
current = CmdLexerState.Space;
break;
default:
itemCache.Append(chr);
break;
}
}
void SingleProcessor(char chr) {
switch (chr) {
case '\'':
current = CmdLexerState.Normal;
break;
case '"':
itemCache.Append('"');
break;
case '\\':
previous = CmdLexerState.Single;
current = CmdLexerState.Shift;
break;
case ' ':
itemCache.Append(' ');
break;
default:
itemCache.Append(chr);
break;
}
}
void DoubleProcessor(char chr) {
switch (chr) {
case '\'':
itemCache.Append('\'');
break;
case '"':
current = CmdLexerState.Normal;
break;
case '\\':
previous = CmdLexerState.Double;
current = CmdLexerState.Shift;
break;
case ' ':
itemCache.Append(' ');
break;
default:
itemCache.Append(chr);
break;
}
}
void ShiftProcessor(char chr) {
switch (chr) {
case '\'':
itemCache.Append('\'');
break;
case '"':
itemCache.Append('"');
break;
case '\\':
itemCache.Append('\\');
break;
case ' ':
throw new ArgumentException();
default:
throw new ArgumentException();
}
current = previous;
}
#endregion
try {
foreach (var item in command) {
switch (current) {
case CmdLexerState.Space:
SpaceProcessor(item);
break;
case CmdLexerState.Normal:
NormalProcessor(item);
break;
case CmdLexerState.Single:
SingleProcessor(item);
break;
case CmdLexerState.Double:
DoubleProcessor(item);
break;
case CmdLexerState.Shift:
ShiftProcessor(item);
break;
}
}
switch (current) {
case CmdLexerState.Space:
break;
case CmdLexerState.Normal:
//add the last one
result.Add(itemCache.ToString());
break;
case CmdLexerState.Single:
case CmdLexerState.Double:
case CmdLexerState.Shift:
throw new ArgumentException();
}
} catch {
// when raise a error, clean list
// and return null
result.Clear();
return null;
}
return result;
}
private enum CmdLexerState {
Space,
Normal,
Single,
Double,
Shift
}
}
}

View File

@ -6,19 +6,22 @@ using System.Threading.Tasks;
namespace BallanceStalker.Cores.Utils { namespace BallanceStalker.Cores.Utils {
public interface IRec { public interface IRec {
Guid RecGetGuid();
void RecSetGuid(Guid g);
void Startup(); void Startup();
void Shutdown(); void Shutdown();
void Play(); void Play();
void Pause(); void Pause();
void Seek(float sec); void Seek(float sec);
void Tick(float delta_sec); void Tick(float delta_sec);
string GetProfile(); string GetProfile(); // todo: in future return a Dict and serialized by PresentManager
/// <summary> /// <summary>
/// register a ball /// register a ball
/// long is identifier, string is name /// long is identifier, string is name
/// </summary> /// </summary>
event Action<long, string> RecRegisterBall; event Action<ulong, string> RecRegisterBall;
event Action<RecBallStateReport> RecNewBallState; event Action<RecBallStateReport> RecNewBallState;
event Action<List<RecBallStateReport>> RecNewBallStates; event Action<List<RecBallStateReport>> RecNewBallStates;
//event Action RecPlaying; //event Action RecPlaying;
@ -27,6 +30,6 @@ namespace BallanceStalker.Cores.Utils {
/// unregister a ball /// unregister a ball
/// long is identifier /// long is identifier
/// </summary> /// </summary>
event Action<long> RecUnregisterBall; event Action<ulong> RecUnregisterBall;
} }
} }

View File

@ -0,0 +1,138 @@
using BallanceStalker.Cores.Utils;
using Godot;
using System;
using System.Collections.Generic;
namespace BallanceStalker.Scenes.Entities {
public class SBallManager : Spatial {
private Dictionary<Guid, PresentHandler> mBallDict = new Dictionary<Guid, PresentHandler>();
private PackedScene mTemplateShadowBall;
private BallanceStalker.Cores.Managers.PresentManager mPresentManager;
public override void _Ready() {
// load template
mTemplateShadowBall = ResourceLoader.Load<PackedScene>("res://scenes/entities/ShadowBall.tscn");
// add event hook
mPresentManager = BallanceStalker.Cores.BStalkerContext.Singleton.mPresentManager;
mPresentManager.RecAdded += Proc_PresentManager_RecAdded;
mPresentManager.RecRemoved += Proc_PresentManager_RecRemoved;
mPresentManager.MultiplayAdded += Proc_PresentManager_MultiplayAdded;
mPresentManager.MultiplayRemoved += Proc_PresentManager_MultiplayRemoved;
}
private void Proc_PresentManager_MultiplayRemoved(Guid uuid, Cores.Utils.IMultiplay mp) {
if (mBallDict.TryGetValue(uuid, out PresentHandler hd)) {
mBallDict.Remove(uuid);
hd.Dispose();
}
}
private void Proc_PresentManager_MultiplayAdded(Guid uuid, Cores.Utils.IMultiplay mp) {
mBallDict.Add(uuid, new PresentHandler(mTemplateShadowBall, this, mp));
}
private void Proc_PresentManager_RecRemoved(Guid uuid, Cores.Utils.IRec rec) {
if (mBallDict.TryGetValue(uuid, out PresentHandler hd)) {
mBallDict.Remove(uuid);
hd.Dispose();
}
}
private void Proc_PresentManager_RecAdded(Guid uuid, Cores.Utils.IRec rec) {
mBallDict.Add(uuid, new PresentHandler(mTemplateShadowBall, this, rec));
}
class PresentHandler : IDisposable {
bool mIsRec;
IRec mRec;
IMultiplay mMp;
Dictionary<ulong, ShadowBall> mBallDict;
Spatial mParent;
PackedScene mTemplate;
public void Dispose() {
// remove event handler
if (mIsRec) {
mRec.RecRegisterBall -= Proc_Rec_RecRegisterBall;
mRec.RecUnregisterBall -= Proc_Rec_RecUnregisterBall;
mRec.RecNewBallState -= Proc_Rec_RecNewBallState;
mRec.RecNewBallStates -= Proc_Rec_RecNewBallStates;
} else {
// todo: add mp event deleter
}
mRec = null;
mMp = null;
// remove all shadow balls
foreach (var ball in mBallDict.Values) {
mParent.RemoveChild(ball);
ball.QueueFree();
}
mBallDict.Clear();
}
#region rec
public PresentHandler(PackedScene template, Spatial parent, IRec rec) {
mTemplate = template;
mParent = parent;
mBallDict = new Dictionary<ulong, ShadowBall>();
mIsRec = true;
mRec = rec;
mMp = null;
rec.RecRegisterBall += Proc_Rec_RecRegisterBall;
rec.RecUnregisterBall += Proc_Rec_RecUnregisterBall;
rec.RecNewBallState += Proc_Rec_RecNewBallState;
rec.RecNewBallStates += Proc_Rec_RecNewBallStates;
}
private void Proc_Rec_RecNewBallStates(List<RecBallStateReport> reports) {
foreach (var report in reports) {
if (mBallDict.TryGetValue(report.Identifier, out ShadowBall ball)) {
ball.SetBallState(report.BallState, report.BallType);
}
}
}
private void Proc_Rec_RecNewBallState(RecBallStateReport report) {
if (mBallDict.TryGetValue(report.Identifier, out ShadowBall ball)) {
ball.SetBallState(report.BallState, report.BallType);
}
}
private void Proc_Rec_RecUnregisterBall(ulong raw_uuid) {
if (mBallDict.TryGetValue(raw_uuid, out ShadowBall ball)) {
mBallDict.Remove(raw_uuid);
mParent.RemoveChild(ball);
ball.QueueFree();
}
}
private void Proc_Rec_RecRegisterBall(ulong raw_uuid, string name) {
var instance = mTemplate.Instance<ShadowBall>();
mParent.AddChild(instance);
instance.SetPlayerName(name);
mBallDict.Add(raw_uuid, instance);
}
#endregion
#region multiply
public PresentHandler(PackedScene template, Spatial parent, IMultiplay mp) {
mTemplate = template;
mParent = parent;
mBallDict = new Dictionary<ulong, ShadowBall>();
mIsRec = false;
mRec = null;
mMp = mp;
// todo: add mp event handler
}
#endregion
}
}
}

View File

@ -4,13 +4,7 @@ using System;
// Reference: https://github.com/godotengine/godot-demo-projects/blob/master/3d/waypoints // Reference: https://github.com/godotengine/godot-demo-projects/blob/master/3d/waypoints
namespace BallanceStalker.Scenes.Entities { namespace BallanceStalker.Scenes.Entities {
public enum ShadowBallType : UInt32 {
Stone,
Wood,
Paper
}
public class ShadowBall : Spatial { public class ShadowBall : Spatial {
static readonly float MARGIN = 16f; // set it as half of arrow image static readonly float MARGIN = 16f; // set it as half of arrow image
@ -24,7 +18,7 @@ namespace BallanceStalker.Scenes.Entities {
Label mPlayername; Label mPlayername;
Camera mSpectatorCamera = null; Camera mSpectatorCamera = null;
MeshInstance mMeshWood, mMeshStone, mMeshPaper; MeshInstance mMeshWood, mMeshStone, mMeshPaper;
ShadowBallType mOldState = ShadowBallType.Wood; Cores.Utils.VxBallType mOldState = Cores.Utils.VxBallType.Wood;
public override void _Ready() { public override void _Ready() {
mCtl2D = GetNode<Control>("TextArchor/Ctl2D"); mCtl2D = GetNode<Control>("TextArchor/Ctl2D");
@ -42,30 +36,31 @@ namespace BallanceStalker.Scenes.Entities {
mPlayername.Text = new_name; mPlayername.Text = new_name;
} }
public void SetBallState(Vector3 pos, Quat quad, ShadowBallType btype) { public void SetBallState(Cores.Utils.VxBallState bstate, Cores.Utils.VxBallType btype) {
this.Translation = pos; // set z weight of pos and quat to minus, for converting it into godot coordinate system.
mModelArchor.Rotation = quad.GetEuler(); this.Translation = new Vector3(bstate.Pos.X, bstate.Pos.Y, -bstate.Pos.Z);
mModelArchor.Rotation = new Quat(bstate.Quat.X, bstate.Quat.Y, -bstate.Quat.Z, bstate.Quat.W).GetEuler();
if (mOldState != btype) { if (mOldState != btype) {
switch (mOldState) { switch (mOldState) {
case ShadowBallType.Stone: case Cores.Utils.VxBallType.Stone:
mMeshStone.Visible = false; mMeshStone.Visible = false;
break; break;
case ShadowBallType.Wood: case Cores.Utils.VxBallType.Wood:
mMeshWood.Visible = false; mMeshWood.Visible = false;
break; break;
case ShadowBallType.Paper: case Cores.Utils.VxBallType.Paper:
mMeshPaper.Visible = false; mMeshPaper.Visible = false;
break; break;
} }
switch (btype) { switch (btype) {
case ShadowBallType.Stone: case Cores.Utils.VxBallType.Stone:
mMeshStone.Visible = true; mMeshStone.Visible = true;
break; break;
case ShadowBallType.Wood: case Cores.Utils.VxBallType.Wood:
mMeshWood.Visible = true; mMeshWood.Visible = true;
break; break;
case ShadowBallType.Paper: case Cores.Utils.VxBallType.Paper:
mMeshPaper.Visible = true; mMeshPaper.Visible = true;
break; break;
} }

View File

@ -1,47 +0,0 @@
using Godot;
using System;
using System.Collections.Generic;
namespace BallanceStalker.Scenes.Entities {
public class ShadowBallManager : Spatial {
private Dictionary<Guid, ShadowBall> mBallDict = new Dictionary<Guid, ShadowBall>();
private PackedScene mTemplateShadowBall;
public override void _Ready() {
mTemplateShadowBall = ResourceLoader.Load<PackedScene>("res://scenes/entities/ShadowBall.tscn");
}
public Guid AddBall() {
var guid = Guid.NewGuid();
var instance = mTemplateShadowBall.Instance<ShadowBall>();
AddChild(instance);
mBallDict.Add(guid, instance);
return guid;
}
public void SetBallName(Guid ballid, string new_name) {
if (mBallDict.TryGetValue(ballid, out ShadowBall entity)) {
entity.SetPlayerName(new_name);
}
}
public void SetBallState(Guid ballid, Vector3 pos, Quat quad, ShadowBallType btype) {
if (mBallDict.TryGetValue(ballid, out ShadowBall entity)) {
entity.SetBallState(pos, quad, btype);
}
}
public void RemoveBall(Guid ballid) {
if (mBallDict.TryGetValue(ballid, out ShadowBall entity)) {
RemoveChild(entity);
entity.QueueFree();
mBallDict.Remove(ballid);
}
}
}
}