1.15.2 [Solved] Cannot Read BlockState Due To Consumer

Discussion in 'Spigot Plugin Development' started by AlexisEvelyn, Mar 30, 2020.

  1. Hello, I'm writing a plugin that will give lecterns the ability to send/receive redstone signal. I'm able to send the redstone signal strength to the internet just fine, however, when I go to receive it, I cannot get the blockstate of the lectern to change the signal strength.

    Now, receiving the messages itself works just fine, it's just getting the blockstate I have issues with. As for the error that is sent, it's a throwable from RxJava which I just catch and log in my Logger class. The error is
    Code (Text):
    Failed to read BlockState at: world: world location: (9, 70, 135)
    and the world and coordinates are the correct location.

    I believe the error is a result of not executing on the main thread (as this code is running in the callback I passed to the consumer), however, I'm not entirely sure if it is broken due to that reason or how to fix it.

    What would your suggestion be for getting the blockstate of a block from a secondary thread? Thanks!

    The code that is broken:
    Code (Text):

    // Function To Run Asynchronously When Message is Received
    Consumer<Mqtt5Publish> callback = mqtt5Publish -> {
      // ... Redacted because this part here works ...

      // Doesn't Work Asynchronously
      // https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling
      // Failed to read BlockState at: world: world location: (9, 70, 135)
      BlockState snapshot = location.getBlock().getState();
    }
     
    The Log:
    Code (Text):
    [18:55:46 INFO]: Time elapsed: 11621 ms
    [18:55:46 INFO]: [Internet Redstone] Enabling InternetRedstone v0.0.5-SNAPSHOT
    [18:55:47 INFO]: [Internet Redstone] MySQL Version: 5.7.29
    [18:55:47 INFO]: Done (41.675s)! For help, type "help"
    [18:55:47 INFO]: Timings Reset
    [18:55:52 INFO]: UUID of player Alexis_Evelyn is f3b4e8a4-7f52-4b0a-a18d-1af64935a89f
    [18:55:53 INFO]: Alexis_Evelyn[/127.0.0.1:54422] logged in with entity id 4 at ([world]9.371498010778046, 70.125, 133.74504909323537)
    [18:55:57 INFO]: [Internet Redstone] Registered Client For: f3b4e8a4-7f52-4b0a-a18d-1af64935a89f
    [18:55:57 INFO]: [Internet Redstone] With Broker: broker.hivemq.com
    [18:56:06 INFO]: [Internet Redstone] Received Message On Topic: alexis/redstone/lectern
    [18:56:06 INFO]: [Internet Redstone] Message: 15
    [18:56:06 INFO]: [Internet Redstone] Setting Redstone Signal To (Not Implemented): 15
    [18:56:06 ERROR]: [Internet Redstone] Severe Throwable Error (Cannot Recover): The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with. Further reading: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling | java.lang.RuntimeException: Failed to read BlockState at: world: world location: (9, 70, 135)
    [18:56:06 ERROR]: [Internet Redstone] ---
    [18:56:06 ERROR]: [Internet Redstone] 367 - io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:367)
    [18:56:06 ERROR]: [Internet Redstone] 69 - io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:69)
    [18:56:06 ERROR]: [Internet Redstone] 57 - io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
    [18:56:06 ERROR]: [Internet Redstone] 264 - java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    [18:56:06 ERROR]: [Internet Redstone] 304 - java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
    [18:56:06 ERROR]: [Internet Redstone] 1128 - java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    [18:56:06 ERROR]: [Internet Redstone] 628 - java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    [18:56:06 ERROR]: [Internet Redstone] 834 - java.base/java.lang.Thread.run(Thread.java:834)
    [18:56:06 ERROR]: [Internet Redstone] ---
     
    Edit: Running the Bukkit Scheduler in an attempt to make the lectern snapshot code run on the main thread results in the same exact error.

    Bukkit Scheduler Code:
    Code (Text):

    // The Below Called With:
    // Future<Void> runBukkit = Bukkit.getScheduler().callSyncMethod(main, syncBukkit(powerLevel));

    public Callable<Void> syncBukkit(Integer powerLevel) {
        Logger.info(ChatColor.GOLD + "" + ChatColor.BOLD + "Setting Redstone Signal To (Not Implemented): "
                + ChatColor.AQUA + "" + ChatColor.BOLD + powerLevel);

        // Doesn't Work Asynchronously Or In This Callable Method.
        // https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling
        // Failed to read BlockState at: world: world location: (9, 70, 135)
        BlockState snapshot = location.getBlock().getState();

        if (snapshot instanceof Lectern) {
            Lectern lectern = (Lectern) snapshot;

            // TODO: Check to ensure at least 15 pages are in book!!!
            // And that there is a book.
            lectern.setPage(powerLevel);
        }

        snapshot.update();

        return null;
    }
     
     
    #1 AlexisEvelyn, Mar 30, 2020
    Last edited: Mar 31, 2020
  2. So, it turns out I was being an idiot between my first post and my last edit. The call to the "synchronous" function was just a call to retrieve a synchronous function. It was still running asynchronously. To solve the issue, I decided to just make a runnable and call it.

    Now, I just have to figure out why "lectern.setPage(powerLevel);" ends up with the exception, "null". At least, I know don't completely break the subscription code, so I can keep receiving messages after causing the error. The exception I currently have is unrelated to this post, so I'm marking this as solved.

    The Working Code:
    Code (Text):

    if (0 <= powerLevel && powerLevel <= 15) {
        Bukkit.getScheduler().runTask(main, new Runnable() {
            @Override
            public void run() {
                Logger.info(ChatColor.GOLD + "" + ChatColor.BOLD + "Setting Redstone Signal To (Not Implemented): "
                        + ChatColor.AQUA + "" + ChatColor.BOLD + powerLevel);

                // Doesn't Work Asynchronously Or In This Callable Method.
                // https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling
                // Failed to read BlockState at: world: world location: (9, 70, 135)
                try {
                    BlockState snapshot = location.getBlock().getState();

                    if (snapshot instanceof Lectern) {
                        Lectern lectern = (Lectern) snapshot;

                        // TODO: Check to ensure at least 15 pages are in book!!!
                        // And that there is a book.
                        lectern.setPage(powerLevel);
                    }

                    snapshot.update();
                } catch(RuntimeException exception) {
                    Logger.severe(ChatColor.GOLD + "" + ChatColor.BOLD
                            + "Failed To Set Redstone Signal To: "
                            + ChatColor.AQUA + "" + ChatColor.BOLD
                            + powerLevel
                            + ChatColor.RESET);

                    Logger.printException(exception);
                }
            }
        });
    }