promotional bannermobile promotional banner

Wave Defense

A versatile PvE and PvP engine featuring wave defense, customizable shops, and three competitive game modes for Minecraft
Back to Files

wavedefense-0.6.0.jar

File namewavedefense-0.6.0.jar
Uploader
Rayman_GCRayman_GC
Uploaded
Aug 8, 2026
Downloads
12
Size
1.3 MB
Mod Loaders
Forge
File ID
8605208
Type
R
Release
Supported game versions
  • 1.20.1

Curse Maven Snippet

Forge

implementation fg.deobf("curse.maven:wave-defense-1492909:8605208")

Learn more about Curse Maven

What's new

Changelog

[0.6.0] - 2026-08-08 — a shop that prices itself

Stocking a shop was the job that did not scale. A modern gun pack ships hundreds of weapons whose strength varies tenfold within a single class, and the mod asked an admin to price every one of them by hand, one screen at a time, with a bulk tool that filed the whole batch under one category. The result was an evening's work that produced a mess.

The mod now reads what an item actually does — a gunpack ships its own ballistics, and armour carries its protection in vanilla attributes — ranks it against its own kind, and prices it from that. An admin tunes about a dozen numbers instead of several hundred.

Around that sits the machinery to use it: an item browser with prices in each row, four presets that describe a shop as roles rather than goods, and duplicate control so the same offer cannot land twice.

Upgrading: the network protocol moves to version 13, so client and server must be updated together. Compile targets are unchanged — Forge 47.2.0, Minecraft 1.20.1, Java 17, official mappings.

Added — prices derived from what an item does

  • /wda shop autoprice <location> [sellRatio] reads a shop and prices it. Weapons are ranked against their own class rather than an absolute scale, which is what makes it work on a collection nobody has seen: the best rifle here sits at the top of the rifle band whatever its numbers are. Measured against a real 268-gun, six-pack arsenal, rifles spread 1485 to 4995 and the most expensive was the one with 25 damage at 923 rpm and full armour bypass — found without being told about it.
  • Armour needs no compatibility layer at all: defence and toughness are vanilla attributes that any modded armour inherits.
  • Both buy and sell prices, from one resale fraction.
  • Anything unmeasurable is reported as such rather than guessed at, and left alone by default.

Added — item browser and shop presets

  • Browser (editor → Огляд): everything installed, searchable, filterable by mod, with buy and sell boxes in each row and prices already filled in. "Add all" applies to the filtered view, each entry with its own category — which is what the old bulk add should have been.
  • Presets (editor → Пресет): Classic buy menu, Deathmatch, Wave defence, Basics only. A preset is a list of roles, not items — "three pistols, cheap to mid" — so it fills from whatever is installed and skips what is not. A preset naming specific gun ids would have quietly made this a mod that requires a 300 MB gun collection.
  • Presets replace the shop, and say how many entries that will delete before doing it.
  • Attachments are priced too — scopes, muzzles, grips, stocks, lasers, extended magazines. Type carries most of the value, and weight counts against it, because in Tacz a heavier attachment slows the weapon.
  • Economy travels with the preset. A buy menu without money around it is a shop nobody can afford.

Fixed — the statistics and rating did not work

Four separate defects, which together made the whole progression system look inert.

  • The lifetime profile was never sent to the client. It was written on every kill, wave and match end, and saved to disk — but no packet carried it and no screen mentioned the class, so the level a player was accumulating existed only in a file they could not read. It now syncs on join and after anything that changes it, and appears at the top of the stats screen.
  • Every run on a non-Normal difficulty was invisible. Records are filed under the mode key plus the difficulty's suffix (PvE_hardPvE_nightmare), and the leaderboard only ever asked for the bare key. There is now a difficulty selector.
  • Endless mode had no tab. Its records were written faithfully to PvE_ENDLESS and had nowhere to be shown.
  • The two PvE boards ranked on different quantities. A cleared run recorded (points, waves) while an endless run recorded (waves, points) — the board sorts on the first and labels the second, so one of the two had its columns swapped under the headings. Both now rank on waves, which is what the run was about.

Fixed — point shops received nothing from any mass operation

