/* Ċ Ġ* ĠKotlin ĠConnector Ġto ĠFl att iverse ĠGame ĠServer Ġ( www . fl att iverse . com ) Ċ Ġ* ĠHar ald ĠMel cher Ġ( fl att iverse @ har ald mel cher . com ) Ċ Ġ* Ġ 2 0 1 9 - 1 0 - 0 8 Ċ Ġ*/ Ċ Ċ package Ġconnector Ċ Ċ import Ġcom . har ald mel cher . kotlin . fl att iverse . connector .* Ċ import Ġcom . har ald mel cher . kotlin . fl att iverse . connector . util . Universal Holder Ċ import Ġkotlinx . coroutines . Global Scope Ċ import Ġkotlinx . coroutines . channels . Channel Ċ import Ġkotlinx . coroutines . launch Ċ import Ġkotlinx . coroutines . run Blocking Ċ import Ġjava . lang . Exception Ċ import Ġjava . util .* Ċ import Ġjava . util . concurrent . locks . Re entrant Lock Ċ import Ġkotlin . concurrent . with Lock Ċ Ċ /** Ċ Ġ* ĠMaint enance Ġof Ġthe Ġconnection Ġto Ġthe Ġserver Ċ Ġ*/ Ċ @ Experimental Unsigned Types Ċ class ĠServer Ġ{ ĊĠĠĠ Ġinternal Ġvar Ġun iver ses Array Ġ= ĠArray < Un iverse ? >( 1 6 ) Ġ{ Ġnull Ġ} ĊĠĠĠ Ġprivate Ġvar Ġplayers Array Ġ= ĠArray < Player ? >( 6 5 6 3 6 ) Ġ{ Ġnull Ġ} ĊĠĠĠ Ġval Ġun iver ses Ġ= ĠUniversal Holder ( un iver ses Array ) ĊĠĠĠ Ġval Ġplayers Ġ= ĠUniversal Holder ( players Array ) ĊĊĠĠĠ Ġlateinit Ġvar Ġconnection : ĠConnection ĊĠĠĠ Ġvar Ġplayer : ĠPlayer ? Ġ= Ġnull ĊĊĠĠĠ Ġval Ġmeta Event Ġ= ĠFl att iverse EventHandler () ĊĠĠĠ Ġval Ġstatus Event Ġ= ĠFl att iverse EventHandler () ĊĠĠĠ Ġval Ġscan Event Ġ= ĠFl att iverse EventHandler () ĊĠĠĠ Ġval Ġchat Event Ġ= ĠFl att iverse EventHandler () ĊĊĠĠĠ Ġprivate Ġval Ġsync Ġ= ĠRe entrant Lock () ĊĠĠĠ Ġprivate Ġvar Ġevent In Execution Ġ= Ġfalse ĊĠĠĠ Ġprivate Ġval Ġevents Ġ= ĠLinkedList < Pair < Fl att iverse EventHandler , ĠFl att iverse Event >>() ĊĊĠĠĠ Ġprivate Ġval Ġlogin Completed Ġ= ĠChannel < Int >() ĊĊĠĠĠ Ġenum Ġclass ĠServer Command ( val Ġcmd Code : ĠU Byte ) Ġ{ ĊĠĠĠĠĠĠĠ ĠPlayer Removed ( 0 x 0 au ), ĊĠĠĠĠĠĠĠ ĠPlayer Added ( 0 x 0 bu ), ĊĠĠĠĠĠĠĠ ĠPlayer Def ragment ed ( 0 x 0 cu ), ĊĠĠĠĠĠĠĠ ĠPing Update ( 0 x 0 du ), ĊĠĠĠĠĠĠĠ ĠPlayer Assignment ( 0 x 0 eu ), ĊĠĠĠĠĠĠĠ ĠLogin Completed ( 0 x 0 fu ), ĊĠĠĠĠĠĠĠ ĠUn iverse Meta Info Updated ( 0 x 1 0 u ), ĊĠĠĠĠĠĠĠ ĠUn iverse Team Meta Info Updated ( 0 x 1 1 u ), ĊĠĠĠĠĠĠĠ ĠUn iverse G alaxy Meta Info Updated ( 0 x 1 2 u ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġenum Ġclass ĠClient Command ( val Ġcmd Code : ĠU Byte ) Ġ{ ĊĠĠĠĠĠĠĠ ĠUn iverse Join ( 0 x 1 au ), ĊĠĠĠĠĠĠĠ ĠUn iverse Part ( 0 x 1 bu ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠLogin Ġto Ġthe Ġserver ĊĠĠĠĠ Ġ* Ġ@ param Ġusername Ġthe Ġusername Ġfor Ġlogin ĊĠĠĠĠ Ġ* Ġ@ param Ġpassword Ġthe Ġpassword Ġfor Ġlogin ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġlogin ( username : ĠString , Ġpassword : ĠString ) Ġ= Ġrun Blocking Ġ{ ĊĠĠĠĠĠĠĠ Ġrequire ( username . isNotBlank ()) Ġ{ Ġ" Invalid Ġusername " Ġ} ĊĠĠĠĠĠĠĠ Ġrequire ( password . isNotBlank ()) Ġ{ Ġ" Invalid Ġpassword " Ġ} ĊĊĠĠĠĠĠĠĠ Ġconnection Ġ= ĠConnection () ĊĠĠĠĠĠĠĠ Ġconnection . packets Received Ġ= Ġ:: received ĊĠĠĠĠĠĠĠ Ġconnection . connect ( username , Ġpassword ) ĊĊĠĠĠĠĠĠĠ Ġlogin Completed . receive () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġreceived ( packets : ĠList < Packet >) Ġ{ ĊĠĠĠĠĠĠĠ Ġfor Ġ( packet Ġin Ġpackets ) Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( packet . session Ġ!= Ġ 0 . to U Byte ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġconnection . process Session Packet ( packet ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontinue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( packet . command ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠServer Command . Player Removed . cmd Code Ġ-> Ġplayer Removed ( packet ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠServer Command . Player Added . cmd Code Ġ-> Ġplayer Added ( packet ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠServer Command . Player Def ragment ed . cmd Code Ġ-> Ġplayer Def ragment ed ( packet ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠServer Command . Ping Update . cmd Code Ġ-> Ġping Update ( packet ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠServer Command . Player Assignment . cmd Code Ġ-> Ġplayer Assignment ( packet ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠServer Command . Login Completed . cmd Code Ġ-> Ġlogin Completed ( packet ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠServer Command . Un iverse Meta Info Updated . cmd Code Ġ-> Ġuniverse Meta Info Updated ( packet ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠServer Command . Un iverse Team Meta Info Updated . cmd Code Ġ-> Ġuniverse Team Meta Info Updated ( packet ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠServer Command . Un iverse G alaxy Meta Info Updated . cmd Code Ġ-> Ġuniverse G alaxy Meta Info Updated ( packet ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġprintln (" Unhandled Ġcommand : Ġ 0 x % 0 2 x ". format ( packet . command . to Byte ())) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġplayer Removed ( packet : ĠPacket ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġplayer Id Ġ= Ġpacket . base Address ĊĠĠĠĠĠĠĠ Ġplayers Array [ player Id ] Ġ= Ġnull ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġplayer Added ( packet : ĠPacket ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġplayer Id Ġ= Ġpacket . base Address ĊĠĠĠĠĠĠĠ Ġplayers Array [ player Id ] Ġ= ĠPlayer ( this , Ġpacket ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġplayer Def ragment ed ( packet : ĠPacket ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġold Player Id Ġ= Ġpacket . reader !!. read Uint 1 6 (). toInt () ĊĠĠĠĠĠĠĠ Ġval Ġnew Player Id Ġ= Ġpacket . base Address ĊĠĠĠĠĠĠĠ Ġplayers Array [ new Player Id ] Ġ= Ġplayers Array [ old Player Id ] ĊĠĠĠĠĠĠĠ Ġplayers Array [ old Player Id ] Ġ= Ġnull ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġping Update ( packet : ĠPacket ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġplayer Id Ġ= Ġpacket . base Address ĊĠĠĠĠĠĠĠ Ġplayers Array [ player Id ]?. update Ping ( packet ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġplayer Assignment ( packet : ĠPacket ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġrequest Player Ġ= Ġplayers Array [ packet . base Address ] ĊĊĠĠĠĠĠĠĠ Ġassert ( request Player Ġ!= Ġnull ) Ġ{ Ġ" Player Ġdoesn 't Ġexist Ġin Ġlocal Ġdatabase ." Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( packet . reader !!. size Ġ== Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( request Player !!. universe Ġ== Ġplayer !!. universe ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġenqueue Meta Event ( Player Part ed Event ( request Player )) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġrequest Player . update Player Assignment ( packet ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrequest Player !!. update Player Assignment ( packet ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( request Player . universe Ġ== Ġplayer !!. universe ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġenqueue Meta Event ( Player Joined Event ( request Player )) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĊĠĠĠ Ġprivate Ġfun Ġlogin Completed ( packet : ĠPacket ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġplayer Id Ġ= Ġpacket . base Address ĊĠĠĠĠĠĠĠ Ġ// ĠReturn Ġvalue Ġgives Ġreason Ġfor Ġden ial ĊĠĠĠĠĠĠĠ Ġval Ġreason For Den ial Ġ= Ġpacket . helper . toInt () ĊĠĠĠĠĠĠĠ Ġif Ġ( reason For Den ial Ġ== Ġ 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġplayer Ġ= Ġplayers Array [ player Id ] ĊĠĠĠĠĠĠĠ ĠGlobal Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogin Completed . send ( reason For Den ial ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġuniverse Meta Info Updated ( packet : ĠPacket ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġuniverse Id Ġ= Ġpacket . base Address ĊĊĠĠĠĠĠĠĠ Ġif Ġ( universe Id Ġ> Ġun iver ses Array . size ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġun iver ses Array Ġ= ĠArray ( universe Id ) Ġ{ Ġi Ġ-> Ġun iver ses Array [ i ] Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġun iver ses . update Database ( un iver ses Array ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpacket . reader ?. size Ġ?: Ġ 0 Ġ== Ġ 0 Ġ-> Ġun iver ses Array [ universe Id ] Ġ= Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġun iver ses Array [ universe Id ] Ġ== Ġnull Ġ-> Ġun iver ses Array [ universe Id ] Ġ= ĠUn iverse ( this , Ġpacket ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġun iver ses Array [ universe Id ]?. update From ( packet ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġuniverse Team Meta Info Updated ( packet : ĠPacket ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġuniverse Id Ġ= Ġpacket . base Address ĊĠĠĠĠĠĠĠ Ġval Ġteam Id Ġ= Ġpacket . sub Address ĊĠĠĠĠĠĠĠ Ġif Ġ( universe Id Ġ> Ġun iver ses Array . size Ġ|| Ġun iver ses Array [ universe Id ] Ġ== Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĊĠĠĠĠĠĠĠ Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpacket . reader ?. size Ġ?: Ġ 0 Ġ== Ġ 0 Ġ-> Ġun iver ses Array [ universe Id ] !!. teams Array [ team Id ] Ġ= Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġun iver ses Array [ universe Id ] !!. teams Array [ team Id ] Ġ== Ġnull Ġ-> Ġun iver ses Array [ universe Id ] !!. teams Array [ team Id ] Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTeam ( un iver ses Array [ universe Id ] !! , Ġpacket ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġun iver ses Array [ universe Id ] !!. teams Array [ team Id ]?. update From ( packet ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġuniverse G alaxy Meta Info Updated ( packet : ĠPacket ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġuniverse Id Ġ= Ġpacket . base Address ĊĠĠĠĠĠĠĠ Ġval Ġgalaxy Id Ġ= Ġpacket . sub Address ĊĠĠĠĠĠĠĠ Ġif Ġ( universe Id Ġ> Ġun iver ses Array . size Ġ|| Ġun iver ses Array [ universe Id ] Ġ== Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĊĠĠĠĠĠĠĠ Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpacket . reader ?. size Ġ?: Ġ 0 Ġ== Ġ 0 Ġ-> Ġun iver ses Array [ universe Id ] !!. galax ies Array [ galaxy Id ] Ġ= Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġun iver ses Array [ universe Id ] !!. galax ies Array [ galaxy Id ] Ġ== Ġnull Ġ-> Ġun iver ses Array [ universe Id ] !!. galax ies Array [ galaxy Id ] Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠGalaxy ( un iver ses Array [ universe Id ] !! , Ġpacket ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġun iver ses Array [ universe Id ] !!. galax ies Array [ galaxy Id ]?. update From ( packet ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/* ĊĠĠĠĠ Ġ* ĠL ittle Ġhelpers ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġenqueue Meta Event ( event : ĠFl att iverse Event ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġhandler : ĠFl att iverse EventHandler Ġ= Ġwhen Ġ( event . kind ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠFl att iverse Event Kind . Meta Ġ-> Ġmeta Event ĊĠĠĠĠĠĠĠĠĠĠĠ ĠFl att iverse Event Kind . Status Ġ-> Ġstatus Event ĊĠĠĠĠĠĠĠĠĠĠĠ ĠFl att iverse Event Kind . Scan Ġ-> Ġscan Event ĊĠĠĠĠĠĠĠĠĠĠĠ ĠFl att iverse Event Kind . Chat Ġ-> Ġchat Event ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġsync . with Lock Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevents . add ( Pair ( handler , Ġevent )) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! event In Execution ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġevent In Execution Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠGlobal Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexecute Events () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġexecute Events () Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġpair : ĠPair < Fl att iverse EventHandler , ĠFl att iverse Event >? Ġ= Ġnull ĊĠĠĠĠĠĠĠ Ġwhile Ġ( true ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsync . with Lock Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( events . size Ġ== Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġevent In Execution Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpair Ġ Ġ= Ġevents . poll () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġ( handler , Ġevent ) Ġ= Ġpair !! ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhandler ( event ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠException ){} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ Ċ }