Configuration

It all lives in one file, config/oas/vortexdread.json, on the server side. Forty-two options in five groups, written whole on first run and rewritten on every save, so that a version adding an option puts it in the file you are already editing instead of leaving you to guess it exists. There is no in-game screen: a file you can read again later beats a panel you walked through once.

What happens when a value is wrong

Every numeric option carries a range. A value outside it is pulled back into the range rather than refused: someone writing a thousand into a tick budget wants a bigger budget, and stopping the server over it helps nobody. A key this version does not know is ignored with a log line naming it. A file that will not parse at all is moved aside as vortexdread.json.broken and a fresh one takes its place, because someone spent time in there and quietly overwriting it is the one outcome they cannot recover from.

The command

/vortex wants permission level 2, the same gate vanilla puts on /weather, since it is the same kind of decision. /vortex spawn drops a funnel where you stand, with a rating and a pair of coordinates as optional arguments. /vortex list reports the live ones within 8192 blocks, with their stage, their distance, their core and how much ground they are carrying. /vortex clear removes them, /vortex storms off stops the sky making more, and /vortex compute names the device doing the arithmetic and counts what went through each path.

The forty-two options

The values below are those of a fresh file. The right-hand column says what changes when you move them, not what the name means.

Group storm, the sky and its decision
OptionDefaultWhat it moves
naturalTornadoestrueFalse and the sky never makes one, leaving only the command.
tornadoChancePerMinute0.18Chance, per minute of thunder, that a supercell organises. 0 to 1.
cooldownTicks9600Quiet enforced after one dissipates, whatever the odds say. Eight minutes.
maxConcurrent1Funnels alive at once in one dimension. Up to 16.
ratingBias0.0Shifts the random rating, in EF steps. Negative keeps the sky to weak ones.
warningRadius640Distance at which the roar starts and the sky begins to turn.
rebuildStormstrueFalse and vanilla weather goes back to looking the way it always did.
cloudFlashesPerMinute34Visual-only bolts fired into the cloud, which is what lights it from inside.
funnelFlashesPerMinute9Bolts fired inside the funnel itself once it is on the ground.
extraLightningtrueFalse leaves only the strikes vanilla would have made.
Group tornado, the shape and the life of one funnel
OptionDefaultWhat it moves
coreRadiusAtEf06.0Core radius of the weakest one. Everything else scales off it.
radiusGrowthExponent1.5How fast the core widens as the wind climbs.
lifespanMinTicks2400Shortest life, two minutes. Most of them last no longer.
lifespanMaxTicks14400Longest life, twelve minutes, the rare long-tracked one.
travelSpeed8.0How fast the system travels over the ground, in blocks per second.
trackWander1.6Heading drift allowed, in degrees per second. At zero the track is a straight line.
turbulence0.22Amplitude of the noise riding on the analytic field, as a fraction of the local wind.
cloudBaseAltitude183.0Height of the cloud deck. That is where Photon puts its cumulus at stock settings.
formingFraction0.12Fraction of the life spent reaching down before touching the ground.
ropeOutFraction0.18Fraction of the life spent drawing out into a rope and dying.
Group damage, what breaks and what flies
OptionDefaultWhat it moves
breakBlockstrueFalse and nothing comes out of the ground, leaving the wind and whatever is already up.
blockBudgetPerTick96Blocks examined per tick across every live tornado. The whole cost of destruction sits here.
resistanceScale1.0Multiplies the resistance a block has to survive. Under one, walls stay up.
dropItemsfalseTrue and a taken block leaves its item. By default what the wind takes is gone.
maxDebris220Heavy debris carried at once by one tornado, each one a real entity.
debrisSettlesfalseTrue and a piece puts its block back down where it lands, rebuilding the track behind it.
damageEntitiestrueFalse and neither the wind nor the debris hurts anything.
damageScale1.0Multiplies every point of damage, wind and impact alike.
liftPlayerstrueFalse keeps players on the ground. Mobs and items still fly.
liftThreshold18.0Wind speed under which nothing is lifted at all, in blocks per second.
Group compute, where the arithmetic runs
OptionDefaultWhat it moves
useGputrueA kill switch. With no device present the processor path runs and nothing has to be touched.
gpuDeviceIndex-1Index into the flat list of OpenCL devices. Negative picks on its own.
gpuWorkgroupSize0Work group size. Zero lets the driver decide, which is the right answer.
advectionThreads0Threads in the processor pool. Zero means cores minus two.
advectionBatch4096Debris handed to one dispatch. Small hides latency, large amortises the upload.
Group look, client side only
OptionDefaultWhat it moves
funnelSteps40Steps through the volume. Under sixteen the wall goes banded.
funnelLightSteps6Steps toward the light for the shadow inside. Zero flattens the funnel entirely.
funnelDetail1.8Size of the smallest visible wisp, in blocks. Finer wants more steps.
funnelRenderDistance1024.0Distance past which the storm is only sky and sound.
screenShaketrueFalse and the screen stops moving when the wind does.
postEffecttrueFalse and the darkening, the streaks and the flash all go.
skyGreen0.55How much of the green a tornado sky takes reaches the world colour, 0 to 1.

Five groups, not five files. A group's name in the JSON comes from the class holding the option, hence storm, tornado, damage, compute and look. An option added to the code lands in its group with no wiring anywhere else, and an option moved from one group to another is still read: the key looked up is the option's name, never the full path.

No dead options. The development tooling is compiled in a separate source set and is not in the shipped jar. What appears in the file is what actually drives something, with nothing left in place in case it comes back.