MadAlchemist Posted January 4, 2022 Report Share Posted January 4, 2022 (edited) I really cannot understand why is my mountable entity crashing. I have copied most of code from bed block entity, the difference is that my entity is EntityAgent and not BlockEntity, and that it does not have any sleep-related code. Just trying to make player mount an entity, no other functionality at this moment. Main class: Spoiler using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Vintagestory.API.Common; using Vintagestory.API.Client; using Vintagestory.API.Server; using Vintagestory.GameContent; using ProtoBuf; using Vintagestory.API.Datastructures; using Vintagestory.API.MathTools; namespace aeronautics.src { [ProtoContract(ImplicitFields = ImplicitFields.AllPublic)] public class ControlMessage { public string message; } public class Main : ModSystem { #region Client public static void BalloonControl(IClientPlayer player, ICoreClientAPI api, IClientNetworkChannel ch) { /* PgUp is hardcoded to switch burner on. */ if (api.Input.KeyboardKeyStateRaw[((int)GlKeys.PageUp)]) { if (player.Entity.MountedOn != null && player.Entity.MountedOn.GetType() == typeof(HotAirBalloon)) { /* Turning on balloon burner on server */ ch.SendPacket(new ControlMessage() { message = "ON" }); } } /* PgDown is hardcoded to switch burner off.*/ if (api.Input.KeyboardKeyStateRaw[((int)GlKeys.PageDown)]) { if (player.Entity.MountedOn != null && player.Entity.MountedOn.GetType() == typeof(HotAirBalloon)) { /* Turning on balloon burner on server */ ch.SendPacket(new ControlMessage() { message = "OFF" }); } } /* Insert is hardcoded to refuel.*/ if (api.Input.KeyboardKeyStateRaw[((int)GlKeys.Insert)]) { if (player.Entity.MountedOn != null && player.Entity.MountedOn.GetType() == typeof(HotAirBalloon)) { /* Trying to refuel balloon */ ch.SendPacket(new ControlMessage() { message = "REFUEL" }); } } } #endregion public override void Start(ICoreAPI api) { base.Start(api); api.RegisterMountable("HotAirBalloon", HotAirBalloon.GetMountable); api.RegisterEntity("HotAirBalloon", typeof(HotAirBalloon)); } public override bool ShouldLoad(EnumAppSide side) => true; #region Client IClientNetworkChannel clientChannel; ICoreClientAPI clientApi; public override void StartClientSide(ICoreClientAPI api) { clientApi = api; clientChannel = api.Network.RegisterChannel("aeronautics") .RegisterMessageType(typeof(ControlMessage)); base.StartClientSide(api); } #endregion #region Server IServerNetworkChannel serverChannel; ICoreServerAPI serverApi; public override void StartServerSide(ICoreServerAPI api) { serverApi = api; serverChannel = api.Network.RegisterChannel("aeronautics") .RegisterMessageType(typeof(ControlMessage)) .SetMessageHandler<ControlMessage>(OnControlMessage) ; base.StartServerSide(api); } /* Control message handler */ private void OnControlMessage(IServerPlayer player, ControlMessage msg) { } #endregion } } Entity class: Spoiler namespace aeronautics.src { using Vintagestory.API.Common; using Vintagestory.API.Datastructures; using Vintagestory.API.MathTools; public class HotAirBalloon : EntityAgent, IMountable { public HotAirBalloon() { base.AllowDespawn = false; } public EntityAgent MountedBy; public Vec3d MountPosition { get { return (base.SidedPos.XYZ); } } public string SuggestedAnimation { get { return "sitflooridle"; } } public void MountableToTreeAttributes(TreeAttribute tree) { tree.SetString("className", "HotAirBalloon"); tree.SetInt("posx", ((int)this.ServerPos.X)); tree.SetInt("posy", ((int)this.ServerPos.Y)); tree.SetInt("posz", ((int)this.ServerPos.Z)); } public void DidUnmount(EntityAgent entityAgent) { MountedBy = null; entityAgent.TeleportTo(this.ServerPos.XYZ.Add(1.0, 1.0, 1.0)); } public void DidMount(EntityAgent entityAgent) { if (MountedBy != null) { entityAgent.TryUnmount(); return; } MountedBy = entityAgent; } public float? MountYaw { get { return this.BodyYaw; } } public static IMountable GetMountable(IWorldAccessor world, TreeAttribute tree) { Vec3d position = new Vec3d(tree.GetInt("posx", 0) + 0.25, tree.GetInt("posy", 0) + 0.25, tree.GetInt("posz", 0) + 0.25); return (world.GetNearestEntity(position, 0.1f, 0.1f, null) as HotAirBalloon); } public override void OnInteract(EntityAgent byEntity, ItemSlot slot, Vec3d hitPosition, EnumInteractMode mode) { if ((mode != EnumInteractMode.Interact) || !(byEntity is EntityPlayer)) { base.OnInteract(byEntity, slot, hitPosition, mode); } if (byEntity != null && byEntity is EntityPlayer) { if(this.MountedBy != null) { this.TryUnmount(); } byEntity.TryMount(this); } } } } Crash log: Spoiler Spoiler System.ArgumentNullException HResult=0x80004003 Сообщение = Значение не может быть неопределенным. Имя параметра: key Источник = mscorlib Трассировка стека: в System.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument) в System.Collections.Generic.Dictionary`2.FindEntry(TKey key) в System.Collections.Generic.Dictionary`2.get_Item(TKey key) в Vintagestory.Common.ClassRegistry.CreateMountable(IWorldAccessor world, TreeAttribute tree) в Vintagestory.API.Common.EntityAgent.<Initialize>b__30_0() в Vintagestory.API.Datastructures.SyncedTreeAttribute.MarkPathDirty(String path) в Vintagestory.API.Common.EntityAgent.TryMount(IMountable onmount) в aeronautics.src.HotAirBalloon.OnInteract(EntityAgent byEntity, ItemSlot slot, Vec3d hitPosition, EnumInteractMode mode) в Z:\Dev\VintageStory\Mods\mods\aeronautics\src\HotAirBalloon.cs:строка 80 в Vintagestory.Client.NoObf.SystemMouseInWorldInteractions.HandleMouseInteractionsNoBlockSelected(Single dt) в Vintagestory.Client.NoObf.SystemMouseInWorldInteractions.OnFinalizeFrame(Single dt) в Vintagestory.Client.NoObf.ClientEventManager.TriggerRenderStage(EnumRenderStage stage, Single dt) в Vintagestory.Client.NoObf.ClientMain.TriggerRenderStage(EnumRenderStage stage, Single dt) в Vintagestory.Client.NoObf.ClientMain.RenderToDefaultFramebuffer(Single dt) в _RpDe0Jt5dbuWGpUxAyvHOIbDBGg._tu5y7iPBPWTBAhlukeXpnCcwz6W(Single ) в _NLF4wmb6UPVLzv4DtU2r1ijDMNo._g5gGlJCvd5tg8L2OIzh5Cqwv60N(Single ) в _NLF4wmb6UPVLzv4DtU2r1ijDMNo._0gqbRXtZfqKlQCIZaKgLGM2FkhV(Single ) в Vintagestory.Client.NoObf.ClientPlatformWindows.window_RenderFrame(Object sender, FrameEventArgs e) в System.EventHandler`1.Invoke(Object sender, TEventArgs e) в OpenTK.GameWindow.RaiseRenderFrame(Double elapsed, Double& timestamp) в OpenTK.GameWindow.DispatchRenderFrame() в OpenTK.GameWindow.Run(Double updates_per_second, Double frames_per_second) в _nFNsDM20as86sGo44HbF6xxAkUD._UjMaM1bzP5Ozg5ilu06DMFIxPyO(_uhgd4BSf8z6N7PAibzFcq8c5IRD , String[] ) в _Y4Bk3tLdFsgoJryQq19g4IoitkE._UjMaM1bzP5Ozg5ilu06DMFIxPyO(ThreadStart ) в _nFNsDM20as86sGo44HbF6xxAkUD._uGIMddfWgVMG3Q8EvXiBxar6tZB(String[] ) Entity JSON: Spoiler { "code": "HotAirBalloon", "class": "HotAirBalloon", "entityClass": "HotAirBalloon", "canClimbAnywhere": true, //"habitat": "Air", "hitboxSize": { "x": 2, "y": 2 }, "deadHitboxSize": { "x": 2, "y": 2 }, "eyeHeight": 1.0, "drops": [], "sounds": { "hurt": "crack", "death": "crack_loud" }, "client": { "renderer": "Shape", "shape": { "base": "entity/air/hot_air_balloon" }, "textures": { "ceramic": { "base": "aeronautics:entity/air/balloon/ceramic" }, "basket": { "base": "aeronautics:entity/air/balloon/basket" }, "normal1": { "base": "aeronautics:entity/air/balloon/normal1" }, "rope_hi_res": { "base": "aeronautics:entity/air/balloon/rope_hi_res" }, "leather": { "base": "aeronautics:entity/air/balloon/leather" } }, "behaviors": [ { "code": "repulseagents" }, { "code": "controlledphysics", "stepHeight": 1.1 }, { "code": "interpolateposition" } ], "animations": [] }, "server": { "behaviors": [ { "code": "repulseagents" }, { "code": "controlledphysics", "stepHeight": 1.1 }, { "code": "health", "currenthealth": 40, "maxhealth": 40 } ] } } Edited January 4, 2022 by MadAlchemist Making long text more readable Link to comment Share on other sites More sharing options...
Recommended Posts