note description: "[ d_net.c DOOM Network game communication and protocol, all OS independend parts. ]" license: "[ Copyright (C) 1993-1996 by id Software, Inc. Copyright (C) 2005-2014 Simon Howard Copyright (C) 2021 Ilgiz Mustafin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ]" class D_NET create make feature i_main: I_MAIN make (a_i_main: like i_main) do i_main := a_i_main create netbuffer.make create doomcom.make create localcmds.make_filled (create {TICCMD_T}, 0, Backuptics - 1) create nodeforplayer.make_filled (0, 0, {DOOMDEF_H}.maxplayers - 1) create frameskip.make_filled (False, 0, 3) create frametics.make_filled (0, 0, 3) end feature skiptics: INTEGER_32 localcmds: ARRAY [TICCMD_T] nodeforplayer: ARRAY [INTEGER_32] feature Netcmds: ARRAY [ARRAY [TICCMD_T]] local i: INTEGER_32 j: INTEGER_32 once create Result.make_filled (create {ARRAY [TICCMD_T]}.make_empty, 0, {DOOMDEF_H}.maxplayers - 1) from i := 0 until i >= {DOOMDEF_H}.maxplayers loop Result [i] := create {ARRAY [TICCMD_T]}.make_filled (create {TICCMD_T}, 0, Backuptics - 1) from j := 0 until j >= Backuptics - 1 loop Result [i] [j] := create {TICCMD_T} j := j + 1 end i := i + 1 end end feature Nettics: ARRAY [INTEGER_32] once create Result.make_filled (0, 0, Maxnetnodes - 1) end Nodeingame: ARRAY [BOOLEAN] -- set false as nodes leave game once create Result.make_filled (False, 0, Maxnetnodes - 1) end Remoteresend: ARRAY [BOOLEAN] -- set when local needs tics once create Result.make_filled (False, 0, Maxnetnodes - 1) end Resendto: ARRAY [INTEGER_32] -- set when remote needs tics once create Result.make_filled (0, 0, Maxnetnodes - 1) end feature d_checknetgame local i: INTEGER_32 do from i := 0 until i >= Maxnetnodes loop Nodeingame [i] := False Nettics [i] := 0 Remoteresend [i] := False Resendto [i] := 0 i := i + 1 end check attached i_main.I_net as i_net then i_net.i_initnetwork end if doomcom.id /= Doomcom_id then i_main.i_error ("Doomcom buffer invalid!") end netbuffer := doomcom.data i_main.G_game.consoleplayer := doomcom.consoleplayer i_main.G_game.displayplayer := doomcom.consoleplayer if i_main.G_game.netgame then d_arbitratenetstart end check attached i_main.D_main as d then print ("startskill " + d.startskill.out + " deathmatch: " + i_main.G_game.deathmatch.out + " startmap: " + d.startmap.out + " startepisode: " + d.startepisode.out + "%N") end ticdup := doomcom.ticdup maxsend := Backuptics \\ (2 * ticdup) - 1 if maxsend < 1 then maxsend := 1 end from i := 0 until i >= doomcom.numplayers loop i_main.G_game.Playeringame [i] := True i := i + 1 end from i := 0 until i >= doomcom.numnodes loop Nodeingame [i] := True i := i + 1 end print ("player " + (i_main.G_game.consoleplayer + 1).out + " of " + doomcom.numplayers.out + " (" + doomcom.numnodes.out + " nodes)%N") end feature maketic: INTEGER_32 assign set_maketic Backuptics: INTEGER_32 = 12 Maxnetnodes: INTEGER_32 = 8 -- Max computers/players in a game. ticdup: INTEGER_32 maxsend: INTEGER_32 -- BACKUPTICS/(2*ticdup)-1 feature doomcom: DOOMCOM_T assign set_doomcom Doomcom_id: INTEGER_32 = 305419896 netbuffer: DOOMDATA_T feature set_doomcom (a_doomcom: like doomcom) do doomcom := a_doomcom end feature set_maketic (a_maketic: like maketic) do maketic := a_maketic end feature -- TryRunTics oldentertics: INTEGER_32 frametics: ARRAY [INTEGER_32] frameon: INTEGER_32 frameskip: ARRAY [BOOLEAN] oldnettics: INTEGER_32 tryruntics local i: INTEGER_32 lowtic: INTEGER_32 entertic: INTEGER_32 realtics: INTEGER_32 availabletics: INTEGER_32 counts: INTEGER_32 numplaying: INTEGER_32 returned: BOOLEAN cmd: TICCMD_T buf: INTEGER_32 j: INTEGER_32 do entertic := i_main.I_system.i_gettime // ticdup realtics := entertic - oldentertics oldentertics := entertic netupdate lowtic := {DOOMTYPE_H}.maxint numplaying := 0 from i := 0 until i >= doomcom.numnodes loop if Nodeingame [i] then numplaying := numplaying + 1 if Nettics [i] < lowtic then lowtic := Nettics [i] end end i := i + 1 end availabletics := lowtic - i_main.G_game.gametic // ticdup if realtics < availabletics - 1 then counts := realtics + 1 elseif realtics < availabletics then counts := realtics else counts := availabletics end if counts < 1 then counts := 1 end frameon := frameon + 1 if i_main.D_main.debugfile /= Void then {NOT_IMPLEMENTED}.not_implemented ("debug file writing", True) end if not i_main.G_game.demoplayback then from i := 0 until i >= {DOOMDEF_H}.maxplayers or else i_main.G_game.Playeringame [i] loop i := i + 1 end if i_main.G_game.consoleplayer = i then else if Nettics [0] <= Nettics [nodeforplayer [i]] then gametime := gametime - 1 end frameskip [frameon & 3] := oldnettics > Nettics [nodeforplayer [i]] oldnettics := Nettics [0] if frameskip [0] and frameskip [1] and frameskip [2] and frameskip [3] then skiptics := 1 end end end from until lowtic >= i_main.G_game.gametic // ticdup + counts loop netupdate lowtic := {DOOMTYPE_H}.maxint from i := 0 until returned or i >= doomcom.numnodes loop if Nodeingame [i] and Nettics [i] < lowtic then lowtic := Nettics [i] i := i + 1 end end if lowtic < i_main.G_game.gametic // ticdup then {I_MAIN}.i_error ("TryRunTics: lowtic < gametic") end if i_main.I_system.i_gettime // ticdup - entertic >= 20 then i_main.M_menu.m_ticker returned := True end end from until counts = 0 loop counts := counts - 1 from i := 0 until i >= ticdup loop if i_main.G_game.gametic // ticdup > lowtic then {I_MAIN}.i_error ("gametic > lowtic") end if i_main.D_main.advancedemo then i_main.D_main.d_doadvancedemo end i_main.M_menu.m_ticker i_main.G_game.g_ticker i_main.G_game.gametic := i_main.G_game.gametic + 1 if i /= ticdup - 1 then buf := (i_main.G_game.gametic // ticdup) \\ Backuptics from j := 0 until j >= {DOOMDEF_H}.maxplayers loop cmd := Netcmds [j] [buf] cmd.chatchar := (0).to_character_8 if cmd.buttons & {D_EVENT}.bt_special /= 0 then cmd.buttons := 0 end j := j + 1 end end i := i + 1 end end netupdate end feature d_arbitratenetstart do {NOT_IMPLEMENTED}.not_implemented ("D_ArbitrateNetStart", False) end feature -- NetUpdate gametime: INTEGER_32 netupdate -- Builds ticcmds for console player, -- sends out a packet local nowtime: INTEGER_32 newtics: INTEGER_32 i, j: INTEGER_32 realstart: INTEGER_32 gameticdiv: INTEGER_32 break: BOOLEAN do nowtime := i_main.I_system.i_gettime // ticdup newtics := nowtime - gametime gametime := nowtime if newtics > 0 then if skiptics <= newtics then newtics := newtics - skiptics skiptics := 0 else skiptics := skiptics - newtics newtics := 0 end netbuffer.player := (i_main.G_game.consoleplayer).to_natural_8 gameticdiv := i_main.G_game.gametic // ticdup from i := 0 until break or i >= newtics loop i_main.I_video.i_starttic check attached i_main.D_main as main then main.d_processevents end if maketic - gameticdiv >= Backuptics // 2 - 1 then break := True else i_main.G_game.g_buildticcmd (localcmds [maketic \\ Backuptics]) maketic := maketic + 1 i := i + 1 end end check attached i_main.D_main as main then if main.singletics then else i_main.i_error ("Non-singletics NetUpdate not imlemented") end end else check attached i_main.D_main as main then if not main.singletics then getpackets end end end end getpackets do {NOT_IMPLEMENTED}.not_implemented ("GetPackets", False) end invariant localcmds.count = Backuptics localcmds.lower = 0 frametics.lower = 0 and frametics.count = 4 frameskip.lower = 0 and frameskip.count = 4 nodeforplayer.lower = 0 and nodeforplayer.count = {DOOMDEF_H}.maxplayers end -- class D_NET
Generated by ISE EiffelStudio