/**
* Odamex's server-to-client protocol.
*/

syntax="proto3";

import "common.proto";

package odaproto.svc;

// svc_noop
message Noop
{
}

// svc_disconnect
message Disconnect
{
	string message = 1;
}

// svc_playerinfo
message PlayerInfo
{
	Player player = 1;
}

// svc_moveplayer
message MovePlayer
{
	int32 tic = 1;
	int32 frame = 2;
	Player player = 3;
	Actor actor = 4;
}

// svc_updatelocalplayer
message UpdateLocalPlayer
{
	int32 tic = 1;
	Actor actor = 2;
}

// svc_levellocals
message LevelLocals
{
	uint32 flags = 1;
	int32 time = 2;
	int32 total_secrets = 3;
	int32 total_items = 4;
	int32 total_monsters = 5;
	int32 found_secrets = 6;
	int32 found_items = 7;
	int32 killed_monsters = 8;
	int32 respawned_monsters = 9;
}

// svc_pingrequest
message PingRequest
{
	uint64 ms_time = 1;
}

// svc_updateping
message UpdatePing
{
	int32 pid = 1;
	int32 ping = 2;
}

// svc_spawnmobj, svc_mobjinfo, svc_corpse
message SpawnMobj
{
	Actor baseline = 1;
	uint32 baseline_flags = 2;
	Actor current = 3;
	uint32 spawn_flags = 4;
	uint32 target_netid = 5;
	repeated int32 args = 6;
}

// svc_disconnectclient
message DisconnectClient
{
	int32 pid = 1;
}

// svc_loadmap
message LoadMap
{
	message Resource
	{
		string name = 1;
		string hash = 2;
	}

	repeated Resource wadnames = 1;
	repeated Resource patchnames = 2;
	string mapname = 3;
	int32 time = 4;
}

// svc_consoleplayer
message ConsolePlayer
{
	int32 pid = 1;
	string digest = 2;
}

// svc_explodemissile
message ExplodeMissile
{
	uint32 netid = 1;
}

// svc_removemobj
message RemoveMobj
{
	uint32 netid = 1;
}

// svc_userinfo
message UserInfo
{
	int32 pid = 1;
	string netname = 2;
	int32 team = 3;
	int32 gender = 4;
	Color color = 5;
	sint64 join_time = 6;
}

// svc_updatemobj
message UpdateMobj
{
	uint32 flags = 1;
	Actor actor = 2;
}

// svc_spawnplayer
message SpawnPlayer
{
	int32 pid = 1;
	Actor actor = 2;
	uint32 cards = 3;
}

// svc_damageplayer
message DamagePlayer
{
	uint32 netid = 1;
	int32 health_damage = 2;
	int32 armor_damage = 3;
	int32 inflictorid = 4;
	Player player = 5;
}

// svc_killmobj
message KillMobj
{
	uint32 source_netid = 1;
	Actor target = 2;
	uint32 inflictor_netid = 3;
	int32 health = 4;
	int32 mod = 5;
	bool joinkill = 6;
	sint32 lives = 7; // Default is -1.
}

// svc_raisemobj
message RaiseMobj
{
	uint32 source_netid = 1;
	Actor corpse = 2;
}

// svc_fireweapon
message FireWeapon
{
	int32 readyweapon = 1;
	int32 servertic = 2;
}

// svc_updatesector
message UpdateSector
{
	int32 sectornum = 1;
	Sector sector = 2;
}

// svc_print
message Print
{
	int32 level = 1;
	string message = 2;
}

// svc_playermembers
message PlayerMembers
{
	int32 pid = 1;
	uint32 flags = 2;
	bool spectator = 3;
	bool ready = 4;
	sint32 lives = 5;
	int32 roundwins = 6;
	int32 points = 7;
	int32 fragcount = 8;
	int32 deathcount = 9;
	int32 monsterdmgcount = 10;
	int32 killcount = 11;

	// [AM] Is there any reason we would ever care about itemcount?
	int32 secretcount = 12;
	int32 totalpoints = 13;
	int32 totaldeaths = 14;

	// Ch0wW: Include Cheats...
	uint32 cheats = 15;
}

// svc_teammembers
message TeamMembers
{
	int32 team = 1;
	int32 points = 2;
	int32 roundwins = 3;
}

// svc_activateline
message ActivateLine
{
	int32 linenum = 1;
	uint32 activator_netid = 2;
	int32 side = 3;
	int32 activation_type = 4;
	bool bossaction = 5;
}

