1. Wulf

    Wulf Community Admin Community Admin Oxide Developer

    The cause is that the host controls too much, and the plane crashing is needed for players to properly spawn. If the plane crash position does not get set, saves will not work properly. This is why you see some NREs and such. I've been trying a bunch of different ways, but sadly it isn't as easy as it was originally. Essentially we have to emulate the client skipping the plane crash in some way, and then saving that.

    You can load previous saves from a client that has skipped the plane crash and saved it successfully, but the saving through Oxide isn't quite solid yet.
     
  2. Cr4nkSt4r

    Cr4nkSt4r Naked Wanderer

    Would it possible to make a project which loads an noserver savefile and convert this savefile into the one the server understands?
    So everyone can convert their normal created saves into working ones with skipped start.
     
  3. Wulf

    Wulf Community Admin Community Admin Oxide Developer

    They are the same save files, there isn't anything different.
     
  4. Cr4nkSt4r

    Cr4nkSt4r Naked Wanderer

    What's in theese files:
    __RESUME__
    __RESUME__prev
    _Save_Game_Data_
    _Save_Game_Data_prev


    And how can I generate the _Save_Game_Data_ and _Save_Game_Data_prev with my normal game?
     
  5. Wulf

    Wulf Community Admin Community Admin Oxide Developer

    Those are all created by The Forest, what they have is beyond me.
     
  6. Cr4nkSt4r

    Cr4nkSt4r Naked Wanderer

    Ah, okay but did you know WHEN the normal game creates the _Save_Game_Data_ file?
    Because for now, I doesn't even create this file for me in normal game.
     
  7. Wulf

    Wulf Community Admin Community Admin Oxide Developer

    I don't, all I know is it creates the files. Like I said, I haven't really worked out the save system in the game, it seems to have a bunch of mixed messes of code for saving.
     
  8. Cr4nkSt4r

    Cr4nkSt4r Naked Wanderer

    Thank you for your fast answer, so for now, it's a mystery.

    And this is your exprimental code for skipping the crash scene?
    Code (Text):
    Scene.TriggerCutScene.SpaceTut.SetActive(false);
    Scene.TriggerCutScene.LightsFlight.SetActive(false);
    Scene.TriggerCutScene.pmTrigger.SendEvent("toSkipOpening");
    //Scene.TriggerCutScene.skipOpening = true;
    scene.planeController.setPlanePosition();

    if (Scene.TriggerCutScene && Scene.TriggerCutScene.planeController) Scene.TriggerCutScene.planeController.enabled = false;
    var transform = PlaneCrashLocations.finalPositions[PlaneCrashLocations.crashSite].transform;
    scene.planeController.transform.position = transform.position;
    scene.planeController.transform.rotation = transform.rotation;
    var gameObjectArray = scene.enableAfterCrash;
    foreach (var gameObject in gameObjectArray) if (gameObject) gameObject.SetActive(true);
    Scene.PlaneGreebles.transform.position = scene.planeController.transform.position;
    Scene.PlaneGreebles.transform.rotation = scene.planeController.transform.rotation;
    Scene.PlaneGreebles.SetActive(true);

    UnityEngine.Object.Destroy(scene);
     
  9. Wulf

    Wulf Community Admin Community Admin Oxide Developer

    That's some of it.
     
    Cr4nkSt4r likes this.
  10. Cr4nkSt4r

    Cr4nkSt4r Naked Wanderer

    What's with one of theese:

    endPlaneAnimEvents:
    Code (Text):

    public class endPlaneAnimEvents : MonoBehaviour
    {
        public GameObject explosion;

        public endPlaneAnimEvents()
        {
            base..ctor();
            return;
        }

        private void enableWingExplosion()
        {
            this.explosion.SetActive(1);
            return;
        }
    }
     
    If we can't send space, what if we can trigger the events itself, eg the wing explosion?


    LandingGear:
    Code (Text):
    public class LandingGear : MonoBehaviour
    {
        private Animator animator;
        public float lowerAtAltitude;
        private AeroplaneController plane;
        public float raiseAtAltitude;
        private GearState state;

        public LandingGear()
        {
            this.raiseAtAltitude = 40f;
            this.lowerAtAltitude = 40f;
            this.state = 1;
            base..ctor();
            return;
        }

        private void Start()
        {
            this.plane = base.GetComponent<AeroplaneController>();
            this.animator = base.GetComponent<Animator>();
            return;
        }

        private unsafe void Update()
        {
            Vector3 vector;
            Vector3 vector2;
            if (this.state != 1)
            {
                goto Label_0046;
            }
            if (this.plane.Altitude <= this.raiseAtAltitude)
            {
                goto Label_0046;
            }
            if (&base.GetComponent<Rigidbody>().velocity.y <= 0f)
            {
                goto Label_0046;
            }
            this.state = -1;
        Label_0046:
            if (this.state != -1)
            {
                goto Label_008C;
            }
            if (this.plane.Altitude >= this.lowerAtAltitude)
            {
                goto Label_008C;
            }
            if (&base.GetComponent<Rigidbody>().velocity.y >= 0f)
            {
                goto Label_008C;
            }
            this.state = 1;
        Label_008C:
            this.animator.SetIntegerReflected("GearState", this.state);
            return;
        }

        private enum GearState
        {
            Lowered = 1,
            Raised = -1
        }
    }
    There is some positioning about the plane.


    PlaneCrashController:
    Code (Text):
    public class PlaneCrashController : MonoBehaviour
    {
        [SerializeThis]
        public bool Crashed;
        public bool doneHidePlayer;
        public bool fakePlaneActive;
        public GameObject savedHullPrefab;
        [HideInInspector]
        public Transform savePos;
        public bool ShowCrash;

        public PlaneCrashController()
        {
            base..ctor();
            return;
        }

        [DebuggerHidden]
        public IEnumerator InitPlaneCrashSequence()
        {
            <InitPlaneCrashSequence>c__Iterator1E1 iteratore;
            iteratore = new <InitPlaneCrashSequence>c__Iterator1E1();
            iteratore.<>f__this = this;
            return iteratore;
        }

        private void loadCrashPlane()
        {
            UnityEngine.Object.Instantiate(this.savedHullPrefab, this.savePos.position, this.savePos.rotation);
            if (CoopPeerStarter.DedicatedHost != null)
            {
                goto Label_0047;
            }
            if (LocalPlayer.Inventory.CurrentView != -1)
            {
                goto Label_0047;
            }
            LocalPlayer.Inventory.CurrentView = 0;
        Label_0047:
            this.fakePlaneActive = 1;
            Scene.PlaneGreebles.transform.position = this.savePos.position;
            Scene.PlaneGreebles.transform.rotation = this.savePos.rotation;
            Scene.PlaneGreebles.SetActive(1);
            if (BoltNetwork.isRunning == null)
            {
                goto Label_00A1;
            }
            if (BoltNetwork.isClient == null)
            {
                goto Label_00A1;
            }
        Label_00A1:
            return;
        }

        private void OnDeserialized()
        {
            base.Invoke("setupCrashedPlane", 0.3f);
            return;
        }

        private void setupCrashedPlane()
        {
            this.setupCrashedPlane(GameObject.FindGameObjectWithTag("savePlanePos").transform);
            return;
        }

        private void setupCrashedPlane(Transform t)
        {
            if (Scene.PlaneCrashAnimGO == null)
            {
                goto Label_0019;
            }
            UnityEngine.Object.Destroy(Scene.PlaneCrashAnimGO);
        Label_0019:
            this.savePos = t;
            if (this.savePos == null)
            {
                goto Label_004A;
            }
            base.Invoke("loadCrashPlane", 0.15f);
            UnityEngine.Debug.Log("fake plane loaded");
        Label_004A:
            return;
        }

        public void SetupCrashedPlane_MP()
        {
            Transform transform;
            transform = new GameObject("MPHostPlanePos").transform;
            transform.position = CoopServerInfo.Instance.state.PlanePosition;
            transform.rotation = CoopServerInfo.Instance.state.PlaneRotation;
            this.setupCrashedPlane(transform);
            return;
        }

        private void Start()
        {
            Scene.PlaneCrash = this;
            return;
        }

        [CompilerGenerated]
        private sealed class <InitPlaneCrashSequence>c__Iterator1E1 : IEnumerator, IDisposable, IEnumerator<object>
        {
            internal object $current;
            internal int $PC;
            internal PlaneCrashController <>f__this;

            public <InitPlaneCrashSequence>c__Iterator1E1()
            {
                base..ctor();
                return;
            }

            [DebuggerHidden]
            public void Dispose()
            {
                this.$PC = -1;
                return;
            }

            public bool MoveNext()
            {
                uint num;
                bool flag;
                num = this.$PC;
                this.$PC = -1;
                switch (num)
                {
                    case 0:
                        goto Label_0021;

                    case 1:
                        goto Label_0039;
                }
                goto Label_00A9;
            Label_0021:
                goto Label_0039;
            Label_0026:
                this.$current = null;
                this.$PC = 1;
                goto Label_00AB;
            Label_0039:
                if (Scene.LoadSave != null)
                {
                    goto Label_0026;
                }
                if (this.<>f__this.Crashed != null)
                {
                    goto Label_00A2;
                }
                if (this.<>f__this.ShowCrash == null)
                {
                    goto Label_00A2;
                }
                this.<>f__this.Crashed = 1;
                if (Scene.PlaneCrashAnimGO == null)
                {
                    goto Label_00A2;
                }
                if (Scene.PlaneCrashAnimGO.activeSelf == null)
                {
                    goto Label_00A2;
                }
                Scene.TriggerCutScene.StartCoroutine("beginPlaneCrash");
            Label_00A2:
                this.$PC = -1;
            Label_00A9:
                return 0;
            Label_00AB:
                return 1;
                return flag;
            }

            [DebuggerHidden]
            public void Reset()
            {
                throw new NotSupportedException();
            }

            object IEnumerator<object>.Current
            {
                [DebuggerHidden]
                get
                {
                    return this.$current;
                }
            }

            object IEnumerator.Current
            {
                [DebuggerHidden]
                get
                {
                    return this.$current;
                }
            }
        }
    }
    What if we can trigger the SetupCrashedPlane_MP or something to do that instead of skipping or recreating the events or the crash itself?
    So the game generates all this stuff and can save it afterwards fo a clean state save.


    EndCrash_Meta:
    Code (Text):

    internal class EndCrash_Meta : Event_Meta, IEventFactory, IFactory
    {
        internal static EndCrash_Meta Instance;

        static EndCrash_Meta()
        {
            Instance = new EndCrash_Meta();
            Instance.InitMeta();
            return;
        }

        public EndCrash_Meta()
        {
            base..ctor();
            return;
        }

        void IEventFactory.Dispatch(Event ev, object target)
        {
            IEndCrashListener listener;
            listener = target as IEndCrashListener;
            if (listener == null)
            {
                goto Label_0019;
            }
            listener.OnEvent((EndCrash) ev);
        Label_0019:
            return;
        }

        object IFactory.Create()
        {
            return new EndCrash();
        }

        internal override void InitMeta()
        {
            NetworkProperty_Bool @bool;
            base.TypeId = new TypeId(0x99);
            base.CountStorage = 1;
            base.CountObjects = 1;
            base.CountProperties = 1;
            base.Properties = new NetworkPropertyInfo[1];
            @bool = new NetworkProperty_Bool();
            @bool.PropertyMeta = this;
            @bool.Settings_Property("Aborted", 1, -1073741824);
            @bool.Settings_Offsets(0, 0);
            base.AddProperty(0, 0, @bool, -1);
            base.InitMeta();
            return;
        }

        internal override void InitObject(NetworkObj obj, NetworkObj_Meta.Offsets offsets)
        {
        }

        TypeId IFactory.TypeId
        {
            get
            {
                return base.TypeId;
            }
        }

        UniqueId IFactory.TypeKey
        {
            get
            {
                return new UniqueId(190, 0x87, 0xed, 40, 0xc2, 0xd5, 0x22, 0x4d, 0x88, 0x26, 150, 0x57, 14, 0x31, 0x5c, 0xc4);
            }
        }

        Type IFactory.TypeObject
        {
            get
            {
                return typeof(EndCrash);
            }
        }
    }
     
    Maybe here is some way to skip the crash?
    Or is this when the game crash itself?


    I'm not familar with C# but I looked a bit into the forest code for myself.
    But at the moment I didn't know how I can trigger something or hook into a function with your Oxidemod sourcecode and then for example hook into the function to start the game or some other who is in front of the plane crash and then trigger SetupCrashedPlane_MP or something.

    Maybe you can or anyone who is familar with C# etc. and want to help, if some of theese things can help, or anyone can give me an example how I can hook a function from the forest with Oxide Source an how I can then call another funcion to trigger something. Maybe an existing example, Oxide have something I think.
    Then I'll try to get this by myself.


    ~ regards

    PS:
    I couldn't find a spoiler tag or something to shorten the message.
     
    Last edited: Jan 9, 2017
  11. Wulf

    Wulf Community Admin Community Admin Oxide Developer

    Yes, I've been trying to find a reliable way to skip the plane crash for months. ;)

    The issue isn't with what needs to be done, it's with how it needs to be done.
     
  12. Cr4nkSt4r

    Cr4nkSt4r Naked Wanderer

    Yeah that's why I looked into the code and tryd to make a suggestion to any of theese code parts.
    And I would try to do it mself if I would know at the moment how to do it ^^
    That's why I search the net for some information about this stuff.
    If you haven't an short example I need to look frward in the net :)


    ~ regards
     
  13. Cr4nkSt4r

    Cr4nkSt4r Naked Wanderer

    @Wulf But why will old saves from oxide still work when new ones didn't?
    So they must have this plane position, do you have an old version of oxide where saving was working or a version number/date?
    I mean, you fixed so much, maybe one of thoose fixes corrupted the save function or smething.

    I got an old save from Host 2, everything works great with that save, except it has already progress on it ^^
    And I'm still interested in fixing this, with or without your help but at least, this info about the version of Oxide would be nice :)


    ~ regards
     
  14. Wulf

    Wulf Community Admin Community Admin Oxide Developer

    Saving has never really been working properly. It all depends on if the save has a plane crash position set or not.
     
  15. Cr4nkSt4r

    Cr4nkSt4r Naked Wanderer

    But how should it be possble to have at least one file with this position and all new files not?
    If the save process is wrong on its own, this shouldn't ever happen to work, but it did.

    And which use do the MSILHash have? I found many of them in the "TheForest.opj" file.


    ~ regards
     
  16. Wulf

    Wulf Community Admin Community Admin Oxide Developer

    The hashes in the .opj are generated from our patcher based on the DLL at the time of use. Save files can be loaded that had a crash position set, but Oxide doesn't actually save that position if starting new.
     
  17. Cr4nkSt4r

    Cr4nkSt4r Naked Wanderer

    Thank you for your fast answer.

    If I start a new game as host without Oxide, then copy theese save files over, it also say there is no plane crash position but I can reload the saves everytime I want without Oxide.
    So, at some point, Oxide worked with theese old files created without Oxide without having trouble, so something have to change or how should it even possible? Or does the game change something Oxide can't handle with new generated ones?

    I'm a little bit confused :-/
    Oxide newer worked correct with new created games in Oxide because no plane crash position
    Oxide worked fine with pre-created saves from an local hosted server without Oxide in The Forest verson ?.?
    Oxide don't work with pre-created saves from an local hosted server without Oxide since? (atm The Forest 0.52b)
    There have to be a change that this do not work with the latest version or some other version of The Forest. No plane crash position.

    And which changed should be made when a new The Forest version will be released? New version is close to release, so I can change it for myself.
    I also looked through the code of Oxide to the point where -batchmode -nographics get parsed and then calling a function to disable.
    If I comment out this stuff, no change is made when I start the game after replacing the old files with the new created ones. If I delete -batchmode -nographics in _start-example.bat, then I see some changes, but the change in code should affect this at all.
    Do you know what I did wrong? This was for testing propose.

    TheForestCore.cs
    Code (Text):
    if (commandLine.HasVariable("batchmode") || commandLine.HasVariable("nographics"))
    {
      //TheForestExtension.Disablei_love_codeo();
      //TheForestExtension.DisableClient();
    }
    This change I made.


    ~ regards
     
  18. Wulf

    Wulf Community Admin Community Admin Oxide Developer

    I'm not sure what you're trying to do with the commented out parts, but those are there to handle making the client into a headless server. If you don't want to run headless, then you can simply not set batchmode and nographics when you start the game.

    Updating to the next version of The Forest requires knowing how to use our Oxide Patcher, and possibly more depending on the changes in the update.
     
  19. Cr4nkSt4r

    Cr4nkSt4r Naked Wanderer

    Yes, I try to start in noal mode with the server, if I delete from batch, it will start in normal mode and not console but when I change the Code from Oxide source so if theese two options are written or not, he MUST go into normale mode because it will not disable the GUI and i_love_codeo, but if I do this and update the result in my Oxide Server Folder structure "TheForest_Data" it does load in console mode which can't met te condition because I commented this stuff out. All my changes arent saved in the "Oxide-develop\Bundles\TheForest" Files.


    ~ regards
     
  20. Wulf

    Wulf Community Admin Community Admin Oxide Developer

    Right, but the server will still run even if you don't see the console. The whole point of those settings is to provide that console if desired, and those settings are just meant to increase the performance of it as a headless/dedicated server. Neither of them would have anything to do with the save process though.