Skip to content

How it works

Tautvydas edited this page Aug 31, 2025 · 9 revisions

Internal workings

What is this long text?

  • This is a pseudocode, but in Markdown showing how service fetching works behind the code, yes I had the dedication to write it all.
  • This also shows where what specific placeholders are available, keep in mind that these placeholders are only available in response handlers!

I wonder if someone is going to read this all...

Some notes

  • ISM — if can send a normal message (configurable).
  • ISEM — if can send an error message (configurable).
  • ISDM — if can send a debug message (configurable).
  • break(?) — breaks the loop or skip to the next (fallback) service. If it breaks, then player is disconnected with a message defined near break(?).
  • Each "check fallback" also checks for handlers PRE_FALLBACK_USE and can also possibly break the loop (for example, if handler defined that player is allowed to join).
  • Services are looped through to find a correct service that works for getting player's online unique ID (properties too if needed).
  • If any fallback check (e.g. ON_SERVICE_RATE_LIMITED) is disabled (not in the list in configuration), player will get disconnected.
  • On every error occurrence, placeholders {error.class} (package and class name), {error.message} and {error.class-name} are going to be available.
  • What is %s? It's a placeholder(s) for specific value. (I'm too lazy to explain what each %s is, in some places it's clear, also you can compare those message to your console output.