// svc_movingsector
message MovingSector
{
	message Snapshot
	{
		int32 ceil_type = 1;
		int32 floor_type = 2;
		int32 ceil_tag = 3;
		int32 floor_tag = 4;
		sint32 ceil_line = 5; // Default is -1
		sint32 floor_line = 6; // Default is -1
		sfixed32 ceil_height = 7;
		sfixed32 floor_height = 8;
		int32 ceil_speed = 9; // Speed might be fixed_t, but it's also centered on 0.
		int32 floor_speed = 10; // Speed might be fixed_t, but it's also centered on 0.
		sfixed32 ceil_dest = 11;
		sfixed32 floor_dest = 12;
		sint32 ceil_dir = 13; // Direction is 1 or -1.
		sint32 floor_dir = 14; // Direction is 1 or -1.
		sint32 ceil_old_dir = 15; // Direction is 1 or -1.
		sint32 floor_old_dir = 16; // Direction is 1 or -1.
		int32 ceil_tex = 17;
		int32 floor_tex = 18;
		int32 ceil_new_special = 19;
		int32 floor_new_special = 20;
		sfixed32 ceil_low = 21;
		sfixed32 ceil_high = 22;
		sfixed32 floor_low = 23;
		sfixed32 floor_high = 24;
		bool ceil_crush = 25;
		bool floor_crush = 26;
		bool silent = 27;
		int32 ceil_wait = 28;
		int32 floor_wait = 29;
		int32 ceil_counter = 30;
		int32 floor_counter = 31;
		int32 reset_counter = 32;
		int32 ceil_status = 33;
		int32 floor_status = 34;
		int32 floor_old_status = 35;
		int32 crusher_speed_1 = 36; // Speed might be fixed_t, but it's also centered on 0.
		int32 crusher_speed_2 = 37; // Speed might be fixed_t, but it's also centered on 0.
		int32 step_time = 38;
		int32 per_step_time = 39;
		int32 pause_time = 40;
		sfixed32 orig_height = 41; // Type is int, but is actually a fixed_t.
		int32 delay = 42;
		sfixed32 floor_lip = 43;
		sfixed32 floor_offset = 44;
		int32 ceil_change = 45;
		int32 floor_change = 46;
	}

	int32 sector = 1;
	sfixed32 ceiling_height = 2;
	sfixed32 floor_height = 3;
	uint32 movers = 4;
	Snapshot ceiling_mover = 5;
	Snapshot floor_mover = 6;
}

// svc_playsound
message PlaySound
{
	oneof source {
		uint32 netid = 1;
		Vec2 pos = 2;
	};

	int32 channel = 3;
	int32 sfxid = 4;
	float volume = 5;
	int32 attenuation = 6;
}

// svc_reconnect
message Reconnect
{
}

// svc_exitlevel
message ExitLevel
{
}

// svc_touchspecial
message TouchSpecial
{
	uint32 netid = 1;
}

// svc_missedpacket
message MissedPacket
{
	int32 seq = 1;
	bytes data = 2;
}

// svc_forceteam
message ForceTeam
{
	int32 team = 1;
}

// svc_switch
message Switch
{
	int32 linenum = 1;
	bool switch_active = 2;
	uint32 special = 3;
	uint32 state = 4;
	int32 button_texture = 5;
	uint32 timer = 6;
}

// svc_say
message Say
{
	bool visibility = 1;
	int32 pid = 2;
	string message = 3;
}

// svc_ctfrefresh
message CTFRefresh
{
	message TeamInfo
	{
		int32 points = 1;
		int32 flag_state = 2;
		int32 flag_flagger = 3;
	}

	bool full = 1;
	repeated TeamInfo team_info = 2;
}

// svc_ctfevent
message CTFEvent
{
	int32 event = 1;
	int32 target_team = 2;
	int32 player_team = 3;
	int32 player_id = 4;
	int32 player_points = 5;
	int32 player_totalpoints = 6;
}

// svc_secretevent
message SecretEvent
{
	int32 pid = 1;
	int32 sectornum = 2;
	Sector sector = 3;
}

// svc_serversettings
message ServerSettings
{
	string key = 1;
	string value = 2;
}

// svc_connectclient
message ConnectClient
{
	int32 pid = 1;
}

// svc_midprint
message MidPrint
{
	string message = 1;
	int32 time = 2;
}

// svc_svgametic
message ServerGametic
{
	int32 tic = 1;
}

// svc_inttimeleft
message IntTimeLeft
{
	int32 timeleft = 1;
}

// svc_fullupdatedone
message FullUpdateDone
{
}

// svc_railtrail
message RailTrail
{
	Vec3 start = 1;
	Vec3 end = 2;
}

// svc_playerstate
message PlayerState
{
	Player player = 1;
}

// svc_levelstate
message LevelState
{
	int32 state = 1;
	int32 countdown_done_time = 2;
	int32 ingame_start_time = 3;
	int32 round_number = 4;
	int32 last_wininfo_type = 5;
	int32 last_wininfo_id = 6;
}

// svc_resetmap
message ResetMap
{
}

// svc_playerqueuepos
message PlayerQueuePos
{
	int32 pid = 1;
	int32 queuepos = 2;
}

// svc_fullupdatestart
message FullUpdateStart
{
}

// svc_lineupdate
message LineUpdate
{
	int32 linenum = 1;
	int32 flags = 2;
	uint32 lucency = 3;
}

