Announcement

Collapse
No announcement yet.

[MOD] Chest of Holding

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    [MOD] Chest of Holding

    Sticks a chest in the game that will allow players to carry items between games. Useful for carrying important items across server wipes.

    It's a bit "strange" because there's no way to properly write the file without using the UpdateTick() method (most people won't know what this means, and that's fine) so there is a random delay of anywhere from instant to several minutes before the file is created. If the server goes down or the player quits during this time...all those items are lost. It's actually for this reason I didn't include this in the SmartContainers mod.

    If anyone can think of a better way of writing the storage file, I'm all ears. I've tried OnBlockUnloaded() and it refuses to write.

    There's no recipe for the Chest of Holding, it's more of a mod tool...so use the creative menu to access it. One chest will produce different items for each player who uses it...so there's no need for each player to have one.

    Before building, you need to go into the config file and change the DataDir property. It's currently set for my computer, and it WILL create the directory if it doesn't exist, so no NREs, but it's probably more convenient for you if you set it to someplace you'll remember.

    THANKS TO HAL9000 FOR THE SCRIPTING HELP!

    Download:
    https://www.mediafire.com/?xw1xaz2qavpyotm
    Last edited by Carlzilla; 08-02-2016, 01:16 AM.

    #2
    awesome.

    Comment


      #3
      I've used the block unload event to write out a file for Pacco's radio. Do you have the right signature for the method?

      Code:
          public override void OnBlockUnloaded(WorldBase _world, int _clrIdx, Vector3i _blockPos, BlockValue _blockValue)
          {
              //do stuff
              base.OnBlockUnloaded(_world, _clrIdx, _blockPos, _blockValue);
          }

      Comment


        #4
        I'll try it again...but yeah, I had it correct, it just didn't write.

        Comment


          #5
          Unloaded is for when the chunk gets unloaded because you've moved away from it. If you're destroying the chest it's probably OnBlockRemoved() or OnBlockDestroyedBy() you want.

          Comment


            #6
            Yeah, I'm trying to get it to write on exit.

            But there's nothing for that in the existing methods.

            Comment


              #7
              I just tried a quick demo on the switch mod and unload worked when quitting the game.

              Code:
                public override void OnBlockUnloaded(WorldBase _world, int _clrIdx, Vector3i _blockPos, BlockValue _blockValue)
                  {
                      Debug.Log("Unloading switch at " + _blockPos.ToString());
                      base.OnBlockUnloaded(_world, _clrIdx, _blockPos, _blockValue);
                  }
              Got me

              Code:
              2016-08-01T18:33:09 69.508 INF NET: Untiy NW server stopped
              2016-08-01T18:33:09 69.509 INF [Steamworks.NET] NET: Server stopped
              2016-08-01T18:33:09 69.509 INF [NET] ServerShutdown
              2016-08-01T18:33:09 69.510 INF SaveAndCleanupWorld
              2016-08-01T18:33:09 69.667 INF Saving 101 of chunks took 101ms
              2016-08-01T18:33:09 69.670 INF [Steamworks.NET] Stopping server
              2016-08-01T18:33:09 69.700 INF World.Unload
              Unloading switch at 1406, 115, -1081
               
              (Filename: C:/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 37)
              
              Unloading switch at 1406, 114, -1081
               
              (Filename: C:/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 37)
              
              2016-08-01T18:33:09 69.825 INF Exited thread thread_GenerateChunks
              2016-08-01T18:33:10 69.919 INF Exited thread thread_Pathfinder
              2016-08-01T18:33:10 69.920 INF World.Cleanup
              2016-08-01T18:33:10 69.921 INF Exited thread thread_Regenerating
              2016-08-01T18:33:10 69.921 INF Exited thread CM
              2016-08-01T18:33:10 69.921 INF Removing observed entity 1
              2016-08-01T18:33:10 69.957 INF Persistent GamePrefs saved
              2016-08-01T18:33:10 69.958 INF Cleanup
              So maybe the tile entity isn't available during the world clean up phase?

              Comment


                #8
                Yeah, that's probably it, it's already been cleared out. I do have a if (entityLootContainer == null) return; so that perfectly explains why nothing is being committed to file.

                I think what I'm going to have to do is use a player initiated content save. E to open Shift+E to save...something like that.

                I just REALLY don't like the current setup at all.

                Comment


                  #9
                  This is the nearest I could get it. A bit hacky but I don't see a way round it. It just uses a coroutine to check if the player has the window open. Once he doesn't it can run the save function

                  Code:
                      public override bool OnBlockActivated(int _indexInBlockActivationCommands, WorldBase _world, int _cIdx, Vector3i _blockPos, BlockValue _blockValue, EntityAlive _player)
                      {        
                          if (!GameManager.IsDedicatedServer) //only run on SP
                             GameManager.Instance.StartCoroutine(SaveOnModalClose());
                  
                          return base.OnBlockActivated(_indexInBlockActivationCommands, _world, _cIdx, _blockPos, _blockValue, _player);
                      }
                  
                      IEnumerator SaveOnModalClose()
                      {
                          Debug.Log("Checking for window close");
                          WaitForSeconds ret = new WaitForSeconds(1f);
                          while(GameManager.Instance.windowManager.IsModalWindowOpen())
                          {
                              Debug.Log("Window is open...");
                              yield return ret;
                          }
                          Debug.Log("Save it!");
                      }

                  Comment


                    #10
                    I thought about doing a coroutine, but I'd never used one before, so I wasn't exactly sure how to go about that. Thanks for this, HAL, it's much appreciated.

                    Comment


                      #11
                      No worries, if you've done any work with threads you'll get coroutines easily enough. The benefit of coroutines though is they're still run on the main thread so you don't have to worry about thread safety. The function pauses at the yield until the WaitFor you specify (there's a few to choose from) completes and then continues from there.

                      They have pros and cons but definitely a nice tool to have in the arsenal.

                      Comment


                        #12
                        Updated, thanks to HAL9000 (as you can probably see), the chest now saves it's contents upon leaving the inventory window back into the game.

                        A much better system than the jankey one I had in place.

                        Same link.

                        Comment


                          #13
                          One more question, HAL, if I may...

                          Does using the coroutine make it so that it only functions in single player, or that the files are only written to the client machines? I'd like to try to maintain server compatibility if possible, so I can use the auto-save on SP and the player induced save (which does work on multiplayer as far as I know) for servers if coroutines will not work.

                          Comment


                            #14
                            That coroutine will only work for SP as there's no modal window to check for on the server but you could change the function to check whether the tile entity is locked instead. That would work on both SP and MP I think.

                            Only the server should be saving the file so you don't have both server and client trying to change the contents of the container. You'd just need a check to see if the code is being run by a connected client or not. That's probably doable by checking the game mode and the IsServer property of the ConnectionManager class.

                            Comment

                            Working...
                            X