Below is a pseudo-code-like explanation of how everything works

  • prepare a service list (main + fallbacks), uses configuration's use-service and fallback-services but combined

  • check for the last successful service used if any and modify service list

  • print ISM Player %s original unique ID is %s

  • for each service in the list:

    • if service is unknown print ISM I do not exist in this universe, I shall vanish...
    • if service is disabled, skip to the next service
    • if service doesn't have defined JSON path to UUID (unique ID) or properties, skip to the next service
    • if service is rate-limited
      • print ISEM Service got rate-limited!
      • check fallback ON_SERVICE_RATE_LIMITED and break(?) (RateLimitedDisconnectMessage)
    • initiating service fetching
    • placeholder {username} is available
    • placeholder {uuid} is available
    • placeholder {database-running} is available (true or false)
    • placeholder {service-name} is available
    • placeholder {max-timeout} is available (value from configuration)
    • placeholder {min-timeout} is available (value from configuration)
    • build request
      • if timeout is below min-timeout, immediately disconnect the player with message TimeoutDisconnectMessage as there is not enough execution time left for this and other services!
      • formula for timeout is below min-timeout:
        • totalExecutionTime - incremental number, how much time it took for previous services to fetch data
        • (maxTimeout - totalExecutionTime) <= minTimeout
        • execution max time is calculated to not time out the player because some service took TOO long to fetch!
      • handle PRE_REQUEST response event
      • send request to the service's endpoint
      • if an error occurred
        • print ISEM Connection error (%s), failed to fetch data from the service!
        • print ISDM the exception
        • if error is about time-out, check fallback ON_SERVICE_TIMEOUT and break(?) (TimeoutDisconnectMessage)
        • if any other error, check fallback ON_CONNECTION_ERROR and break(?) (ConnectionErrorDisconnectMessage)
    • placeholder {http.url} is available
    • placeholder {http.status} is available
    • placeholder {execution-time} is available (how much time current service took to fetch data)
    • placeholder {total-execution-time} / {total-took} is available (added up execution time of all previous services)
    • placeholder {total-execution-time-left} / {total-took-left} is available (formula maxTimeout - totalExecutionTime)
    • handle POST_REQUEST response event
    • print IDM (Debug) Took %sms to fetch data.
    • if the expected status code is set for the service (in configuration)
      • if it's not equal to returned service's status code
        • print IDM Returned wrong HTTP status code! Got %s, expected %s.
        • check for the custom status code disconnect message (in configuration), use BadStatusDisconnectMessage if not defined
        • check fallback ON_BAD_STATUS and break(?)
    • placeholders {http.header.str.<any>} are available (<any> will get replaced to header's name, value is converted to string/text)
    • placeholders {http.header.raw.<any>} are available (<any> will get replaced to header's name, the value can be either a string/text, number, a list)
    • parse JSON from returned response from the request
      • if an error occurred - print IDM (Debug) Body does not have valid JSON, parsing as text => %s and continue assuming response is in text instead
    • if response was parsed as JSON
      • placeholders {response.<any>} are available (<any> are JSON paths, e.g., {response.path.to[3].json})
    • else
      • placeholder {response} is available (whole response's body/text)
    • if JSON path to UUID is defined in the service's configuration
      • try to get UUID from JSON path or just use body text
      • if an error occurred doing that
        • print ISEM Failed, invalid JSON path to unique ID - %s
        • print ISDM the exception
      • if the fetched UUID is not valid (an error occurred), check fallback ON_BAD_UUID_PATH and break(?) (BadUniqueIdDisconnectMessage)
      • continue if UUID is good
      • placeholder {fetched-uuid} is available
      • placeholder {fetched-dashless-uuid} is available (UUID without dashes)
      • handle FETCHED_UUID response event
      • if any error that got overlooked occurred, check fallback ON_INVALID_UUID and break(?) (BadUniqueIdDisconnectMessage)
    • handle PRE_PROPERTIES_FETCH response event
    • check for any handler had set apply-properties and check if service is requiring properties to be set for the player (via require-properties configuration setting)
    • try fetch properties if the above statement is true
      • a list of sub-services is made
      • current service is also added (as first) as a sub-service, it doesn't send the request again, but uses already fetched data
      • for each (properties) sub-service in the list
        • if JSON path to properties is not defined, print ISEM JSON path to properties is not defined! and switch to fallback sub-service
        • check if it's a current service (with fetched data where UUID was taken from)
        • pretty much the same stuff as normal service is fetched, there are no response handlers inside
        • if sub-service is rate-limited, print ISM Service got rate-limited!, check fallback ON_SUB_SERVICE_RATE_LIMITED and break(?) (RateLimitedDisconnectMessage)
        • if sub-service is checked for minTimeout, print ISEM Not enough time-out for sending this request! reached timeout %sms, min timeout %sms, check fallback ON_SUB_SERVICE_TIMEOUT and break(?) (TimeoutDisconnectMessage)
        • print ISDM (Debug) Took %sms to fetch data.
        • placeholder {sub-execution-time} / {sub-took-time} placeholders
        • updated {total-execution-time-left} / {total-took-left} placeholders
        • updated {total-execution-time} / {total-took} placeholders
        • if sub-service's response contains an error
          • print ISEM Connection error (%s), failed to fetch properties from the service!
          • print ISDM the exception
          • switch to fallback sub-service if any, else, continue
        • try parsing JSON, if an error occurred, print ISEM Failed to parse JSON from properties service! and switch to fallback sub-service
        • try getting properties from the JSON, either check for a list of properties or for one property
        • if it's not a list and not a JSON object, print Invalid JSON
        • if an error occurred during property list building, print ISEM Failed to get profile's properties! (Invalid properties?)
        • PROPERTIES ARE RETURNED IF NO ERRORS OCCURRED
        • final checks
          • if properties were successfully retrieved, print ISM Properties successfully fetched for %s (took %s/%sms)
          • if failed, print ISEM Failed to retrieve properties (even if fallbacks were used)
    • end of fetching properties
    • handle FETCHED_PROPERTIES response event if properties were successfully retrieved
      • if require-properties was set to true and properties were NOT retrieved, check fallback ON_BAD_PROPERTIES and break(?) (BadPropertiesDisconnectMessage)
    • check if saving to the database is enabled, save if so
    • if UUID was fetched before, print ISM Unique ID successfully fetched for %s => %s (took %s/%sms)
    • mark the player acceptable to joining
    • if unexpected error occurs during all above processes, check fallback ON_UNKNOWN_ERROR and break(?) (UnknownErrorDisconnectMessage)
  • end of fetching services

  • if disconnect message was not defined by any errors (or was not set in the configuration), DefaultDisconnectMessage is used

  • if even that message is not set... oh well, a generic translatable disconnect message is sent to the player (Disconnected)

  • if a disconnect message was NOT set by any service or response handler, allow player to join

  • if fallback service was used (assuming main one failed), remember the service for time set in the configuration (fallback-service-remember-time).

Clone this wiki locally