Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use SSE Events to push realtime data from the internal server to the webmap #8

Merged
merged 69 commits into from
May 1, 2024

Conversation

granny
Copy link
Owner

@granny granny commented Oct 27, 2023

Overview

This pull request introduces the integration of Server-Sent Events (SSE) into our internal webserver, enabling real-time data updates for our webmap. Using SSE we can achieve seamless real-time updates, significantly enhancing the user experience.

Details

Here are the key features and functionalities that this pull request will bring:

  1. SSE provides real-time player position updates, allowing the webmap to track and display accurate player positions as they rotate and run around.
  2. SSE facilitates immediate marker updates, making sure that any adjustments or additions to markers are instantly reflected on the webmap.
  3. In cases where SSE connections are closed or nonexistent, the system gracefully falls back to updating through the old system, which is done through files.
  4. When an SSE connection is established, the frontend bypasses file-based checks entirely.

What if I want this but I have the internal server disabled ???

You can still get the advantages of this change if you use an external server. Just re-enable the internal web server under a different port and set up a reverse proxy that points only to the /sse endpoint. This means you can gain the functionality of real-time data updates while the server is running, while also keeping the map available to view, even if the minecraft server is offline.

/sse reverse proxy Caddy example:
map.example.com {
    root * /var/www/map.example.com/
    file_server

    reverse_proxy /sse* localhost:8084 {
        flush_interval -1
    }

    @gz {
        path *.gz
    }

    handle @gz {
        header Content-Encoding gzip
    }
}
/sse reverse proxy NGINX example:
server {
    server_name map.example.com;

    root /var/www/map.example.com/;
    index index.html;

    location ~ \.gz$ {
      gzip off; # Ensure nginx doesn't double-compress
      add_header Content-Encoding gzip;
    }

    location /sse {
      chunked_transfer_encoding off;
      proxy_buffering off;
      proxy_cache off;
      proxy_pass http://<SERVER IP>:<Pl3xMap Internal Web Server Port>;
    }
}

API Changes

Internally, layers used to update in a per-second basis, which meant everything was configured in seconds. This PR changes that so everything runs in ticks instead. I tried to make sure that all API methods that state "seconds" correctly return or set the update interval as seconds. More specifically, I've overloaded Layer#setUpdateInterval and Scheduler#addTask(...) with an extra boolean parameter called ticks that indicates whether to return or accept the interval as ticks.

LiveDataHandler.java

A LiveDataHandler class has been added to help with pushing data to the SSE endpoints. There is one global SSE handler that sends data to /sse, and each world has it's own handler that sends data to /sse/<world>. If you hit /sse/<world> with an invalid world, you'll receive a JSON error that lists available worlds (worlds that are disabled will not appear). This is not really API, so don't expect it to be stable if it gets changed in the future.

image

Layer.java

The following methods were added to the Layer class. Any created layers will by default return false when isLiveUpdate() is called, which will stop the layer from being pushed through SSE. If you believe that your custom layers should be able to update through SSE, then call setLiveUpdate(true) when creating your layer.

    /**
     * Get if this layer gets pushed through sse.
     *
     * @return true if being sent through sse
     */
    public @Nullable boolean isLiveUpdate() {
        return this.liveUpdate;
    }

    /**
     * Set whether to push this layer through sse.
     *
     * @param liveUpdate true to push this layer through sse.
     * @return this layer
     */
    public @NotNull Layer setLiveUpdate(@Nullable boolean liveUpdate) {
        this.liveUpdate = liveUpdate;
        return this;
    }

Download the pl3xmap jar for this pull request: pl3xmap-8.zip

@granny
Copy link
Owner Author

granny commented Oct 27, 2023

A preview of what it looks like when a player is moving around:

2023-10-22.02-52-04.mp4

@granny granny linked an issue Oct 27, 2023 that may be closed by this pull request
@zndrmn
Copy link

zndrmn commented Nov 11, 2023

that is actually so cool, really hope this becomes a thing eventually

@Folas1337
Copy link

I can also only express my utmost interest in this. It looks like an absolute killer feature for this plugin 😎

@Folas1337
Copy link

Wohooo more progress 😄 If you need someone to test this out, feel free to get in contact with me.

@granny
Copy link
Owner Author

granny commented Dec 22, 2023

Wohooo more progress 😄 If you need someone to test this out, feel free to get in contact with me.

I'll most likely release a test build when I think it's ready for testing before I merge it into the main project! I'll make sure to mention you when that happens :)

@granny
Copy link
Owner Author

granny commented Mar 15, 2024

I'm pretty satisfied with the progress made in this PR. Pending any reported issues regarding code design or bugs resulting from these changes, this PR will be merged sometime next month. During this period, I would like some help from all of you in putting together Apache and NGINX configurations that will allow proper SSE functionality. I have already configured Caddy successfully (example in the PR description), so if anyone has a functioning setup with Apache or Nginx, please share it with me in the Discord server. (SSE prefers batch data transmission, which may hinder real-time updates.)

For those interested in conducting tests to ensure consistency, I recommend enabling the debug option in the config file and observing how the logs update between the browser and the server. If properly configured, they should both update simultaneously. Please refer to the video below for a demonstration. If the server logs update instantly while those in the browser do not, it indicates a problem with the reverse proxy configuration.

Please report any issues with this PR in the discord server.

The auto-updating link to the build with the most recent changes is available at the bottom of the PR description.

2024-03-14.21-17-21.mp4

@Folas1337
Copy link

Next month is almost over 😛
Just wanna remind you of this and even though I had to switch from nginx to caddy, it's been running super smooth ever since 😄

I hope to see this merged soon!

@granny
Copy link
Owner Author

granny commented Apr 27, 2024

Will be merged into the first build for 1.20.6 :)

@granny granny changed the base branch from v3 to chore/1-20-6 May 1, 2024 10:02
@granny granny merged commit 1891263 into chore/1-20-6 May 1, 2024
1 of 4 checks passed
@granny granny deleted the feat/sse-events branch May 1, 2024 10:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
build-pr-jar Enables a workflow to build Pl3xMap jars on the pull request.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Suggestion: Using Websockets instead of periodic AJAX polling
5 participants