Every bulk path assumed the global shop and hardcoded an empty point name. On a location in point mode that list is not the shop players buy from, so a bulk add filled something nobody would ever see and left the real shop empty — it looked stocked in the editor and sold nothing in game. The browser, the presets and the upload queue now carry an explicit target, and offer a picker for it.

Fixed — duplicate entries

The same offer could be added any number of times. It is now refused with a reason on a single add, skipped silently on a bulk upload (re-running one over an existing shop is ordinary, not an error), cleaned on import, and /wda shop dedupe <location> clears out a shop that already accumulated them. Identity is what a player can tell apart: price is not part of it, stack size and availability trigger are, and NBT is read only in the part that names the item — so an arsenal does not collapse into one entry.

Fixed — the category row ran off the screen

The shop item editor laid its categories out as one row of fixed-width buttons. That fitted the four that existed when it was written; with the gun buckets there are twelve, so the row ran some 740 px from its left edge and the fixed width clipped the longer labels. Both faults were the same mistake — a layout that assumed its content. It now sizes to the text and wraps.

Fixed — two arenas could reach into each other

PvpRoundManager keeps three collections of per-round bookkeeping — pending respawns, kill streaks, death-penalty de-duplication — indexed by player rather than by location. Emptying them with clear() is therefore a server-wide operation wearing the clothes of a local one, and starting or ending a match did exactly that.

Everyone playing in a different arena had their state wiped: the pending respawn was forgotten, which left them spectating with no way back; the kill streak reset; and the next death could be charged twice. One defect, three symptoms — including the "can't respawn" report. Every reset now names the players it applies to, and LocationIsolationTest fails if a blanket clear reappears outside load().

Fixed — death and respawn in PvP

Rewritten to one rule: while the round is still running a dead player watches; once it is not, they come back. It had been six branches keyed on a mix of phase, a "was this a PvP death" set and whatever game mode the player happened to be in, and they disagreed about who clears the waiting effects — which is why players returned holding an hour of blindness and slowness that nothing took off. Effects are now cleared before every transition rather than once at round start over a list built before the player respawned. Deathmatch and Battle Royale remain exceptions because those modes genuinely differ.

Fixed — the PvE wave loop ran on PvP locations

tickSession did not check the mode, so joining a PvP match announced "Wave 2 has begun" and every wave it silently completed paid out that wave's point reward on top of the PvP economy. That is where the duplicated points came from. refreshHudState had drawn this line for a long time; the tick itself never did.

Fixed — typing in a shop search destroyed the search box

rebuildWidgets() runs init(), which builds a fresh EditBox — so rebuilding on each keystroke threw away the field being typed into, caret and all. Both shop searches did this. They now recompute the filter on the keystroke and rebuild the rows on the next frame, restoring text and focus. WidgetRebuildTest forbids the pattern outright.

Added — a quantity column in the item browser

Entries could only ever be added one at a time, which is wrong for exactly the things bought in bulk: ammunition, arrows, food. Suggested prices follow the quantity, and a price already typed by hand is left alone.

Changed — refactoring, to stop the same bugs returning

  • Points have one gateway. All eighteen direct writes now go through PointsService, which resolves the live location (a caller holding a replaced copy credited an object nobody reads — the defect behind a balance of 973 that would not buy a 900-point item), floors the result at zero, syncs the client, and logs every change with its reason. A wrong balance can now be traced instead of hunted in-game. Guarded by PointsGatewayTest.
  • Screens no longer read a stale location — except where they must not be refreshed. Fifteen screens re-adopt the cached object in init(). Five deliberately do not: they hold the admin's unsaved work in that same object, and refreshing would replace half-finished waves or a loot table with the server's copy mid-edit. Both halves of the rule are pinned by StaleLocationTest, because either one alone is a bug.
  • Considered and rejected: narrowing the per-tick loops to active sessions only. Three of them must see locations without a session by design — the activation zone starts a location that has none, and a portal stands for one — so the change would have broken working features. The cost it would have saved is a few thousand boolean checks a second, which is nothing.

Internal

  • Tacz remains entirely optional and is reached only by reflection: no hard imports, every entry point guarded, no hardcoded gun ids or pack names. Verified, not assumed.
  • Lang keys: 1579 per locale across 8 locales, parity checked.
  • Test suite: 117 tests, all passing.

This mod has no related projects