etdd.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053
  1. package etdd
  2. import (
  3. "encoding/binary"
  4. "errors"
  5. "fmt"
  6. "math"
  7. "os"
  8. "regexp"
  9. "strconv"
  10. "strings"
  11. )
  12. const (
  13. maxMessageLength int = 32768
  14. maxStringChars int = 1024
  15. maxConfigStrings int = 1024
  16. bigInfoString int = 8192
  17. gEntityNumBits int = 10
  18. maxParseEntities int = 2048
  19. maxGEntities int = 1 << uint(gEntityNumBits)
  20. packetBackup int = 32
  21. packetMask int = packetBackup - 1
  22. maxPlayersNum int = 64
  23. csServerInfo int = 0
  24. csLevelStartTime int = 11
  25. csPlayers int = 689
  26. svcNop byte = byte(1)
  27. svcGameState byte = byte(2)
  28. svcConfigString byte = byte(3)
  29. svcBaseLine byte = byte(4)
  30. svcServerCommand byte = byte(5)
  31. svcSnapshot byte = byte(7)
  32. svcEof byte = byte(8)
  33. Chat string = "c"
  34. TeamChat string = "tc"
  35. )
  36. // Player events are not that interesting. We track them, but not actually using them.
  37. const (
  38. psEventSequence int = 27
  39. psEventNum int = 4
  40. psEventParams int = 4
  41. psClientNum int = psEventSequence + psEventNum + psEventParams + 1
  42. )
  43. // Event fields beyond esEventSequence seem to be just movement related.
  44. const (
  45. esType int = 0
  46. )
  47. // Event entity related stuff. Not sure how the field positioning works.
  48. const (
  49. eeMod int = 1
  50. eeVictim int = 20
  51. eeAttacker int = 21
  52. eeObituary int = 71
  53. )
  54. const (
  55. etEvents int = 60
  56. )
  57. type snapshot struct {
  58. valid bool
  59. deltaNum int
  60. messageNum int
  61. serverTime int
  62. flags int
  63. parseEntitiesNum int
  64. entitiesNum int
  65. ps PlayerState
  66. }
  67. type entityState struct {
  68. number int
  69. fields [71]int
  70. }
  71. type PlayerState struct {
  72. Num int
  73. Name string
  74. Team int
  75. fields [77]int
  76. }
  77. type Demo struct {
  78. file *os.File
  79. commandSequence int
  80. messageSequence int
  81. parseEntities [maxParseEntities]entityState
  82. baselines [maxGEntities]entityState
  83. snapshots [packetBackup]snapshot
  84. players [maxPlayersNum]PlayerState
  85. snapshot snapshot
  86. parseEntitiesNum int
  87. startTime int
  88. levelTime int
  89. bloc int // We need to maintain this in our thread.
  90. initialized bool
  91. illegible int
  92. }
  93. type message struct {
  94. oob bool
  95. data []byte
  96. size int
  97. read int
  98. bit int
  99. bloc *int
  100. }
  101. // crafted from netField_t entityStateFields[]
  102. var entityFieldBits = []int{
  103. 8, 24, 8, 32, 32, 0, 0, 0, 0, 0, 0, 8, 32, 32, 0, 0, 0, 0, 0, 0, 32, 32, 0, 0,
  104. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 8, 32, 32, 9, 9, 16, 8, 24, 10, 8, 8,
  105. 8, 8, 8, 8, 8, 8, 8, 8, 16, 8, 10, 10, 10, 32, 32, 32, 8, 8, 32, 32, 32, 4, 2,
  106. }
  107. // netField_t playerStateFields[]
  108. var playerStateFieldBits = []int{
  109. 32, 8, 8, 16, -16, 0, 0, 0, 0, 0, 0, -16, -16, -16, 16, 0, 16, 16, 16, 16, 10, 16, 16,
  110. 10, 10, 8, 24, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 32, 32, 7, 4, 10, 0, 0, 0, 8, 8, 8, 8, 8,
  111. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 16, 8, 8, 32, 8, 8, 8, 8, 32, 8, 8, 2,
  112. }
  113. func Open(name string) (Demo, error) {
  114. d := Demo{}
  115. for i := 0; i < maxPlayersNum; i++ {
  116. d.players[i].Num = i
  117. }
  118. file, err := os.Open(name)
  119. if err == nil {
  120. d.file = file
  121. }
  122. return d, err
  123. }
  124. func (d *Demo) Read(handler *Logger) {
  125. for {
  126. if d.file == nil {
  127. break
  128. } else {
  129. // Sequence number.
  130. seq, err := d.readLittleLong()
  131. if err != nil {
  132. handler.Error(err)
  133. break
  134. }
  135. // Needed by delta parser.
  136. d.messageSequence = seq
  137. // Message length.
  138. size, err := d.readLittleLong()
  139. if err != nil {
  140. handler.Error(err)
  141. break
  142. }
  143. // Graceful end.
  144. if size == math.MaxUint32 {
  145. break
  146. }
  147. if size > maxMessageLength {
  148. handler.Error(errors.New("message size overflow"))
  149. break
  150. }
  151. // Initialize the message.
  152. m := message{false, make([]byte, size), size, 0, 0, &d.bloc}
  153. r, err := d.readBuffer(m.data)
  154. if err != nil {
  155. if r < size {
  156. handler.Error(errors.New(err.Error() + "; demo file was truncated"))
  157. } else {
  158. handler.Error(err)
  159. }
  160. break
  161. }
  162. // Parse the message.
  163. m.Parse(handler, d)
  164. }
  165. }
  166. handler.End()
  167. }
  168. func (d *Demo) readLittleLong() (int, error) {
  169. s, err := d.readBytes(4)
  170. if err != nil {
  171. d.Close()
  172. return -1, err
  173. }
  174. return int(binary.LittleEndian.Uint32(s)), nil
  175. }
  176. func (d *Demo) readBytes(n int) ([]byte, error) {
  177. s := make([]byte, n)
  178. _, err := d.readBuffer(s)
  179. return s, err
  180. }
  181. func (d *Demo) readBuffer(buffer []byte) (int, error) {
  182. r, err := d.file.Read(buffer)
  183. if err != nil {
  184. d.Close()
  185. }
  186. if r != len(buffer) && err == nil {
  187. err = errors.New("incorrect number of bytes read")
  188. }
  189. return r, err
  190. }
  191. func (d *Demo) Close() {
  192. if d.file != nil {
  193. _ = d.file.Close()
  194. d.file = nil
  195. }
  196. }
  197. func (d *Demo) checkEvents(handler *Logger) {
  198. // Entities event detection.
  199. for i := 0; i < d.snapshot.entitiesNum; i++ {
  200. entity := &d.parseEntities[(d.snapshot.parseEntitiesNum+i)&(maxParseEntities-1)]
  201. // We are only interested in event entities.
  202. if entity.fields[esType] > etEvents {
  203. switch (entity.fields[esType] - etEvents) & (^768) {
  204. case eeObituary:
  205. d.obituary(handler, entity.fields[eeVictim], entity.fields[eeAttacker], entity.fields[eeMod])
  206. break
  207. }
  208. // Excludes from subsequent event processing.
  209. entity.fields[esType] = 0
  210. }
  211. }
  212. }
  213. func (d *Demo) obituary(handler *Logger, victimNum int, attackerNum int, mod int) {
  214. var victim *PlayerState
  215. var attacker *PlayerState
  216. if victimNum < 0 || victimNum >= maxPlayersNum {
  217. return
  218. }
  219. victim = &d.players[victimNum]
  220. if attackerNum >= 0 && attackerNum < maxPlayersNum {
  221. attacker = &d.players[attackerNum]
  222. }
  223. handler.Obituary(d.levelTime, victim, attacker, mod)
  224. }
  225. func (m *message) Parse(handler *Logger, demo *Demo) {
  226. // Acknowledge number.
  227. m.readLong()
  228. for {
  229. if demo.file == nil {
  230. break
  231. }
  232. if m.read > m.size {
  233. handler.Error(errors.New("read past end of server message"))
  234. break
  235. }
  236. command := m.readByte()
  237. if command == svcEof || demo.file == nil {
  238. break
  239. }
  240. switch command {
  241. case svcNop:
  242. break
  243. case svcGameState:
  244. m.parseGameState(handler, demo)
  245. break
  246. case svcServerCommand:
  247. m.parseCommandString(handler, demo)
  248. break
  249. case svcSnapshot:
  250. m.parseSnapshot(handler, demo)
  251. break
  252. default:
  253. demo.illegible++
  254. handler.Error(errors.New(fmt.Sprintf("illegible server message %d", int(command))))
  255. }
  256. if demo.illegible == 10 {
  257. demo.file = nil
  258. break
  259. }
  260. }
  261. m.parseBinaryMessage(handler, demo)
  262. // Is this the best time to do it?
  263. demo.checkEvents(handler)
  264. }
  265. func (m *message) parseGameState(handler *Logger, demo *Demo) {
  266. demo.commandSequence = m.readLong()
  267. for {
  268. command := m.readByte()
  269. if command == svcEof {
  270. break
  271. }
  272. switch command {
  273. case svcConfigString:
  274. i := m.readShort()
  275. if i < 0 || i >= maxConfigStrings {
  276. handler.Error(errors.New(fmt.Sprintf("config strings overflow")))
  277. demo.Close()
  278. return
  279. }
  280. s := m.readBigString()
  281. demo.cs(handler, i, s)
  282. break
  283. case svcBaseLine:
  284. nn := m.readBits(10)
  285. if nn < 0 || nn >= maxGEntities {
  286. handler.Error(errors.New(fmt.Sprintf("baseline number out of range: %d", nn)))
  287. demo.Close()
  288. return
  289. }
  290. nullState := entityState{}
  291. m.readDeltaEntity(demo, &nullState, &demo.baselines[nn], nn)
  292. break
  293. default:
  294. handler.Error(errors.New(fmt.Sprintf("bad command byte %d", int(command))))
  295. return
  296. }
  297. }
  298. m.readLong() // clc.clientNum...
  299. m.readLong() // ...and a checksum.
  300. }
  301. func (m *message) parseCommandString(handler *Logger, demo *Demo) {
  302. seq := m.readLong()
  303. s := m.readString()
  304. if demo.commandSequence >= seq {
  305. return
  306. }
  307. demo.commandSequence = seq
  308. if len(s) == 0 || s[0] == '*' {
  309. return
  310. }
  311. var command string
  312. if !word(&s, &command) {
  313. return
  314. }
  315. switch command {
  316. case "chat", "print", "cpm", "cp", "b", "sc":
  317. if command == "b" {
  318. var __ string
  319. word(&s, &__)
  320. }
  321. r := regexp.MustCompile(`^("|\s)*|("|\s|\^.)*$|\[lo[nf]]|" -?\d+ \d+$`)
  322. s = r.ReplaceAllString(s, "")
  323. // Line break would fuck statistics up.
  324. if command == "sc" {
  325. // I wonder what this is, huh?
  326. if s == "0" {
  327. break
  328. }
  329. lines := strings.Split(strings.TrimSpace(s), "\n")
  330. for _, line := range lines {
  331. if line != "" {
  332. handler.Print(demo.levelTime, line)
  333. }
  334. }
  335. } else {
  336. handler.Print(demo.levelTime, s)
  337. }
  338. break
  339. case Chat, TeamChat, "cs":
  340. var ps string
  341. if word(&s, &ps) {
  342. p, _ := strconv.Atoi(ps)
  343. var message string
  344. if quoted(&s, &message) {
  345. if command == "cs" {
  346. demo.cs(handler, p, message)
  347. } else {
  348. handler.Chat(demo.levelTime, demo.players[p], message, command)
  349. }
  350. }
  351. }
  352. break
  353. default:
  354. return
  355. }
  356. }
  357. func (m *message) parseSnapshot(handler *Logger, demo *Demo) {
  358. newSnap := snapshot{}
  359. newSnap.messageNum = demo.messageSequence
  360. newSnap.serverTime = m.readLong()
  361. deltaNum := m.readBits(8)
  362. if deltaNum == 0 {
  363. newSnap.deltaNum = -1
  364. } else {
  365. newSnap.deltaNum = demo.messageSequence - deltaNum
  366. }
  367. newSnap.flags = m.readBits(8)
  368. var old *snapshot
  369. if newSnap.deltaNum <= 0 {
  370. newSnap.valid = true
  371. } else {
  372. old = &demo.snapshots[newSnap.deltaNum&packetMask]
  373. if old.valid && old.messageNum == newSnap.deltaNum && demo.parseEntitiesNum-old.parseEntitiesNum <= maxParseEntities-128 {
  374. newSnap.valid = true
  375. }
  376. }
  377. areaMask := m.readBits(8)
  378. if areaMask > 32 {
  379. return
  380. }
  381. for i := 0; i < areaMask; i++ {
  382. m.readBits(8)
  383. }
  384. if old != nil {
  385. m.readDeltaPlayerState(&old.ps, &newSnap.ps)
  386. } else {
  387. m.readDeltaPlayerState(nil, &newSnap.ps)
  388. }
  389. // This is basically CL_ParsePacketEntities()
  390. newSnap.parseEntitiesNum = demo.parseEntitiesNum
  391. newSnap.entitiesNum = 0
  392. index, oNum := 0, 0
  393. var oldState *entityState = nil
  394. if old == nil {
  395. oNum = 99999
  396. } else {
  397. if index >= old.entitiesNum {
  398. oNum = 99999
  399. } else {
  400. oldState = &demo.parseEntities[(old.parseEntitiesNum+index)&(maxParseEntities-1)]
  401. oNum = oldState.number
  402. }
  403. }
  404. for {
  405. nn := m.readBits(gEntityNumBits)
  406. if nn == maxGEntities-1 {
  407. break
  408. }
  409. if m.read > m.size {
  410. demo.Close()
  411. return
  412. }
  413. for oNum < nn {
  414. m.deltaEntity(demo, &newSnap, oNum, oldState, true)
  415. index++
  416. if index >= old.entitiesNum {
  417. oNum = 99999
  418. } else {
  419. oldState = &demo.parseEntities[(old.parseEntitiesNum+index)&(maxParseEntities-1)]
  420. oNum = oldState.number
  421. }
  422. }
  423. if oNum == nn {
  424. m.deltaEntity(demo, &newSnap, nn, oldState, false)
  425. index++
  426. if index >= old.entitiesNum {
  427. oNum = 99999
  428. } else {
  429. oldState = &demo.parseEntities[(old.parseEntitiesNum+index)&(maxParseEntities-1)]
  430. oNum = oldState.number
  431. }
  432. continue
  433. }
  434. if oNum > nn && nn < maxGEntities {
  435. m.deltaEntity(demo, &newSnap, nn, &demo.baselines[nn], false)
  436. }
  437. }
  438. for oNum != 99999 {
  439. m.deltaEntity(demo, &newSnap, oNum, oldState, true)
  440. index++
  441. if index >= old.entitiesNum {
  442. oNum = 99999
  443. } else {
  444. oldState = &demo.parseEntities[(old.parseEntitiesNum+index)&(maxParseEntities-1)]
  445. oNum = oldState.number
  446. }
  447. }
  448. // CL_ParsePacketEntities end.
  449. if !newSnap.valid {
  450. return
  451. }
  452. oldMessageNum := demo.snapshot.messageNum + 1
  453. if newSnap.messageNum-oldMessageNum >= packetBackup {
  454. oldMessageNum = newSnap.messageNum - (packetBackup - 1)
  455. }
  456. for oldMessageNum < newSnap.messageNum {
  457. demo.snapshots[oldMessageNum&packetMask].valid = false
  458. oldMessageNum++
  459. }
  460. demo.snapshot = newSnap
  461. demo.snapshots[newSnap.messageNum&packetMask] = newSnap
  462. demo.levelTime = newSnap.serverTime - demo.startTime
  463. // Transfer player state updates to CG players struct.
  464. player := &demo.players[newSnap.ps.fields[psClientNum]]
  465. for i := 0; i < len(player.fields); i++ {
  466. player.fields[i] = newSnap.ps.fields[i]
  467. }
  468. }
  469. func (m *message) parseBinaryMessage(handler *Logger, demo *Demo) {
  470. // Switch to uncompressed reading mode.
  471. m.bit = (m.bit + 1) & ^7
  472. m.oob = true
  473. size := m.size - m.read
  474. if size <= 0 || size > maxMessageLength {
  475. return
  476. }
  477. // Nothing happens here?
  478. }
  479. func (m *message) deltaEntity(demo *Demo, snapshot *snapshot, num int, oldState *entityState, unchanged bool) {
  480. state := &demo.parseEntities[demo.parseEntitiesNum&(maxParseEntities-1)]
  481. if unchanged {
  482. *state = *oldState
  483. } else {
  484. m.readDeltaEntity(demo, oldState, state, num)
  485. }
  486. if state.number == maxGEntities-1 {
  487. return
  488. }
  489. demo.parseEntitiesNum++
  490. snapshot.entitiesNum++
  491. }
  492. func (m *message) readDeltaEntity(demo *Demo, from *entityState, to *entityState, number int) {
  493. if m.readBits(1) == 1 {
  494. *to = entityState{}
  495. to.number = maxGEntities - 1
  496. return
  497. }
  498. if m.readBits(1) == 0 {
  499. *to = *from
  500. to.number = number
  501. return
  502. }
  503. lc := m.readBits(8)
  504. if lc > len(entityFieldBits) {
  505. lc = len(entityFieldBits)
  506. }
  507. to.number = number
  508. for i := 0; i < lc; i++ {
  509. if m.readBits(1) == 1 {
  510. if entityFieldBits[i] == 0 {
  511. if m.readBits(1) == 1 {
  512. if m.readBits(1) == 0 {
  513. to.fields[i] = m.readBits(13)
  514. } else {
  515. to.fields[i] = m.readBits(32)
  516. }
  517. }
  518. } else {
  519. if m.readBits(1) == 1 {
  520. to.fields[i] = m.readBits(entityFieldBits[i])
  521. }
  522. }
  523. }
  524. }
  525. }
  526. func (m *message) readDeltaPlayerState(from *PlayerState, to *PlayerState) {
  527. if from == nil {
  528. from = &PlayerState{}
  529. }
  530. *to = *from
  531. lc := m.readBits(8)
  532. for i := 0; i < lc && i < len(playerStateFieldBits); i++ {
  533. if m.readBits(1) == 1 {
  534. if playerStateFieldBits[i] == 0 {
  535. if m.readBits(1) == 0 {
  536. to.fields[i] = m.readBits(13)
  537. } else {
  538. to.fields[i] = m.readBits(32)
  539. }
  540. } else {
  541. to.fields[i] = m.readBits(playerStateFieldBits[i])
  542. }
  543. }
  544. }
  545. if m.readBits(1) == 1 {
  546. // stats, persistent and holdable stats
  547. for a := 0; a < 3; a++ {
  548. if m.readBits(1) == 1 {
  549. bits := m.readShort()
  550. for i := 0; i < 16; i++ {
  551. if (bits & (1 << uint(i))) != 0 {
  552. m.readShort()
  553. }
  554. }
  555. }
  556. }
  557. // powerups
  558. if m.readBits(1) == 1 {
  559. bits := m.readShort()
  560. for i := 0; i < 16; i++ {
  561. if (bits & (1 << uint(i))) != 0 {
  562. m.readLong()
  563. }
  564. }
  565. }
  566. }
  567. // check for any ammo change (0-63)
  568. if m.readBits(1) == 1 {
  569. for j := 0; j < 4; j++ {
  570. if m.readBits(1) == 1 {
  571. bits := m.readShort()
  572. for i := 0; i < 16; i++ {
  573. if (bits & (1 << uint(i))) != 0 {
  574. m.readShort()
  575. }
  576. }
  577. }
  578. }
  579. }
  580. // ammo in clip
  581. for j := 0; j < 4; j++ {
  582. if m.readBits(1) == 1 {
  583. bits := m.readShort()
  584. for i := 0; i < 16; i++ {
  585. if (bits & (1 << uint(i))) != 0 {
  586. m.readShort()
  587. }
  588. }
  589. }
  590. }
  591. }
  592. func (m *message) readLong() int {
  593. c := m.readBits(32)
  594. if m.read > m.size {
  595. return -1
  596. }
  597. return c
  598. }
  599. func (m *message) readShort() int {
  600. c := m.readBits(16)
  601. if m.read > m.size {
  602. return -1
  603. }
  604. return c
  605. }
  606. func (m *message) readString() string {
  607. s := ""
  608. for l := 0; l < maxStringChars && m.read <= m.size; l++ {
  609. c := m.readByte()
  610. if c == byte(0) {
  611. break
  612. }
  613. if c == '%' || c > 127 {
  614. c = '.'
  615. }
  616. s += string(c)
  617. }
  618. return s
  619. }
  620. func (m *message) readBigString() string {
  621. s := ""
  622. for l := 0; l < bigInfoString && m.read <= m.size; l++ {
  623. c := m.readByte()
  624. if c == byte(0) {
  625. break
  626. }
  627. if c == '%' {
  628. c = '.'
  629. }
  630. s += string(c)
  631. }
  632. return s
  633. }
  634. func (m *message) readByte() byte {
  635. return byte(m.readBits(8))
  636. }
  637. func (m *message) readBits(bits int) int {
  638. value, r, s, i, n := 0, 0, false, 0, 0
  639. if bits < 0 {
  640. bits = -bits
  641. s = true
  642. }
  643. if m.oob {
  644. if bits == 8 || bits == 16 || bits == 32 {
  645. for i*8 < bits {
  646. value |= int(m.data[m.read]) << uint8(i*8)
  647. m.read += 1
  648. m.bit += bits
  649. i++
  650. }
  651. } else {
  652. panic(fmt.Sprintf("can't read %d bits", bits))
  653. }
  654. } else {
  655. if (bits & 7) != 0 {
  656. n = bits & 7
  657. for i = 0; i < n; i++ {
  658. value |= HuffGetBit(m.data, &m.bit, m.bloc) << uint(i)
  659. }
  660. bits = bits - n
  661. }
  662. for i = 0; bits != 0 && i < bits; i += 8 {
  663. HuffOffsetReceive(&r, m.data, &m.bit, m.bloc)
  664. value |= r << uint(i+n)
  665. }
  666. m.read = (m.bit >> 3) + 1
  667. }
  668. if s && (value&(1<<uint(bits-1))) != 0 {
  669. value |= -1 ^ ((1 << uint(bits)) - 1)
  670. }
  671. return value
  672. }
  673. func (d *Demo) cs(handler *Logger, p int, s string) {
  674. if p == csServerInfo && !d.initialized {
  675. d.initialized = true
  676. bits := strings.Split(s, "\\")
  677. vars := make(map[string]string)
  678. for i := 1; i+1 < len(bits); i += 2 {
  679. vars[bits[i]] = bits[i+1]
  680. }
  681. if hostname, ok := vars["sv_hostname"]; ok {
  682. if mapname, ok := vars["mapname"]; ok {
  683. handler.Start(hostname, mapname)
  684. }
  685. }
  686. return
  687. }
  688. if p == csLevelStartTime {
  689. d.startTime, _ = strconv.Atoi(s)
  690. return
  691. }
  692. if p < csPlayers || p >= csPlayers+maxPlayersNum {
  693. return
  694. }
  695. bits := strings.Split(s, "\\")
  696. state := &d.players[p-csPlayers]
  697. for i := 0; i < len(bits); i += 2 {
  698. switch bits[i] {
  699. case "n":
  700. state.Name = bits[i+1]
  701. break
  702. case "t":
  703. state.Team, _ = strconv.Atoi(bits[i+1])
  704. break
  705. }
  706. }
  707. }
  708. func word(s *string, word *string) bool {
  709. i := strings.Index(*s, " ")
  710. if i < 1 {
  711. return false
  712. }
  713. *word = (*s)[0:i]
  714. *s = (*s)[i+1:]
  715. return true
  716. }
  717. func quoted(s *string, quoted *string) bool {
  718. if (*s)[0] == '"' {
  719. *s = (*s)[1:]
  720. }
  721. i := strings.Index(*s, "\"")
  722. if i < 1 {
  723. return false
  724. }
  725. *quoted = (*s)[0:i]
  726. *s = (*s)[i+1:]
  727. return true
  728. }