Security
Koja Fishing treats the client as untrusted: everything that gives an item, money, XP or points is decided and checked on the server. This page lists what is validated, so you know what a modified client cannot do and where to hook your own anticheat.
What the server checks
| System | Validation |
|---|---|
| Fishing | The fish is rolled on the server. A catch is accepted only for the fish that was rolled, only after the bite wait has passed, and only if the equipped line can hold its weight. Gear, bait, spot and level are checked when the cast starts. |
| Spot locks | The spot's requiredLevel, requireLicense, minRodTier and unlockFlag are checked on the server when the cast starts. |
| Keep / release | Only the fish waiting for a decision can be kept or released, once. |
| Shop | Prices come from the server, including per-ped multipliers of the nearest shop ped. Requests must come from next to a shop ped, quantities are capped and merged per item, and the item's requiredLevel is enforced. The buy-back price of equipment is always below its cheapest sale price at that ped. Failed item deliveries are refunded. |
| Redeem codes | One use per player, an atomic use counter, a rate limit against guessing. |
| Quests | Progress is only added by server-side actions. Clients cannot add progress. Money and item rewards are given by the server when a quest completes. |
| Fishing guide | Must be started next to the guide ped. The starter kit is given once per character (database flag). Finishing needs at least 30 seconds after the start and gives XP once. |
| Hermits | Delivery only next to the hermit. Items are counted and removed on the server, the reward is given once per character, and removed items are given back if the reward cannot be delivered. |
| Tournaments | Points come from validated catches. Joining requires being at the tournament ped. Prizes are paid once, tracked in the database. |
| Licence exam | Answers stay on the server, the time limit is enforced, attempts and cooldowns are stored. |
| Boat rental | Level requirement, deposit and return position are checked on the server. |
| Diving caches | Distance to the cache, licence, one collection per spawn. |
| Diving centre | Upgrades, refills and contracts only next to the diving ped, paid in cash checked on the server. A crate counts only at its server-generated position, underwater, once, and not earlier than 10 seconds after accepting the contract. Air reported by the client can only go down. |
| Digging | Shovel, minimum dig time, maximum movement, cooldown. Gear modifiers come from the server. |
| Digging centre | Upgrades and contracts only next to the digging ped. A contract cache counts only after a real dig, at its server-generated position, inside the contract area, once. The tutorial shovel is given once per character. |
| Electric fishing | Owner-only actions, distance checks for placing, connecting and grabbing, one battery per player, one grab attempt per fish. |
| Party | Invites only to nearby players, leader-only actions, shared sale money split on the server, goal progress only from server-side catches, sales, dives and digs. |
| Poaching | Evidence is recorded on the server from validated catches. Only players with a job from PoliceJobs (grade, duty) can inspect and fine, within InspectDistance. Offences need matching evidence, the total is capped by MaxFine, and the same angler has a cooldown. |
| Admin panel | Every request checks the ACE or group. Values are validated by type and range before they are saved, writes are rate-limited, and every change is logged to the server console. |
| All endpoints | Per-player rate limits on every callback a client can spam. |
Admin commands are console-only or ACE-protected — see Commands.
Reacting to cheat attempts
Every rejected request that can only come from a modified client calls Config.Security.OnSuspicious and prints a [security] line in the server console.
shared/config.main.lua
Config.Security = {
ValidatePedDistance = true,
PedInteractDistance = 10.0,
OnSuspicious = function(source, reason)
-- exports['your-anticheat']:flag(source, 'koja-fishing: ' .. reason)
end,
}reason is a short description such as fishing/catch: too fast.
Before you go live
Config.Debug = false— debug enables free-battery and test commands.Config.Digging.EnableTestCommand = false.- Check that every
sellPriceinconfig.items.luais belowprice - maxPriceChange. - Grant
command.fishingquest_testonly to admins. - Grant
koja-fishing.adminonly to trusted staff, and checkConfig.Admin.Groups— the panel changes prices, rewards and players' data.