// svc_sectorproperties
message SectorProperties
{
	int32 sectornum = 1;
	uint32 changes = 2; // bitfield
	Sector sector = 3;
}

// svc_linesideupdate
message LineSideUpdate
{
	int32 linenum = 1;
	int32 side = 2;
	uint32 changes = 3; // bitfield
	int32 toptexture = 4;
	int32 midtexture = 5;
	int32 bottomtexture = 6;
}

// svc_mobjstate
message MobjState
{
	int32 netid = 1;
	int32 mostate = 2;
}

// svc_damagemobj
message DamageMobj
{
	int32 netid = 1;
	int32 health = 2;
	int32 pain = 3;
}

// svc_executelinespecial
message ExecuteLineSpecial
{
	int32 special = 1;
	sint32 linenum = 2; // Default is -1.
	uint32 activator_netid = 3;
	int32 arg0 = 4;
	int32 arg1 = 5;
	int32 arg2 = 6;
	int32 arg3 = 7;
	int32 arg4 = 8;
}

// svc_executeacsspecial
message ExecuteACSSpecial
{
	int32 special = 1;
	int32 activator_netid = 2;
	string print = 3;
	repeated sint32 args = 4;
}

// svc_thinkerupdate
message ThinkerUpdate
{
	message Scroller
	{
		int32 type = 1;
		sfixed32 scroll_x = 2;
		sfixed32 scroll_y = 3;
		int32 affectee = 4;
		sint32 control = 5; // Default is -1.
		uint32 accel = 6;
	}

	message FireFlicker
	{
		int32 sector = 1;
		int32 min_light = 2;
		int32 max_light = 3;
	}

	message Flicker
	{
		int32 sector = 1;
		int32 min_light = 2;
		int32 max_light = 3;
	}

	message LightFlash
	{
		int32 sector = 1;
		int32 min_light = 2;
		int32 max_light = 3;
	}

	message Strobe
	{
		int32 sector = 1;
		int32 min_light = 2;
		int32 max_light = 3;
		int32 dark_time = 4;
		int32 bright_time = 5;
		int32 count = 6;
	}

	message Glow
	{
		int32 sector = 1;
	}

	message Glow2
	{
		int32 sector = 1;
		int32 start = 2;
		int32 end = 3;
		int32 max_tics = 4;
		bool one_shot = 5;
	}

	message Phased
	{
		int32 sector = 1;
		int32 base_level = 2;
		int32 phase = 3;
	}

	oneof thinker
	{
		Scroller scroller = 1;
		FireFlicker fire_flicker = 2;
		Flicker flicker = 3;
		LightFlash light_flash = 4;
		Strobe strobe = 5;
		Glow glow = 6;
		Glow2 glow2 = 7;
		Phased phased = 8;
	}
}

// svc_vote_update
message VoteUpdate
{
	int32 result = 1;
	string votestring = 2;
	int32 countdown = 3;
	int32 yes = 4;
	int32 yes_needed = 5;
	int32 no = 6;
	int32 no_needed = 7;
	int32 abs = 8;
}

// svc_maplist
message Maplist
{
	int32 status = 1;
}

// svc_maplist_update
message MaplistUpdate
{
	message Row
	{
		uint32 map = 1;
		uint32 lastmap = 2;
		repeated uint32 wads = 3;
	}

	int32 status = 1;
	map<uint32, string> dict = 2;
	repeated Row maplist = 3;
}

// svc_maplist_index
message MaplistIndex
{
	int32 count = 1;
	int32 next_index = 2;
	int32 this_index = 3;
}

// svc_toast
message Toast
{
	uint32 flags = 1;
	string left = 2;
	sint32 left_pid = 3;
	string right = 4;
	sint32 right_pid = 5;
	sint32 icon = 6;
	sint32 points = 7;
	sint32 spree_color = 8;
}

// svc_hordeinfo
message HordeInfo
{
	int32 state = 1;
	int32 wave = 2;
	int32 wave_time = 3;
	int32 boss_time = 4;
	int32 spawned_health = 5;
	int32 killed_health = 6;
	int32 boss_health = 7;
	int32 boss_damage = 8;
	int32 wave_start_health = 9;
	uint64 define_id = 10;
}

// svc_spree
message Spree
{
	int32 pid = 1;
	int32 spree_level = 2;
}

// svc_spreebreaker
message SpreeBreaker
{
	int32 victim_pid = 1;
	int32 source_pid = 2;
	string victim_name = 3;
	string source_name = 4;
	int32 spree_points = 5;
	int32 spree_level = 6;
	int32 spree_breaker_type = 7;
}

// svc_netdemocap
message NetdemoCap
{
	bytes player_cmd = 1;
	Player player = 2;
	Actor actor = 3;
}

// svc_netdemostop
message NetDemoStop
{
}

// svc_netdemoloadsnap
message NetDemoLoadSnap
{
}
