e7299b17e9
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)
143 lines
6.3 KiB
Bash
Executable File
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
|