Jump to content

[Forge 1.14.4] Loading saved world


geekles

Recommended Posts

I am currently working on creating a method that lets me load a world from the world saves directory, however, after calling launchIntegratedServer to hopefully start loading up the world, I get some kind of *out of context* error that I'm not sure how to handle or resolve.

This is my current setup:

    public static void joinWorld(String world) {
        Minecraft mc = Minecraft.getInstance();
        SaveHandler handler = mc.getSaveLoader().getSaveLoader(world, mc.getIntegratedServer());
        WorldInfo info = handler.loadWorldInfo();
        if (info != null) {
            WorldSettings settings = new WorldSettings(info.getSeed(), info.getGameType(), info.isMapFeaturesEnabled(), info.isHardcore(), info.getGenerator());
            mc.launchIntegratedServer(handler.getWorldDirectory().getAbsolutePath(), world, settings);
            LogManager.getLogger().info("World: " + info.getWorldName());
        }
    }

Stacktrace:

FATAL ERROR in native method: Thread[Thread-15,5,main]: No context is current or a function that is not available in the current context was called. The JVM will abort execution.
	at org.lwjgl.opengl.GL11.glPushMatrix(Native Method)
	at com.mojang.blaze3d.platform.GlStateManager.pushMatrix(GlStateManager.java:572)
	at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:916)
	at net.minecraft.client.Minecraft.func_213241_c(Minecraft.java:1710)
	at net.minecraft.client.Minecraft.func_213231_b(Minecraft.java:1683)
	at net.minecraft.client.Minecraft.func_213254_o(Minecraft.java:1667)
	at net.minecraft.client.Minecraft.launchIntegratedServer(Minecraft.java:1563)

 

Edited by geekles
Link to comment
Share on other sites

On 12/13/2019 at 3:20 AM, diesieben07 said:

Where are you calling this method? What are you trying to achieve?

I'm calling the Minecraft#launchIntegratedServer() function since the CreateWorldScreen class does the same when creating a world. I'm merely trying to replicate the actions used to create/load a new or existing world. 

 

CreateWorldScreen#createWorld() 

 
 
 
 
Spoiler

   private void createWorld() {
      this.minecraft.displayGuiScreen((Screen)null);
      if (!this.alreadyGenerated) {
         this.alreadyGenerated = true;
         long i = (new Random()).nextLong();
         String s = this.worldSeedField.getText();
         if (!StringUtils.isEmpty(s)) {
            try {
               long j = Long.parseLong(s);
               if (j != 0L) {
                  i = j;
               }
            } catch (NumberFormatException var6) {
               i = (long)s.hashCode();
            }
         }
         WorldType.WORLD_TYPES[this.selectedIndex].onGUICreateWorldPress();

         WorldSettings worldsettings = new WorldSettings(i, GameType.getByName(this.gameMode), this.generateStructuresEnabled, this.hardCoreMode, WorldType.WORLD_TYPES[this.selectedIndex]);
         worldsettings.setGeneratorOptions(Dynamic.convert(NBTDynamicOps.INSTANCE, JsonOps.INSTANCE, this.chunkProviderSettingsJson));
         if (this.bonusChestEnabled && !this.hardCoreMode) {
            worldsettings.enableBonusChest();
         }

         if (this.allowCheats && !this.hardCoreMode) {
            worldsettings.enableCommands();
         }

         this.minecraft.launchIntegratedServer(this.saveDirName, this.worldNameField.getText().trim(), worldsettings);
      }
   }

 

 

Link to comment
Share on other sites

On 12/14/2019 at 5:15 PM, diesieben07 said:

You have not answered my first question.

I'm working on a mod (for a personal project of mine) that allows for the game to be controlled wirelessly through commands. It's a challenge for the game where the output from the game will be streamed to connected viewers. The audience may control the game's instance through commands. I currently have it so that the ingame character's movement may be controlled via commands as well as specifying which multiplayer server to join etc. however loading up a singleplayer world is ironically seemingly more tedious and I haven't been able to get far with that part. I would like to give the audience the opportunity to either choose to join a server and try controlling the game through commands only or choose to create or join a pre-existing singleplayer world. Naturally, checks will be made to ensure no one abuses this system and tries spamming servers with connection requests. 

Edited by geekles
Link to comment
Share on other sites

8 hours ago, diesieben07 said:

You still have not answered the first question.

Where are you calling this method? Show the code.

public class WorldCmd implements CommandExecutor {

    @Override
    public boolean onCommand(String[] args) {
        if(!args[0].equalsIgnoreCase("world"))
            return false;
        if(args.length == 2)
            NetworkUtil.joinWorld(args[1]);
        return true;
    }
}

 

Link to comment
Share on other sites

3 hours ago, diesieben07 said:

