Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix cursor smoothing for 3 and more players #230

Merged
merged 3 commits into from
Sep 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions OniMod.sln
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ Global
{0C3E1EF7-5EFB-4FAC-B676-2C0660E959AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0C3E1EF7-5EFB-4FAC-B676-2C0660E959AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0C3E1EF7-5EFB-4FAC-B676-2C0660E959AA}.Publish|Any CPU.ActiveCfg = Publish|Any CPU
{0C3E1EF7-5EFB-4FAC-B676-2C0660E959AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{80DD29DB-6127-4F8B-845E-A04420FE22AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{80DD29DB-6127-4F8B-845E-A04420FE22AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{80DD29DB-6127-4F8B-845E-A04420FE22AB}.Publish|Any CPU.ActiveCfg = Publish|Any CPU
Expand All @@ -83,6 +84,7 @@ Global
{649CD3D0-39C9-412A-A42D-4826FD443B5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{649CD3D0-39C9-412A-A42D-4826FD443B5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{649CD3D0-39C9-412A-A42D-4826FD443B5F}.Publish|Any CPU.ActiveCfg = Debug|Any CPU
{649CD3D0-39C9-412A-A42D-4826FD443B5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
16 changes: 16 additions & 0 deletions src/MultiplayerMod.Test/Core/Collections/LinkedHashSetTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using MultiplayerMod.Core.Collections;
using NUnit.Framework;

namespace MultiplayerMod.Test.Core.Collections;

[TestFixture]
public class LinkedHashSetTests {

[Test]
public void ItemRemovedCorrectly() {
var set = new LinkedHashSet<string> { "First", "Second" };
Assert.IsTrue(set.Remove("Second"));
Assert.IsFalse(set.Remove("Second"));
}

}
46 changes: 46 additions & 0 deletions src/MultiplayerMod.Test/Core/Events/EventDispatcherTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System.Collections.Generic;
using MultiplayerMod.Core.Events;
using NUnit.Framework;

namespace MultiplayerMod.Test.Core.Events;

[TestFixture]
public class EventDispatcherTests {

[Test]
public void SubscribersMustBeExecuted() {
var result = new List<int>();
var dispatcher = new EventDispatcher();

dispatcher.Subscribe<Event<int>>(it => result.Add(it.Value));
dispatcher.Subscribe<Event<int>>(it => result.Add(it.Value * 3));

dispatcher.Dispatch(new Event<int>(2));

Assert.AreEqual(expected: new List<int> { 2, 6 }, actual: result);
}

[Test]
public void ActionMustBeUnsubscribed() {
var result = new List<int>();
var dispatcher = new EventDispatcher();

IEventSubscription subscription = dispatcher.Subscribe<Event<int>>(it => result.Add(it.Value));
dispatcher.Subscribe<Event<int>>(it => result.Add(it.Value * 3));

subscription.Cancel();

dispatcher.Dispatch(new Event<int>(2));

Assert.AreEqual(expected: new List<int> { 6 }, actual: result);
}

private class Event<T> {
public T Value { get; }

public Event(T value) {
Value = value;
}
}

}
46 changes: 46 additions & 0 deletions src/MultiplayerMod.Test/Core/Events/TypedEventDispatcherTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System.Collections.Generic;
using MultiplayerMod.Core.Events;
using NUnit.Framework;

namespace MultiplayerMod.Test.Core.Events;

[TestFixture]
public class TypedEventDispatcherTests {

[Test]
public void SubscribersMustBeExecuted() {
var result = new List<int>();
var dispatcher = new EventDispatcher<Event<int>>();

dispatcher.Subscribe(it => result.Add(it.Value));
dispatcher.Subscribe(it => result.Add(it.Value * 3));

dispatcher.Dispatch(new Event<int>(2));

Assert.AreEqual(expected: new List<int> { 2, 6 }, actual: result);
}

[Test]
public void ActionMustBeUnsubscribed() {
var result = new List<int>();
var dispatcher = new EventDispatcher<Event<int>>();

IEventSubscription subscription = dispatcher.Subscribe(it => result.Add(it.Value));
dispatcher.Subscribe(it => result.Add(it.Value * 3));

subscription.Cancel();

dispatcher.Dispatch(new Event<int>(2));

Assert.AreEqual(expected: new List<int> { 6 }, actual: result);
}

private class Event<T> {
public T Value { get; }

public Event(T value) {
Value = value;
}
}

}
5 changes: 3 additions & 2 deletions src/MultiplayerMod.Test/Network/CommandTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Runtime.InteropServices;
using MultiplayerMod.ModRuntime;
using MultiplayerMod.Multiplayer;
using MultiplayerMod.Network;
using MultiplayerMod.Platform.Steam.Network;
Expand All @@ -16,14 +17,14 @@ public class CommandTests {
private class Command : MultiplayerCommand {
public int Value { set; get; }

public override void Execute() { }
public override void Execute(Runtime runtime) { }
}

[Serializable]
private class DataCommand : MultiplayerCommand {
public byte[] Data = new byte[Configuration.MaxMessageSize * 2];

public override void Execute() { }
public override void Execute(Runtime runtime) { }
}

[Test]
Expand Down
44 changes: 44 additions & 0 deletions src/MultiplayerMod/Core/Collections/LinkedHashSet.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System.Collections;
using System.Collections.Generic;

namespace MultiplayerMod.Core.Collections;

public class LinkedHashSet<T> : ICollection<T>, IReadOnlyCollection<T> {

public int Count => list.Count;

public bool IsReadOnly => false;

private readonly Dictionary<T, LinkedListNode<T>> dictionary = new();
private readonly LinkedList<T> list = new();

public IEnumerator<T> GetEnumerator() => list.GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

public void Add(T item) {
if (dictionary.ContainsKey(item))
return;

dictionary[item] = list.AddLast(item);
}

public void Clear() {
list.Clear();
dictionary.Clear();
}

public bool Contains(T item) => dictionary.ContainsKey(item);

public void CopyTo(T[] array, int arrayIndex) => list.CopyTo(array, arrayIndex);

public bool Remove(T item) {
if (!dictionary.TryGetValue(item, out var node))
return false;

dictionary.Remove(item);
list.Remove(node);
return true;
}

}
59 changes: 59 additions & 0 deletions src/MultiplayerMod/Core/Events/EventDispatcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using MultiplayerMod.Core.Collections;
using MultiplayerMod.Core.Extensions;

namespace MultiplayerMod.Core.Events;

public class EventDispatcher {

private readonly Dictionary<Type, LinkedHashSet<Delegate>> handlers = new();

public EventSubscription Subscribe<T>(Action<T> action) {
var type = typeof(T);
if (!handlers.TryGetValue(type, out var delegates)) {
delegates = new LinkedHashSet<Delegate>();
handlers[type] = delegates;
}
delegates.Add(action);
return new EventSubscription(this, action, typeof(T));
}

public void Unsubscribe<T>(Action<T> action) => Unsubscribe(typeof(T), action);

public void Unsubscribe(Type type, Delegate action) {
if (!handlers.TryGetValue(type, out var delegates))
return;

delegates.Remove(action);
}

public void Dispatch<T>(T @event) where T : notnull {
if (!handlers.TryGetValue(typeof(T), out var delegates))
return;

var arguments = new object[] { @event };
delegates.ForEach(it => it.Method.Invoke(it.Target, arguments));
}

}

public class EventDispatcher<T> where T : notnull {

private readonly LinkedHashSet<Delegate> delegates = new();

public EventSubscription<T> Subscribe(Action<T> action) {
delegates.Add(action);
return new EventSubscription<T>(this, action);
}

public void Unsubscribe(Delegate action) {
delegates.Remove(action);
}

public void Dispatch(T @event) {
var arguments = new object[] { @event };
delegates.ForEach(it => it.Method.Invoke(it.Target, arguments));
}

}
38 changes: 38 additions & 0 deletions src/MultiplayerMod/Core/Events/EventSubscription.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System;

namespace MultiplayerMod.Core.Events;

public interface IEventSubscription {
void Cancel();
}

public class EventSubscription : IEventSubscription {

private readonly EventDispatcher dispatcher;
private readonly Delegate action;
private readonly Type type;

public EventSubscription(EventDispatcher dispatcher, Delegate action, Type type) {
this.dispatcher = dispatcher;
this.action = action;
this.type = type;
}

public void Cancel() => dispatcher.Unsubscribe(type, action);

}


public class EventSubscription<T> : IEventSubscription where T : notnull {

private readonly EventDispatcher<T> dispatcher;
private readonly Delegate action;

public EventSubscription(EventDispatcher<T> dispatcher, Delegate action) {
this.dispatcher = dispatcher;
this.action = action;
}

public void Cancel() => dispatcher.Unsubscribe(action);

}
6 changes: 6 additions & 0 deletions src/MultiplayerMod/ModRuntime/Runtime.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using JetBrains.Annotations;
using MultiplayerMod.Core.Dependency;
using MultiplayerMod.Core.Events;
using MultiplayerMod.ModRuntime.Context;
using MultiplayerMod.Multiplayer.State;

namespace MultiplayerMod.ModRuntime;

Expand All @@ -11,13 +13,17 @@ public class Runtime {

public DependencyContainer Dependencies { get; }
public ExecutionContext ExecutionContext => executionContextManager.Context;
public EventDispatcher EventDispatcher => Dependencies.Get<EventDispatcher>();
public MultiplayerGame Multiplayer => Dependencies.Get<MultiplayerGame>();

private readonly ExecutionContextManager executionContextManager = new();

public Runtime() {
Dependencies = new DependencyContainer();
Dependencies.Register(executionContextManager);
Dependencies.Register<ExecutionLevelManager>();
Dependencies.Register<EventDispatcher>();
Dependencies.Register(this);
Instance = this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using MultiplayerMod.Core.Logging;
using MultiplayerMod.Game.Chores;
using MultiplayerMod.ModRuntime;
using MultiplayerMod.Multiplayer.World;
using Object = UnityEngine.Object;

Expand Down Expand Up @@ -33,7 +34,7 @@ public FindNextChore(FindNextChoreEventArgs args) {
isAttemptingOverride = args.IsAttemptingOverride;
}

public override void Execute() {
public override void Execute(Runtime runtime) {
log.Debug(
$"Received {instanceId} {instanceString} {instanceCell} {choreId} {choreType} {choreCell}"
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using MultiplayerMod.ModRuntime;
using MultiplayerMod.Multiplayer.World.Debug;

namespace MultiplayerMod.Multiplayer.Commands.Debug;
Expand All @@ -12,7 +13,7 @@ public SyncWorldDebugSnapshot(WorldDebugSnapshot snapshot) {
this.snapshot = snapshot;
}

public override void Execute() {
public override void Execute(Runtime runtime) {
WorldDebugSnapshotRunner.LastServerInfo = snapshot;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using MultiplayerMod.Game.Mechanics.Minions;
using MultiplayerMod.Game.Mechanics.Printing;
using MultiplayerMod.Game.UI.Screens;
using MultiplayerMod.ModRuntime;
using MultiplayerMod.Multiplayer.Objects;
using static MultiplayerMod.Game.Mechanics.Printing.TelepadEvents;

Expand All @@ -17,7 +18,7 @@ public AcceptDelivery(AcceptDeliveryEventArgs args) {
this.args = args;
}

public override void Execute() {
public override void Execute(Runtime runtime) {
var telepad = args.Target.GetComponent();
var capture = LocalCaptor.Capture<TelepadAcceptDeliveryCapture>(
() => telepad.OnAcceptDelivery(args.Deliverable)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Linq;
using System.Reflection;
using MultiplayerMod.Game.Mechanics.Objects;
using MultiplayerMod.ModRuntime;
using MultiplayerMod.Multiplayer.Objects.Reference;

namespace MultiplayerMod.Multiplayer.Commands.Gameplay;
Expand All @@ -28,7 +29,7 @@ public CallMethod(StateMachineEventsArgs eventArgs) {
args = eventArgs.Args;
}

public override void Execute() {
public override void Execute(Runtime runtime) {
var method = methodType
.GetMethod(
methodName,
Expand Down
Loading