HI, I try to do a IModApi mod and could not figure out (yet?) how to get the player and entity/structure object from the (int) id ... (also is there a better manual than the html in the game folder anywhere?) thanks a lot!
Take a look in my EmpyrionScriptionMod it nearly uses all of the functions from the API. https://github.com/GitHub-TC/EmpyrionScripting
Thank you ASTIC. Your code is almost to high for me to understand. (lots of googleing needed for me) I tryed to copy/adapt parts of it, and I can get the objects now; but I am in the wrong thread most of the time... So I tryed to use the modapi.network stuff - does it work? I could not get it to, even as I copyed the whole class.
Ok, you can get this data from an IPlayfield Code: namespace Eleon.Modding { public interface IPlayfield { ... Dictionary<int, IPlayer> Players { get; } Dictionary<int, IEntity> Entities { get; } ... } and you can get the playfields from the event Code: namespace Eleon.Modding { public interface IApplication { ... event PlayfieldDelegate OnPlayfieldLoaded; event PlayfieldDelegate OnPlayfieldUnloading; you have to store the IPlayfield localy and remove it from your List wenn the unloading event ist raised Code: ModApi.Application.OnPlayfieldLoaded += Application_OnPlayfieldLoaded; ModApi.Application.OnPlayfieldUnloading += Application_OnPlayfieldUnloading; ConcurrentDictionary<string, IPlayfield> YourLocalPlayfieldCache = new ... private void Application_OnPlayfieldLoaded(IPlayfield playfield) { YourLocalPlayfieldCache.TryAdd(playfield.Name, playfield) } This way you get access to the elements by ID which are on the playfield. For a "global" query for a specific ID, you unfortunately have to query the SQLite database, because only that contains all the elements.
Thanks again, but I kind of already was that far. I got the playfield and player object in the playfield server (at least I think so) In the dedicated server i get a callback for chat mesages, but there i got no objects (i get the info objects from the chat and application, but i need the real ones). Now the problem is now how to (best) tell the playfield server i got a chat callback. I noticed the modapi.network code in your mod, but could not get it to work; is this the right way? Code: ConcurrentDictionary<string, IPlayfield> YourLocalPlayfieldCache = new ConcurrentDictionary<string, IPlayfield>(); public void Init(IModApi modAPI) { ModApi = modAPI; if (ModApi.Application.Mode == ApplicationMode.DedicatedServer) { //set up a Listener for Chat Messages ModApi.Application.ChatMessageSent += Application_ChatMessageSent; return; } ModApi.Network.RegisterReceiverForDediPackets(callback_playfield); ModApi.Application.OnPlayfieldLoaded += Application_OnPlayfieldLoaded; ModApi.Application.OnPlayfieldUnloading += Application_OnPlayfieldUnloading; } private void Application_OnPlayfieldLoaded(IPlayfield playfield) { Log($"CALLBACK Application_OnPlayfieldLoaded {playfield.Name}"); if( ! YourLocalPlayfieldCache.TryAdd(playfield.Name, playfield)) { Log("FAILED: YourLocalPlayfieldCache.TryAdd(playfield.Name, playfield))"); }; } private void Application_OnPlayfieldUnloading(IPlayfield playfield) { YourLocalPlayfieldCache.TryRemove(playfield.Name, out var outp); } private void callback_playfield(string sender, string playfieldName, byte[] data) { LogFile("CALLBACK.txt", "command callback callback_playfield"); Log($"CALLBACK Sender {sender} playfield {playfieldName} {Encoding.ASCII.GetString(data)}"); } private void Application_ChatMessageSent(MessageData chatMsgData) { if (chatMsgData.Text.StartsWith("/warp ") ) { Log("warp"); int from = chatMsgData.SenderEntityId; string[] SplitMsg = chatMsgData.Text.Split(' '); string msg = ""; for (int i = 1; i < SplitMsg.Count(); i++) { msg += " " + SplitMsg[i]; } if(int.TryParse(SplitMsg[1],out int dist)) { msg = "int geht " + dist.ToString() + msg; }else dist = 0; try { PlayerData? playerData = ModApi.Application.GetPlayerDataFor(chatMsgData.SenderEntityId); if (playerData != null) { var playerData2 = (PlayerData)playerData; var pf = playerData2.PlayfieldName; var playername = playerData2.PlayerName; msg = $"player {playername} playfield {pf} mode {ModApi.Application.Mode.ToString()} {msg}"; byte[] Data = Encoding.ASCII.GetBytes($"Data {playername} {msg}"); ModApi.Network.SendToPlayfieldServer("me777", pf, Data); } } catch { msg = "try catch " +msg; } Log("say " + msg); //Complicated thing for assembling all the variables for Sending a Server message MessageData SendableMsgData = new MessageData { //Channel = Eleon.MsgChannel.SinglePlayer, //Channel = Eleon.MsgChannel.Global, RecipientEntityId = chatMsgData.SenderEntityId, Text = msg, SenderNameOverride = ModApi.Application.GetPlayerDataFor(chatMsgData.SenderEntityId).Value.PlayerName, SenderType = Eleon.SenderType.ServerPrio }; //Send the request to the server ModApi.Application.SendChatMessage(SendableMsgData); } }
You can send chat messages only from the dedicated server process, so your mod have to run on both playfield & dedicated server and you have to send as message from your playfield mod instance to the dedicated mod instance and these can call the chat api. For an com example take a look here https://github.com/GitHub-TC/Empyri...r/EmpyrionScripting/DataWrapper/PlayerData.cs
Sorry ASTIC, ich glaube ich mache hier lost in translation... Ich habe sowohl die Objekte im Spielfeld als auch die Chat Messages im dediacated Prozess, ich kann praktisch alles logen. Wo das Problem ist ist dem Spielfeld zu sagen das ich eine Nachricht im dedicated bekommen habe. Code: im playfield: ModApi.Network.RegisterReceiverForDediPackets(callback_playfield); private void callback_playfield(string sender, string playfieldName, byte[] data) { LogFile("CALLBACK.txt", "command callback callback_playfield"); Log($"CALLBACK Sender {sender} playfield {playfieldName} {Encoding.ASCII.GetString(data)}"); } ========================== im dedicated: ModApi.Network.SendToPlayfieldServer("me777", pf, Data);
lol - ok dann haben wir uns missverstanden ich bin mir nicht sicher ob man als "Kanal" für die Kommunikation nicht immer den Namen der MOD verwenden muss. Ich habe bisher nur Codebeispiele gesehen die das genau so gemacht haben, also müsste deine Mod demnach "me777" heißen. Hier für den umgekehrten Weg Code: ModApi.Network.SendToDedicatedServer("EmpyrionScripting", data, currentPlayfield.Name) Ob der Name nur der in der .._info.yaml ist oder auch die DLL so heißen muss weis ich nicht, ich habe sie einfachheitshalber gleich benannt
Danke, probiere ich wenn ich wieder zu hause bin. *edit* Ja, war der Name. Ich dachte der ist frei, aber wie so oft falsch gedacht ... Vielen Dank.