Files
tactical-shooter/tests/netem_profiles.sh
T
shawn e7299b17e9 Phase 7: netfox + godot-jolt stack upgrade
Stack installed:
- netfox v1.35.3 (core + extras + noray + internals)
- godot-jolt v0.16.0-stable

Architecture:
- Server: ENet transport (works headless, no netfox deps)
- Client/Editor: netfox rollback (RollbackSynchronizer, TickInterpolator)

New/modified:
- docs/migration-netfox-plan.md — migration architecture
- scripts/network/network_manager.gd — netfox-aware ENet fallback
- scripts/network/player.gd — clean base player
- client/characters/player_netfox.gd — rollback player w/ WeaponManager
- client/characters/input/player_net_input.gd — BaseNetInput subclass
- client/characters/character/fps_character_controller.gd — netfox input feed
- client/weapons/ — weapon data, registry, TacticalWeaponHitscan, WeaponManager
- client/scripts/round_replicator.gd — client-side round state bridge
- server/scripts/round_manager.gd — improved state machine
- server/scripts/plugin_api/plugin_manager.gd — refined plugin system
- config: enemy_tag, ally_tag for meatball targeting

Removed: old C++ SimulationServer GDExtension (replaced by netfox rollback)
2026-07-02 17:39:22 -04:00

143 lines
6.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# ═══════════════════════════════════════════════════════════════════════════
# tc/netem Network Profile Manager for Tactical Shooter
#
# Applies tc qdisc netem rules to simulate real-world network conditions
# on the game server's port. Requires root (sudo).
#
# Usage:
# sudo ./netem_profiles.sh apply lan # 0% loss, near-zero latency
# sudo ./netem_profiles.sh apply dsl # 0.5% loss, 20ms ±5ms
# sudo ./netem_profiles.sh apply cellular # 2% loss, 60ms ±20ms
# sudo ./netem_profiles.sh apply satellite # 1% loss, 600ms ±50ms
# sudo ./netem_profiles.sh apply congested # 5% loss, 100ms ±40ms, reorder
# sudo ./netem_profiles.sh apply warzone # 10% loss, 200ms ±60ms, burst
# sudo ./netem_profiles.sh apply extreme # 25% loss, 500ms ±100ms
# sudo ./netem_profiles.sh apply edge # 50% loss, 1000ms ±200ms (catastrophic)
# sudo ./netem_profiles.sh off # Remove all netem rules
# sudo ./netem_profiles.sh status # Show current rules
#
# Requires: iproute2 (tc), root, IFACE (default: eth0), PORT (default: 7777)
# ═══════════════════════════════════════════════════════════════════════════
set -euo pipefail
# ─── Config ────────────────────────────────────────────────────────────────
IFACE="${NETEM_IFACE:-eth0}"
PORT="${NETEM_PORT:-7777}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# ─── Color ─────────────────────────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'
# ─── Help / Usage ──────────────────────────────────────────────────────────
usage() {
echo "Usage: $0 {apply <profile>|off|status}"
echo ""
echo "Profiles:"
echo " lan 0% loss, 1ms latency"
echo " dsl 0.5% loss, 20ms ± 5ms jitter"
echo " cellular 2% loss, 60ms ±20ms jitter"
echo " satellite 1% loss, 600ms ±50ms jitter"
echo " congested 5% loss, 100ms ±40ms jitter, reorder 5%"
echo " warzone 10% loss, 200ms ±60ms jitter, 1% dupe, reorder 2%"
echo " extreme 25% loss, 500ms ±100ms jitter, reorder 10%"
echo " edge 50% loss, 1000ms ±200ms jitter (catastrophic)"
exit 1
}
# ─── Profile definitions ───────────────────────────────────────────────────
declare -A PROFILES
# Format: loss lat jitter reorder reorder_corr dup dup_corr
# loss: percentage (0-100)
# lat: one-way latency in ms
# jitter: ±ms
# reorder: percentage of packets reordered
# reorder_corr: correlation factor for reorder (0-100)
# dup: duplicate percentage
# dup_corr: correlation factor for duplicate
PROFILES["lan"]="loss 0% delay 1ms 0ms"
PROFILES["dsl"]="loss 0.5% delay 20ms 5ms"
PROFILES["cellular"]="loss 2% delay 60ms 20ms"
PROFILES["satellite"]="loss 1% delay 600ms 50ms"
PROFILES["congested"]="loss 5% delay 100ms 40ms reorder 5% 50%"
PROFILES["warzone"]="loss 10% delay 200ms 60ms 25% duplicate 1% 25%"
PROFILES["extreme"]="loss 25% delay 500ms 100ms reorder 10% 50%"
PROFILES["edge"]="loss 50% delay 1000ms 200ms"
# ─── Apply netem to a specific port via iptables + tc mirror ───────────────
apply_netem() {
local profile_name="$1"
local profile_params="${PROFILES[$profile_name]:-}"
if [ -z "$profile_params" ]; then
echo -e "${RED}Unknown profile: $profile_name${NC}"
usage
fi
echo -e "${CYAN}Applying netem profile: ${YELLOW}$profile_name${NC}"
echo -e " Interface: $IFACE Port: $PORT"
echo -e " Parameters: $profile_params"
echo ""
# Remove existing qdisc on the root
sudo tc qdisc del dev "$IFACE" root 2>/dev/null || true
# Apply netem to ALL traffic on the interface (targeted filtering is complex)
# To target specific ports, you'd use iptables + ifb mirroring, but for
# dev/testing, applying to the full interface is sufficient when run on
# a dedicated test machine.
sudo tc qdisc add dev "$IFACE" root netem $profile_params
echo -e "${GREEN}✓ Profile '$profile_name' applied${NC}"
show_status
}
# ─── Remove all netem rules ────────────────────────────────────────────────
remove_netem() {
echo -e "${YELLOW}Removing all netem rules on $IFACE...${NC}"
sudo tc qdisc del dev "$IFACE" root 2>/dev/null || true
echo -e "${GREEN}✓ Netem rules removed (interface returned to normal)${NC}"
}
# ─── Show current status ───────────────────────────────────────────────────
show_status() {
echo ""
echo -e "${CYAN}Current qdisc on $IFACE:${NC}"
sudo tc qdisc show dev "$IFACE" 2>/dev/null || echo " (no qdisc configured — interface is clean)"
echo ""
echo -e "${CYAN}Filter by port $PORT (iptables):${NC}"
sudo iptables -L netem -n 2>/dev/null || echo " (no netem iptables chain)"
}
# ─── Main ──────────────────────────────────────────────────────────────────
if [ $# -lt 1 ]; then
usage
fi
case "$1" in
apply)
if [ $# -lt 2 ]; then
echo -e "${RED}Error: 'apply' requires a profile name${NC}"
echo ""
usage
fi
apply_netem "$2"
;;
off|remove|clear)
remove_netem
;;
status)
show_status
;;
*)
usage
;;
esac