AtriusX / Waystones

A small plugin that brings long-distance teleportation to Minecraft survival mode!
https://www.spigotmc.org/resources/waystones.93917/
11 stars 6 forks source link

Warp range inconsistency between dimensions #11

Closed luna-skye closed 3 years ago

luna-skye commented 3 years ago

Current range calculations regarding interDimension are broken, due to the worldRatio division being done on the range of the waystone, rather than the distance the player is and the relative location of the waystone to the origin of the world.

There is a temp fix with Nether -> Overworld warping, though it is still inconsistent with Overworld -> Nether warping and doesn't account for other dimensions, especially considering 1.16 allows various dimensions to be added through Data Packs.

// handler/WaystoneHandler.kt | Line 29
override fun handle(): Boolean {
    error = state.message(name)
    return when (state) {
        is Active, is InterDimension -> {
            // Calculate warpLocation based on interDimension
            // Exclusively works with Nether -> Overworld teleportation
            val warpVector = if (interDimension) {
                warpLocation.toVector().divide(Vector(8, 1, 8))
            } else warpLocation.toVector()

            // Calculate range and distance from warp
            val range = state.range
            val distance = location.toVector().distance(warpVector)

            if (distance > range) false.also {
                error = distanceError(name, distance, range)
            } else true
        }
        is Inhibited -> false
        else -> error == null
    }
}

However, the current way of detecting and returning player dimension location causes problems, in general. Due to variable worldRatios and the inability to calculate it in reverse. This is because the true/false return, in Location.sameDimension, is not enough information to specify player dimensional location. This is causing an issue with nether and end dimension waystone range, and could elicit a rework of the interdimensional function.

// utilities/Location.kt | Line 69
fun Location.sameDimension(other: Location) =
    world == other.world ?: false
AtriusX commented 3 years ago

The original idea behind including the inter-dimensional ratio initially was meant as a way to deter inter-dimensional travel. I didn't see much benefit into mapping it the same way nether portals were because they don't serve the same purpose as them.

If we mapped the world ratios in reverse for the nether to overworld travel, then you would be able to travel 8 times as far in the nether as you would the overworld. Likewise, you would be severely limited in your ability to reach warps in the nether from the overworld. I feel like the former is overpowered.

luna-skye commented 3 years ago

Well, that's not exactly what this addresses, I'd agree that kind of system would be overpowered. The issue though is that the location of the waystone is still its coordinates within the Overworld, and isn't accounting for the worldRatio.


So a couple examples of this, assuming you place a waystone and only a few blocks away build a portal, and without range shrinkage for the sake of explanation:

If you do this around coordinates 0, 63, 0 and the portal is placed very close by, say only 15-20 blocks away. We essentially have these values to consider, and this should work even with a shrinking of the waystone range.

waystoneLocation: 2, 63, 5
playerLocation: 10, 63, 9

However if you were to do this same thing around 2000, 63 2000, the portal in the Nether would open up around 250, 63, 250, but we get these values at the moment

waystoneLocation: 2000, 63, 2000
playerLocation: 250, 63, 250

Running a distance check on these will fail, saying the player is not within range, though they should be when considering the worldRatio.


While the solution in my initial issue does work while being in the Nether and warping to a waystone in the Overworld, it doesn't calculate properly vice versa, which is what I was referring to as calculating the ratio in reverse. If the waystone is around 250, 63, 250 within the Nether, it'd be expecting you to be at those same coords in the Overworld, but the correctly mapped coords would be 2000, 63, 2000, in order to calculate that we'd need to multiply the waystoneLocation by 8.

Essentially, the type of math applied is contextually based on ratios and which worlds you're going to and from, hence the suggest to rewrite the interdimensional system. It's not so much an expansion or change to the feature set, but rather addressing an oversight in regards to functional, consistent interdimensional travel.

AtriusX commented 3 years ago

I think I might have the idea for a basic solution at least. I might be able to update the WarpState object to include from and to world parameters. This could then be used to retrieve offsets from a ratio file. From there the formula: from / to could be applied to retrieve the true ratio. This could then be applied to the distance formula via multiplication.

In this case we end up with the table:

Overworld -> Nether: 1 / 8 = 8
Nether -> Overworld: 8 / 1 = 0.125
Overworld -> End: 1 / 1 = 1
End -> Nether: 1 / 8 = 0.125
Nether -> End: 8 / 1 = 8

If any luck this should also translate well over to custom dimensions as well.

A ratio: 50

Overworld -> A: 1 / 50 = 0.02
Nether -> A: 8 / 50 = 0.16
A -> Nether: 50 / 8 = 6.25

Any thoughts on this solution?

luna-skye commented 3 years ago

I could see that system working well, the question then is where are these defined? I assume we still have no way to hook into specific world ratios through Spigot/Paper, so I imagine these will be hardcoded to some extent?

AtriusX commented 3 years ago

This will be defined via the InterDimensional class type, which will take data from a JSON file. Any ratios that aren't provided in the file will be assumed as a 1:1 ratio.