-
Notifications
You must be signed in to change notification settings - Fork 3
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
Multiplayer quickstart #107
base: main
Are you sure you want to change the base?
Changes from all commits
fa52313
2863455
a8c058d
5dcc487
981f4e8
a951b01
a31a925
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
using OmsiHook; | ||
using System.Numerics; | ||
using System.Runtime.CompilerServices; | ||
|
||
namespace OmsiHook.Examples.Multiplayer_Client | ||
{ | ||
internal class GameClient | ||
{ | ||
public Tuple<int, long, long> LastPing; | ||
private OmsiHook omsi; | ||
private Dictionary<int, OmsiRoadVehicleInst> Vehicles = new Dictionary<int, OmsiRoadVehicleInst>(); | ||
private int frameCounter = 0; | ||
public GameClient() | ||
{ | ||
omsi = new OmsiHook(); | ||
omsi.AttachToOMSI().Wait(); | ||
var OMSIRM = omsi.RemoteMethods; | ||
OMSIRM.OmsiSetCriticalSectionLock(omsi.Globals.ProgamManager.CS_MakeVehiclePtr).ContinueWith((_) => | ||
{ | ||
OMSIRM.MakeVehicle(@"Vehicles\GPM_MAN_LionsCity_M\MAN_A47.bus", __copyToMainList: true).ContinueWith((id) => | ||
{ | ||
Console.WriteLine($"Spawned Vehicle ID: {id.Result}"); | ||
Vehicles[0] = omsi.Globals.RoadVehicles.FList[1]; | ||
OMSIRM.OmsiReleaseCriticalSectionLock(omsi.Globals.ProgamManager.CS_MakeVehiclePtr).ContinueWith((_) => Console.WriteLine($"Unlock")); | ||
}); | ||
}); | ||
} | ||
|
||
public void UpdateVehicles(OMSIMPMessages.Vehicle_Position_Update update) | ||
{ | ||
if (Vehicles.TryGetValue(update.ID, out var vehicle)) | ||
{ | ||
if (frameCounter % 20 == 0) | ||
vehicle.Position = update.position; | ||
vehicle.Rotation = update.rotation; | ||
vehicle.Velocity = update.velocity; | ||
vehicle.MyKachelPnt = update.tile; | ||
vehicle.RelMatrix = update.relmatrix; | ||
vehicle.Acc_Local = update.acclocal; | ||
|
||
var posMat = Matrix4x4.CreateFromQuaternion(update.rotation); | ||
posMat.Translation = update.position; | ||
var absPosMat = Matrix4x4.Multiply(posMat, Matrix4x4.Identity/*update.relmatrix*/); | ||
Matrix4x4.Invert(absPosMat, out var absPosMatInv); | ||
|
||
vehicle.Pos_Mat = posMat; | ||
vehicle.AbsPosition = absPosMat; | ||
vehicle.AbsPosition_Inv = absPosMatInv; | ||
vehicle.Used_RelVec = ((Matrix4x4)update.relmatrix).Translation; | ||
vehicle.AI_Blinker_L = 1; | ||
vehicle.AI_Blinker_R = 1; | ||
vehicle.AI_var = 1; | ||
frameCounter++; | ||
} | ||
else | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tidy this up a bit. |
||
{ | ||
|
||
} | ||
} | ||
|
||
public void Tick(Telepathy.Client client) | ||
{ | ||
if (omsi.Globals.PlayerVehicle.IsNull || !client.Connected) | ||
return; | ||
|
||
var vehicle = omsi.Globals.PlayerVehicle; | ||
Console.WriteLine($"\x1b[8;0HP:{vehicle.Position}/{vehicle.MyKachelPnt}\x1b[9;0HR:{vehicle.Rotation}\x1b[10;0HV:{vehicle.Velocity}\x1b[11;0HB:{vehicle.Acc_Local} / {((Vehicles.ContainsKey(0)) ? (Vehicles[0].Acc_Local.ToString()) : "-")}"); | ||
byte[] buff = new byte[Unsafe.SizeOf<OMSIMPMessages.Player_Position_Update>() + 4]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To reduce GC pressure, allocate a single byte array and just reuse it. (Use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This also applies to the message parser class... |
||
int out_pos = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Naming conventions |
||
FastBinaryWriter.Write(buff, ref out_pos, OMSIMPMessages.Messages.UPDATE_PLAYER_POSITION); | ||
FastBinaryWriter.Write(buff, ref out_pos, new OMSIMPMessages.Player_Position_Update() | ||
{ | ||
position = vehicle.Position, | ||
tile = vehicle.MyKachelPnt, | ||
rotation = vehicle.Rotation, | ||
velocity = vehicle.Velocity, | ||
relmatrix = vehicle.RelMatrix, | ||
acclocal = vehicle.Acc_Local | ||
//vehicle = vehicle.RoadVehicle.MyPath | ||
|
||
}); ; | ||
client.Send(buff); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
namespace OmsiHook.Examples.Multiplayer_Client | ||
{ | ||
internal class MessageParser | ||
{ | ||
readonly static int MAJOR_VERSION = 1; | ||
readonly static int MINOR_VERSION = 0; | ||
public static void ParseMessage(byte[] message, Telepathy.Client client, GameClient gameClient) | ||
{ | ||
message.AsSpan<byte>(0, message.Length); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not use this lovely span you just made? |
||
int parse_pos = 0; | ||
switch ((OMSIMPMessages.Messages)FastBinaryReader.ReadI32(message, ref parse_pos)) | ||
{ | ||
case OMSIMPMessages.Messages.PING: | ||
{ | ||
byte[] buff = new byte[8]; | ||
int out_pos = 0; | ||
FastBinaryWriter.Write(buff, ref out_pos, OMSIMPMessages.Messages.PONG); | ||
FastBinaryWriter.Write(buff, ref out_pos, FastBinaryReader.ReadI32(message, ref parse_pos)); | ||
client.Send(buff); | ||
} | ||
break; | ||
case OMSIMPMessages.Messages.PONG: | ||
{ | ||
if (gameClient.LastPing.Item1 == FastBinaryReader.ReadI32(message, ref parse_pos)) | ||
{ | ||
gameClient.LastPing = new Tuple<int, long, long>(gameClient.LastPing.Item1, gameClient.LastPing.Item2, DateTime.Now.Ticks); | ||
Console.WriteLine($"Last Ping time: {((gameClient.LastPing.Item3 - gameClient.LastPing.Item2) / 10000):f3}ms"); | ||
} | ||
} | ||
break; | ||
case OMSIMPMessages.Messages.REPLY_VERSION: | ||
{ | ||
Console.WriteLine($"Server Version: {FastBinaryReader.ReadI32(message, ref parse_pos)}.{FastBinaryReader.ReadI32(message, ref parse_pos):D2}"); | ||
} | ||
break; | ||
case OMSIMPMessages.Messages.UPDATE_VEHICLE_POSITION: | ||
{ | ||
gameClient.UpdateVehicles(FastBinaryReader.Read<OMSIMPMessages.Vehicle_Position_Update>(message, ref parse_pos)); | ||
} | ||
break; | ||
default: | ||
{ | ||
Console.WriteLine($"Data received {message}"); | ||
break; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please be consistent with where you put your break statements. |
||
} | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>net6.0-windows</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
<StartupObject>OMSIClient</StartupObject> | ||
<PlatformTarget>x86</PlatformTarget> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="OmsiHook" Version="2.5.4" /> | ||
<PackageReference Include="Telepathy" Version="1.0.341" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Compile Include="..\Multiplayer_Server\Lib\OMSIMPMessages.cs" Link="Lib\OMSIMPMessages.cs" /> | ||
<Compile Include="..\Multiplayer_Server\Lib\FastBinaryReader.cs" Link="Lib\FastBinaryReader.cs" /> | ||
<Compile Include="..\Multiplayer_Server\Lib\FastBinaryWriter.cs" Link="Lib\FastBinaryWriter.cs" /> | ||
</ItemGroup> | ||
|
||
</Project> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
using OmsiHook.Examples.Multiplayer_Client; | ||
using Telepathy; | ||
|
||
class OMSIClient | ||
{ | ||
static void Main(string[] args) | ||
{ | ||
Client client = new Client(); | ||
GameClient gameClient = new GameClient(); | ||
client.Connect("127.0.0.1", 1337); | ||
|
||
|
||
while (true) | ||
{ | ||
Telepathy.Message msg; | ||
while (client.GetNextMessage(out msg)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just realised that the version of Telepathy on NuGet is really out of date (from 2019)... Anyway, is this a blocking method? If so, why do you thread sleep at the end of this method? |
||
{ | ||
switch (msg.eventType) | ||
{ | ||
case EventType.Connected: | ||
{ | ||
Console.WriteLine($"Client connected: {msg.connectionId}"); | ||
byte[] buff = new byte[4]; | ||
int out_pos = 0; | ||
FastBinaryWriter.Write(buff, ref out_pos, OMSIMPMessages.Messages.REQUEST_VERSION); | ||
client.Send(buff); | ||
byte[] buff2 = new byte[8]; | ||
out_pos = 0; | ||
gameClient.LastPing = new Tuple<int, long, long>(787, DateTime.Now.Ticks, 0); | ||
FastBinaryWriter.Write(buff2, ref out_pos, OMSIMPMessages.Messages.PING); | ||
FastBinaryWriter.Write(buff2, ref out_pos, 787); | ||
client.Send(buff2); | ||
} | ||
break; | ||
case EventType.Data: | ||
MessageParser.ParseMessage(msg.data, client, gameClient); | ||
break; | ||
case EventType.Disconnected: | ||
Console.WriteLine($"Client disconnected: {msg.connectionId}"); | ||
break; | ||
} | ||
} | ||
gameClient.Tick(client); | ||
System.Threading.Thread.Sleep(33); | ||
} | ||
client.Disconnect(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace OmsiHook.Examples.Multiplayer_Server | ||
{ | ||
internal class Client | ||
{ | ||
public int ClientId { get; private set; } | ||
public Client(int clientId) | ||
{ | ||
ClientId = clientId; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tuple<int, long, long> LastPing
-->(int xxx, long yyy, long zzz) lastPing