CommandExecutor is not a class added by Forge or Minecraft. As such your code still does not answer my question, as it is not clear how you are using this WorldCmd class and where onCommand is called.

Should I send over my entire project? ? CommandExecutor is an interface I implemented. CommandManager is a class that is responsible for registering these interfaces and setting up a listener for a class responsible for collecting outputs from a node.js proxy connection. Whenever a response is returned, the message is handled and then passed over to the listener that CommandManager uses. It then takes the string, converts it into an array of string command arguments and passes it to all the registered CommandExecutor. I know there's a more efficient method of going about doing this, e.g. associating aliases for each of these classes so that CommandManager can instead pass the parameter to only one of the classes instead of passing it to all of them blindly, however considering that this project is relatively small, and I have not created too many commands yet, but is something I intend to correct soon. But the information you're asking for now is quite redundant since now you're getting into how my entire project is functioning and not staying particularly focused on the subject of why the following line is throwing an error.

mc.launchIntegratedServer(handler.getWorldDirectory().getAbsolutePath(), world, settings);

I suppose first you can highlight what that error ("No context is current or a function that is not available in the current context was called") means since I'm quite unfamiliar with it and would like a general explanation of why the minecraft client throws it. Secondly, if you really need more information, please explain for what purpose, because at this point, I feel going back and forth like this is quite inefficient, and isn't getting us anywhere. If you have a question about the particular functionality of a class, then please ask and I'll explain.

Edited by geekles
Link to comment
Share on other sites

2 hours ago, geekles said:

I feel going back and forth like this is quite inefficient, and isn't getting us anywhere. If you have a question about the particular functionality of a class, then please ask and I'll explain.

This would be avoidable if you provide your project as a GitHub repo.

Some tips:

Spoiler

Modder Support:

Spoiler

1. Do not follow tutorials on YouTube, especially TechnoVision (previously called Loremaster) and HarryTalks, due to their promotion of bad practice and usage of outdated code.

2. Always post your code.

3. Never copy and paste code. You won't learn anything from doing that.

4. 

Quote

Programming via Eclipse's hotfixes will get you nowhere

5. Learn to use your IDE, especially the debugger.

6.

Quote

The "picture that's worth 1000 words" only works if there's an obvious problem or a freehand red circle around it.

Support & Bug Reports:

Spoiler

1. Read the EAQ before asking for help. Remember to provide the appropriate log(s).

2. Versions below 1.11 are no longer supported due to their age. Update to a modern version of Minecraft to receive support.

 

 

Link to comment
Share on other sites

2 hours ago, diesieben07 said:

Context is important.

You are most likely not doing this on the Minecraft main thread.

Minecraft is not threadsafe.

Thank you for the information. I looked into it, and yes, I forgot to consider that I am on a separate thread. This is because the listener I spoke about earlier is called from a separate thread. Is there a client supported asynchronous method that I can use to easily switch back to its main thread?

Link to comment
Share on other sites

7 minutes ago, geekles said:

Thank you for the information. I looked into it, and yes, I forgot to consider that I am on a separate thread. This is because the listener I spoke about earlier is called from a separate thread. Is there a client supported asynchronous method that I can use to easily switch back to its main thread?

I see my problem. I'll try to rewrite my proxy response checker and subscribe to the client's tick instead of running the checks on a new thread.

Link to comment
Share on other sites

How would I go about creating a connection on a separate thread but then calling a listener synchronous with the main thread with the result? Currently my last issue is synchronously starting my "ProxyResponseReader" class if the connection was successful.

new SocketConnection("127.0.0.1", 8080).connect().onConnectionResult(new ConnectionResultEvent() {
            @Override
            public void onResult(boolean connected) {
                if(Thread.currentThread() == Main.t) {
                    System.out.println("onResult: Same Thread!");
                } else {
                    System.out.println("onResult: Other Thread!"); //not on the main thread
                }
                if (connected) {
                    reader = new ProxyResponseReader(socket);
                    return;
                }
            [...]
          }
  }
    private static class SocketConnection {
        private Socket socket;

        private final String ip;
        private final int port;

        private ConnectionResultEvent event;

        public SocketConnection(String ip, int port) {
            this.ip = ip;
            this.port = port;
        }

        // make the connection with the socket
        private SocketConnection connect() {

            new Thread() {
                public void run() {
                    try {
                        SocketConnection.this.socket = new Socket(ip, port);
                        SocketConnection.this.event.onResult(true);
                    } catch (IOException e) {
                        SocketConnection.this.event.onResult(false);
                    }
                }
            }.start();
            return this;
        }

        public void onConnectionResult(ConnectionResultEvent event) {
            this.event = event;
        }
     
        [...]
     }

 

Edited by geekles
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.