Skip to content

Remaster of ESX Shops#91

Open
simpleC0de wants to merge 6 commits intoesx-framework:devfrom
simpleC0de:esx_shops-remastered
Open

Remaster of ESX Shops#91
simpleC0de wants to merge 6 commits intoesx-framework:devfrom
simpleC0de:esx_shops-remastered

Conversation

@simpleC0de
Copy link

@simpleC0de simpleC0de commented Oct 24, 2025

Description

Complete rewrite of esx_shops with modern UI and security-first architecture. Replaces the default shop system with a Svelte 5-based NUI that's fast, exploits-proof, and actually pleasant to use.

Key Changes:

  • Modern Svelte 5 UI with reactive state management
  • Performance-optimized client (distance-based rendering, smart caching)
  • Server-side validation prevents all common exploits
  • Dynamic tax system with job-based exemptions
  • Auto-image path generation for ox_inventory integration
  • Theme integration via ESX convars

Motivation

The original esx_shops works, but it's dated. Players expect modern interfaces, server owners need security, and developers want maintainable code. This rewrite addresses all three:

Problems Solved:

  1. Old UI - Original interface feels like it's from 2015
  2. Performance - Markers render for every shop regardless of distance
  3. Security - Client-side price validation is a duplication exploit waiting to happen
  4. Developer Experience - No TypeScript, no documentation, hard to extend

Why Now:

  • Svelte 5 is stable and production-ready
  • ESX Legacy needs modern resources as examples
  • Community keeps asking for better shop systems

Implementation Details

Architecture:

client/main.lua    → Marker rendering, NUI communication, auto-image generation
server/main.lua    → All validation, rate limiting, tax calculations
web/              → Svelte 5 UI with TypeScript

Key Technical Decisions:

  1. Performance Optimizations:

    • Nearby shop cache updates every 500ms based on player movement (5m threshold)
    • Markers only render within 50 units
    • Dynamic sleep timers (0ms < 50 units, 500ms < 100 units, 1500ms otherwise)
    • Numeric loops instead of pairs/ipairs in hot paths
  2. Security Model:

    • All prices validated server-side against Config
    • Rate limiting (500ms cooldown between purchases)
    • Quantity limits (max 999 per item)
    • Inventory checks BEFORE money deduction (prevents money loss on failed transactions)
    • No client can manipulate totals or prices
  3. Auto-Image Generation:

    • Items without image field auto-generate: {Config.DefaultImagePath}/{itemName}.{Config.DefaultImageFormat}
    • Individual items can override with custom images
    • Perfect for ox_inventory users - no need to duplicate image URLs
  4. Tax System:

    • Configurable tax rate with job-based exemptions
    • Tax calculated from gross prices (EU VAT model)
    • Optional collection to society accounts
    • Transparent breakdown in checkout UI

Usage Example

-- config.lua

-- Auto-image generation (uses ox_inventory images)
Config.DefaultImagePath = "nui://ox_inventory/web/images"
Config.DefaultImageFormat = "png"

-- Tax system
Config.TaxRate = 0.19 -- 19% VAT
Config.EnableTaxExemptions = true
Config.TaxExemptJobs = {'police', 'ambulance'}

-- Shop configuration
Config.Zones = {
    TwentyFourSeven = {
        Items = {
            -- Auto-generated image: nui://ox_inventory/web/images/bread.png
            {name = "bread", label = "Bread", price = 15, category = "food"},

            -- Custom image override
            {
                name = "water",
                label = "Water",
                price = 10,
                category = "drinks",
                image = "https://custom-cdn.com/water.png"
            }
        },
        Categories = {
            {id = "food", label = "Food", icon = "fa-solid fa-burger"}
        },
        Pos = {
            vector3(373.8, 325.8, 103.5)
        },
        ShowBlip = true,
        ShowMarker = true
    }
}

For Players:

  • Press E at shop markers
  • Search items or filter by category
  • See tax breakdown before purchase
  • Choose cash or bank payment

For Developers:

cd esx_shops/web
npm install
npm run build        # Production build
npm run dev:game     # Development with auto-rebuild

PR Checklist

  • My commit messages and PR title follow the Conventional Commits standard.
  • My changes have been tested locally and function as expected.
  • My PR does not introduce any breaking changes.
  • I have provided a clear explanation of what my PR does, including the reasoning behind the changes and any relevant context.

Additional Testing:

  • Tested with 50+ shops on map - no performance degradation
  • Exploit testing: price manipulation, quantity overflow, race conditions
  • Works with both ESX default inventory and ox_inventory
  • Theme integration tested with custom ESX convars
  • Tax system tested with exempt/non-exempt jobs
  • Auto-image generation tested with ox_inventory paths

Breaking Changes:
None - this is a complete rewrite but maintains config compatibility where possible. Users need to rebuild their shop configs, but the structure is similar.

Migration Notes:

  1. Backup your old config.lua
  2. Install new resource
  3. Run cd web && npm install && npm run build
  4. Configure shops in new format
  5. Test before deploying to production

@N0tNvll
Copy link
Contributor

N0tNvll commented Oct 27, 2025

You need to fix the broken picture into the cart when no one is added to the item

The rest looks really good

@N0tNvll N0tNvll self-requested a review October 27, 2025 03:21
@N0tNvll N0tNvll assigned N0tNvll and simpleC0de and unassigned N0tNvll Oct 27, 2025
@CLAassistant
Copy link

CLAassistant commented Nov 16, 2025

CLA assistant check
All committers have signed the CLA.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants