├── .gitignore ├── SimpleWebSocketServer ├── __init__.py ├── PicarioTest.py ├── SimpleHTTPSServer.py ├── BaseServer.py ├── PicarioServer.py └── SimpleWebSocketServer.py ├── setup.py ├── README.md ├── websocket.html ├── index.html └── picario.p8 /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc -------------------------------------------------------------------------------- /SimpleWebSocketServer/__init__.py: -------------------------------------------------------------------------------- 1 | from .SimpleWebSocketServer import * 2 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | 3 | setup( 4 | name='SimpleWebSocketServer', 5 | version='0.1.0', 6 | author='Dave', 7 | packages=['SimpleWebSocketServer'], 8 | url='https://github.com/dpallot/simple-websocket-server/', 9 | description='A Simple Websocket Server written in Python', 10 | long_description=open('README.md').read() 11 | ) 12 | -------------------------------------------------------------------------------- /SimpleWebSocketServer/PicarioTest.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from PicarioServer import * 3 | 4 | class MessageTestCase(unittest.TestCase): 5 | def setUp(self): 6 | initTest() 7 | 8 | class DefaultWidgetSizeTestCase(MessageTestCase): 9 | def runTest(self): 10 | self.assertEqual(1, 1) 11 | 12 | class WidgetResizeTestCase(MessageTestCase): 13 | def runTest(self): 14 | self.assertEqual(1, 1) -------------------------------------------------------------------------------- /SimpleWebSocketServer/SimpleHTTPSServer.py: -------------------------------------------------------------------------------- 1 | ''' 2 | The MIT License (MIT) 3 | Copyright (c) 2013 Dave P. 4 | ''' 5 | 6 | import BaseHTTPServer, SimpleHTTPServer 7 | import ssl 8 | 9 | # openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout cert.pem 10 | httpd = BaseHTTPServer.HTTPServer(('', 443), SimpleHTTPServer.SimpleHTTPRequestHandler) 11 | httpd.socket = ssl.wrap_socket(httpd.socket, server_side=True, certfile='./cert.pem', keyfile='./cert.pem', ssl_version=ssl.PROTOCOL_TLSv1) 12 | httpd.serve_forever() 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Try it out at [**zachpetersendev.com/picarioGame**](http://zachpetersendev.com/picarioGame/) 2 | 3 | You are a fruit. Eat the tiny dots to grow bigger, or eat other fruit that are smaller than you. Just make sure that none of the larger fruits eat you! Works on anything that can run a web browser. 4 | 5 | Controls: 6 | Arrow Keys : Move 7 | Mouse : Click and hold to move in direction of cursor 8 | Touchscreen : Touch and hold to move in that direction 9 | 10 | This is a proof of concept game made by Dylan Tran, Zachary Petersen, John Chau, and Sterling Salvaterra. Special thanks to our amazing instructor Adam Smith at UC Santa Cruz for his advice and encouragement. 11 | 12 | Our goal was to show that the PICO-8 can support a relatively massive number of simultaneous players in a single game given its constraints. We decided to recreate the popular agar.io to achieve this goal. 13 | 14 | In our largest test, we had 35+ simultaneous players. Theoretically, the game can handle 64+ simultaneous players. 15 | 16 | One of the biggest challenges we faced is that there are only 128 bytes of GPIO in the PICO-8 meaning that the each client can only process 128 bytes of Input/Output per frame. We decided to represent each object with six bytes, one for ID, one for size, two for X Coordinate, and two for Y Coordinate. With 128 bytes of I/O, that meant we could update 21 objects per frame. We designated three of these objects to output (The client telling the server about changes in the player's state and the state of any objects the player eats) and the other 18 to Input (The server telling the client about the change of objects in the world). 17 | 18 | We wrote the server in python. Since the clients can only handle 18 updated objects per frame, we implemented a spatial hashing optimization so that each client only receives updates about objects that are nearby the player. The connection between the clients and the server is made using websockets. 19 | 20 | -------------------------------------------------------------------------------- /websocket.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | WebSocket Test 6 | 7 | 93 | 94 |
95 | 96 |
97 |

98 | 99 |

100 |

101 | 102 |

103 |

104 | 105 |

106 |

107 | 108 | 109 | 110 | 111 |

112 | 113 |

Not Connected

114 | 115 |
116 | 117 | -------------------------------------------------------------------------------- /SimpleWebSocketServer/BaseServer.py: -------------------------------------------------------------------------------- 1 | ''' 2 | The MIT License (MIT) 3 | Copyright (c) 2013 Dave P. 4 | ''' 5 | 6 | import json 7 | import signal 8 | import sys 9 | import ssl 10 | from SimpleWebSocketServer import WebSocket, SimpleWebSocketServer, SimpleSSLWebSocketServer 11 | from optparse import OptionParser 12 | from PicarioServer import * 13 | 14 | 15 | # data structures for managing clients 16 | maxPlayers = 64 17 | openIds = [] 18 | clients = {} 19 | 20 | #starts up PicarioServer 21 | onStart() 22 | 23 | # setup data structures for managing clients 24 | for i in range(1, maxPlayers + 1): 25 | openIds.append(i) 26 | clients[i] = None 27 | 28 | #checks if a player can join the game 29 | def canJoin(): 30 | if len(openIds) == 0: 31 | return False 32 | else: 33 | return True 34 | 35 | #sends a message denying access to server 36 | def refuseConnection(socket): 37 | msg = {"type":"error", "message":"Game full, unable to connect"} 38 | socket.sendMessage(json.dumps(msg)) 39 | socket.close() 40 | 41 | #accepts a connection and stores client in a dict 42 | def acceptConnection(socket): 43 | thisID = openIds.pop(0) 44 | clients[thisID] = socket 45 | socket.myId = thisID 46 | outBound = onConnect(thisID) 47 | sendOutbound(outBound) 48 | msg = {"type":"connect", "id": thisID} 49 | socket.sendMessage(json.dumps(msg)) 50 | print("Accepted Connection with id: " + str(thisID)) 51 | 52 | # handles client socket organization when client disconnects 53 | def disconnect(socket): 54 | if(socket.myId != 0): 55 | clients[socket.myId] = None 56 | openIds.append(socket.myId) 57 | sendOutbound(onDisconnect(socket.myId)) 58 | 59 | # prints out the state of client sockets within server 60 | def debugClients(): 61 | clientsDebugStr = "{ " 62 | for key in clients: 63 | clientsDebugStr += str(key) + (":None " if clients[key] == None else ":Sock ") 64 | clientsDebugStr += "}" 65 | 66 | print("Clients : " + clientsDebugStr) 67 | print("Open Ids : " + str(openIds)) 68 | 69 | def sendOutbound(outBound): 70 | for key in outBound: 71 | if (outBound[key] != None): 72 | for msg in outBound[key]: 73 | if clients[key] != None: 74 | clients[key].sendMessage(json.dumps(msg)) 75 | clearMessages() 76 | 77 | class Socket(WebSocket): 78 | 79 | myId = 0 80 | 81 | def handleMessage(self): 82 | message = json.loads(self.data) 83 | if message['type'] == 'obj': 84 | sendOutbound(onMessage(self.myId, message)) 85 | 86 | def handleConnected(self): 87 | if(canJoin()): 88 | acceptConnection(self) 89 | else: 90 | refuseConnection(self) 91 | 92 | def handleClose(self): 93 | disconnect(self) 94 | 95 | 96 | if __name__ == "__main__": 97 | 98 | parser = OptionParser(usage="usage: %prog [options]", version="%prog 1.0") 99 | parser.add_option("--host", default='', type='string', action="store", dest="host", help="hostname (localhost)") 100 | parser.add_option("--port", default=8000, type='int', action="store", dest="port", help="port (8000)") 101 | parser.add_option("--ssl", default=0, type='int', action="store", dest="ssl", help="ssl (1: on, 0: off (default))") 102 | parser.add_option("--cert", default='./cert.pem', type='string', action="store", dest="cert", help="cert (./cert.pem)") 103 | parser.add_option("--ver", default=ssl.PROTOCOL_TLSv1, type=int, action="store", dest="ver", help="ssl version") 104 | 105 | (options, args) = parser.parse_args() 106 | 107 | cls = Socket 108 | 109 | if options.ssl == 1: 110 | server = SimpleSSLWebSocketServer(options.host, options.port, cls, options.cert, options.cert, version=options.ver) 111 | else: 112 | server = SimpleWebSocketServer(options.host, options.port, cls) 113 | 114 | def close_sig_handler(signal, frame): 115 | server.close() 116 | sys.exit() 117 | 118 | signal.signal(signal.SIGINT, close_sig_handler) 119 | 120 | server.serveforever() 121 | -------------------------------------------------------------------------------- /SimpleWebSocketServer/PicarioServer.py: -------------------------------------------------------------------------------- 1 | import math 2 | import random 3 | 4 | cells = {} 5 | objects = {} 6 | playerMsgs = {} 7 | mapSize = pow(2,9) - 1 #hard coded in pico-carts 8 | cellWidth = 64 9 | cellMax = math.ceil(mapSize / cellWidth) 10 | 11 | def initRandom(): 12 | # Create empty cells 13 | for i in range(0, cellMax): 14 | for j in range(0, cellMax): 15 | cells[(i,j)] = {} 16 | # Generate objects 1-255 17 | for i in range(1, 256): 18 | obj = {"type":"obj", "id":i, "x":0, "y":0, "size": 5} 19 | setRndLoc(obj) 20 | cells[objGetCellIndex(obj)][i] = obj 21 | objects[i] = obj 22 | 23 | def initTest(): 24 | # Create empty cells 25 | for i in range(0, cellMax): 26 | for j in range(0, cellMax): 27 | cells[(i,j)] = {} 28 | # Generate objects 1-255 29 | for i in range(1, 256): 30 | obj = {"type":"obj", "id":i, "x":0, "y":0, "size": 5} 31 | obj["x"] = i 32 | obj["y"] = i 33 | cells[objGetCellIndex(obj)][i] = obj 34 | objects[i] = obj 35 | addPlayer(1) 36 | 37 | def onStart(): 38 | initRandom() 39 | 40 | def addPlayer(myId): 41 | playerMsgs[myId] = [] 42 | objects[myId]['size'] = 20 43 | playerMsgs[myId].append(objects[myId]) 44 | thisCell = objGetCellIndex(objects[myId]) 45 | for cellIndex in getSelfAndNeighbors(thisCell): 46 | for key, obj in cells[cellIndex].items(): 47 | playerMsgs[myId].append(obj) 48 | 49 | def onConnect(myId): 50 | addPlayer(myId) 51 | return playerMsgs 52 | 53 | def onMessage(myId, objectToUpdate): 54 | # gather info about cells 55 | leavingCell = objGetCellIndex(objects[objectToUpdate["id"]]) # object's cell location currently stored in memory 56 | arrivingCell = objGetCellIndex(objectToUpdate) # object's cell location given new position 57 | leavingCells = getSelfAndNeighbors(leavingCell) # all neighboring cells near where object was 58 | arrivingCells = getSelfAndNeighbors(arrivingCell) # all neigboring cells near where object is now 59 | destroyCells = treatAsDestroy(leavingCells, arrivingCells) # cells that object was near and is no longer near 60 | createCells = treatAsCreate(leavingCells, arrivingCells) # cells that object was not near and is now near 61 | 62 | # update myself 63 | objects[objectToUpdate["id"]] = objectToUpdate 64 | 65 | # if this object is a player then update that player 66 | if(isPlayer(objectToUpdate["id"]) and (leavingCell != arrivingCell)): 67 | for cellIndex in destroyCells: 68 | for key, obj in cells[cellIndex].items(): 69 | destroyMsg = obj.copy() 70 | destroyMsg["size"] = 0 71 | if objectToUpdate["id"] != destroyMsg["id"]: 72 | playerMsgs[objectToUpdate["id"]].append(destroyMsg) 73 | for cellIndex in createCells: 74 | for key, obj in cells[cellIndex].items(): 75 | if objectToUpdate["id"] != obj["id"]: 76 | playerMsgs[objectToUpdate["id"]].append(obj) 77 | 78 | if(leavingCell != arrivingCell): 79 | destroyInTheseCells(destroyCells, objectToUpdate) 80 | if objectToUpdate["id"] in cells[leavingCell]: 81 | del cells[leavingCell][objectToUpdate["id"]] 82 | 83 | updateInTheseCells(arrivingCells, objectToUpdate) 84 | cells[arrivingCell][objectToUpdate["id"]] = objectToUpdate 85 | return playerMsgs 86 | 87 | def clearMessages(): 88 | for key in playerMsgs: 89 | playerMsgs[key] = [] 90 | 91 | def destroyInTheseCells(destroyCells, message): 92 | destroyMsg = message.copy() 93 | destroyMsg["size"] = 0 94 | for cellIndex in destroyCells: 95 | for playerID in getPlayerIDsInCell(cellIndex): 96 | if playerID != destroyMsg["id"]: 97 | playerMsgs[playerID].append(destroyMsg) 98 | 99 | def updateInTheseCells(updateCells, message): 100 | for cellIndex in updateCells: 101 | for playerID in getPlayerIDsInCell(cellIndex): 102 | if playerID != message["id"]: 103 | playerMsgs[playerID].append(message) 104 | 105 | def treatAsDestroy(leaving, arriving): 106 | """ 107 | Finds all the cells that need to remove an object 108 | 109 | >>> treatAsDestroy([(0, 0), (1, 0), (2, 0), (0, 1), (1, 1), (2, 1), (0, 2), (1, 2), (2, 2)], [(1, 1), (2, 1), (3, 1), (1, 2), (2, 2), (3, 2), (1, 3), (2, 3), (3, 3)]) 110 | [(0, 0), (1, 0), (2, 0), (0, 1), (0, 2)] 111 | 112 | >>> treatAsDestroy([(0,0),(1,1),(0,1), (1,0)], [(0,0),(1,1),(0,1), (1,0)]) 113 | [] 114 | 115 | """ 116 | tmp = [] 117 | for elem in leaving: 118 | if elem not in arriving: 119 | tmp.append(elem) 120 | return tmp 121 | 122 | def treatAsCreate(leaving, arriving): 123 | tmp = [] 124 | for elem in arriving: 125 | if elem not in leaving: 126 | tmp.append(elem) 127 | return tmp 128 | 129 | def onDisconnect(myId): 130 | debugActivePlayers() 131 | objects[myId]['size'] = 5 132 | setRndLoc(objects[myId]) 133 | cellIndex = objGetCellIndex(objects[myId]) 134 | surroundingCells = getSelfAndNeighbors(cellIndex) 135 | updateInTheseCells(surroundingCells, objects[myId]) 136 | del playerMsgs[myId] 137 | debugActivePlayers() 138 | return playerMsgs 139 | 140 | def getSelfAndNeighbors(cellIndex): 141 | """Find neighboring cell 142 | 143 | Parameters 144 | ---------- 145 | c : tuple 146 | (i,j) of cell space. 147 | 148 | >>> getSelfAndNeighbors((1,1)) # doctest: +ELLIPSIS 149 | [(0, 0), ..., (2, 2)] 150 | >>> len(getSelfAndNeighbors((0,0))) 151 | 4 152 | """ 153 | i,j = cellIndex 154 | cellList = [] 155 | for y in range(j-1, j+2): 156 | for x in range(i-1, i+2): 157 | if(x >= 0 and x < cellMax and y >= 0 and y < cellMax): 158 | cellList.append((x, y)) 159 | return cellList 160 | 161 | def isPlayer(playerID): 162 | return playerID in playerMsgs 163 | 164 | def getPlayerIDsInCell(cellIndex): 165 | playerIDs = [] 166 | for key, obj in cells[cellIndex].items(): 167 | if isPlayer(obj['id']): 168 | playerIDs.append(obj['id']) 169 | return playerIDs 170 | 171 | def objGetCellIndex(obj): 172 | return (getCellIndex(obj['x'], obj['y'])) 173 | 174 | def getCellIndex(x, y): 175 | return (int(x/cellWidth), int(y/cellWidth)) 176 | 177 | # Set obj to random location 178 | def setRndLoc(obj): 179 | obj['x'] = int(random.random() * mapSize) 180 | obj['y'] = int(random.random() * mapSize) 181 | 182 | def debugCells(): 183 | for cellIndex in cells: 184 | print(str(cellIndex) + " "+ str(cells[cellIndex])) 185 | 186 | def debugOutGoingMessages(myId): 187 | print("Outgoing for " + str(myId) +" " + str(playerMsgs[myId])) 188 | 189 | def debugActivePlayers(): 190 | if len(playerMsgs) == 0: 191 | print('No active players') 192 | for playerID in playerMsgs: 193 | print("Player id: " + str(playerID)) -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PICO-8 Cartridge 6 | 7 | 8 | 52 | 53 | 54 | 55 | 56 | 57 |


58 | 59 |
60 | 61 | 62 | 63 | 216 | 217 | 218 | 219 | 237 | 238 |
239 | 240 |
241 | 242 | Reset 243 | 244 | Reset
245 | 246 |
247 | 248 | Pause 249 | 250 | Pause
251 |
252 | Fullscreen 253 | 254 | Fullscreen
255 |
256 | Toggle Sound 257 | 258 | Sound
259 | 263 | 264 |
265 | 266 |
267 |

268 | 269 | 270 | -------------------------------------------------------------------------------- /SimpleWebSocketServer/SimpleWebSocketServer.py: -------------------------------------------------------------------------------- 1 | ''' 2 | The MIT License (MIT) 3 | Copyright (c) 2013 Dave P. 4 | ''' 5 | import sys 6 | VER = sys.version_info[0] 7 | if VER >= 3: 8 | import socketserver 9 | from http.server import BaseHTTPRequestHandler 10 | from io import StringIO, BytesIO 11 | else: 12 | import SocketServer 13 | from BaseHTTPServer import BaseHTTPRequestHandler 14 | from StringIO import StringIO 15 | 16 | import hashlib 17 | import base64 18 | import socket 19 | import struct 20 | import ssl 21 | import errno 22 | import codecs 23 | from collections import deque 24 | from select import select 25 | 26 | __all__ = ['WebSocket', 27 | 'SimpleWebSocketServer', 28 | 'SimpleSSLWebSocketServer'] 29 | 30 | def _check_unicode(val): 31 | if VER >= 3: 32 | return isinstance(val, str) 33 | else: 34 | return isinstance(val, unicode) 35 | 36 | class HTTPRequest(BaseHTTPRequestHandler): 37 | def __init__(self, request_text): 38 | if VER >= 3: 39 | self.rfile = BytesIO(request_text) 40 | else: 41 | self.rfile = StringIO(request_text) 42 | self.raw_requestline = self.rfile.readline() 43 | self.error_code = self.error_message = None 44 | self.parse_request() 45 | 46 | _VALID_STATUS_CODES = [1000, 1001, 1002, 1003, 1007, 1008, 47 | 1009, 1010, 1011, 3000, 3999, 4000, 4999] 48 | 49 | HANDSHAKE_STR = ( 50 | "HTTP/1.1 101 Switching Protocols\r\n" 51 | "Upgrade: WebSocket\r\n" 52 | "Connection: Upgrade\r\n" 53 | "Sec-WebSocket-Accept: %(acceptstr)s\r\n\r\n" 54 | ) 55 | 56 | GUID_STR = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' 57 | 58 | STREAM = 0x0 59 | TEXT = 0x1 60 | BINARY = 0x2 61 | CLOSE = 0x8 62 | PING = 0x9 63 | PONG = 0xA 64 | 65 | HEADERB1 = 1 66 | HEADERB2 = 3 67 | LENGTHSHORT = 4 68 | LENGTHLONG = 5 69 | MASK = 6 70 | PAYLOAD = 7 71 | 72 | MAXHEADER = 65536 73 | MAXPAYLOAD = 33554432 74 | 75 | class WebSocket(object): 76 | 77 | def __init__(self, server, sock, address): 78 | self.server = server 79 | self.client = sock 80 | self.address = address 81 | 82 | self.handshaked = False 83 | self.headerbuffer = bytearray() 84 | self.headertoread = 2048 85 | 86 | self.fin = 0 87 | self.data = bytearray() 88 | self.opcode = 0 89 | self.hasmask = 0 90 | self.maskarray = None 91 | self.length = 0 92 | self.lengtharray = None 93 | self.index = 0 94 | self.request = None 95 | self.usingssl = False 96 | 97 | self.frag_start = False 98 | self.frag_type = BINARY 99 | self.frag_buffer = None 100 | self.frag_decoder = codecs.getincrementaldecoder('utf-8')(errors='strict') 101 | self.closed = False 102 | self.sendq = deque() 103 | 104 | self.state = HEADERB1 105 | 106 | # restrict the size of header and payload for security reasons 107 | self.maxheader = MAXHEADER 108 | self.maxpayload = MAXPAYLOAD 109 | 110 | def handleMessage(self): 111 | """ 112 | Called when websocket frame is received. 113 | To access the frame data call self.data. 114 | 115 | If the frame is Text then self.data is a unicode object. 116 | If the frame is Binary then self.data is a bytearray object. 117 | """ 118 | pass 119 | 120 | def handleConnected(self): 121 | """ 122 | Called when a websocket client connects to the server. 123 | """ 124 | pass 125 | 126 | def handleClose(self): 127 | """ 128 | Called when a websocket server gets a Close frame from a client. 129 | """ 130 | pass 131 | 132 | def _handlePacket(self): 133 | if self.opcode == CLOSE: 134 | pass 135 | elif self.opcode == STREAM: 136 | pass 137 | elif self.opcode == TEXT: 138 | pass 139 | elif self.opcode == BINARY: 140 | pass 141 | elif self.opcode == PONG or self.opcode == PING: 142 | if len(self.data) > 125: 143 | raise Exception('control frame length can not be > 125') 144 | else: 145 | # unknown or reserved opcode so just close 146 | raise Exception('unknown opcode') 147 | 148 | if self.opcode == CLOSE: 149 | status = 1000 150 | reason = u'' 151 | length = len(self.data) 152 | 153 | if length == 0: 154 | pass 155 | elif length >= 2: 156 | status = struct.unpack_from('!H', self.data[:2])[0] 157 | reason = self.data[2:] 158 | 159 | if status not in _VALID_STATUS_CODES: 160 | status = 1002 161 | 162 | if len(reason) > 0: 163 | try: 164 | reason = reason.decode('utf8', errors='strict') 165 | except: 166 | status = 1002 167 | else: 168 | status = 1002 169 | 170 | self.close(status, reason) 171 | return 172 | 173 | elif self.fin == 0: 174 | if self.opcode != STREAM: 175 | if self.opcode == PING or self.opcode == PONG: 176 | raise Exception('control messages can not be fragmented') 177 | 178 | self.frag_type = self.opcode 179 | self.frag_start = True 180 | self.frag_decoder.reset() 181 | 182 | if self.frag_type == TEXT: 183 | self.frag_buffer = [] 184 | utf_str = self.frag_decoder.decode(self.data, final = False) 185 | if utf_str: 186 | self.frag_buffer.append(utf_str) 187 | else: 188 | self.frag_buffer = bytearray() 189 | self.frag_buffer.extend(self.data) 190 | 191 | else: 192 | if self.frag_start is False: 193 | raise Exception('fragmentation protocol error') 194 | 195 | if self.frag_type == TEXT: 196 | utf_str = self.frag_decoder.decode(self.data, final = False) 197 | if utf_str: 198 | self.frag_buffer.append(utf_str) 199 | else: 200 | self.frag_buffer.extend(self.data) 201 | 202 | else: 203 | if self.opcode == STREAM: 204 | if self.frag_start is False: 205 | raise Exception('fragmentation protocol error') 206 | 207 | if self.frag_type == TEXT: 208 | utf_str = self.frag_decoder.decode(self.data, final = True) 209 | self.frag_buffer.append(utf_str) 210 | self.data = u''.join(self.frag_buffer) 211 | else: 212 | self.frag_buffer.extend(self.data) 213 | self.data = self.frag_buffer 214 | 215 | self.handleMessage() 216 | 217 | self.frag_decoder.reset() 218 | self.frag_type = BINARY 219 | self.frag_start = False 220 | self.frag_buffer = None 221 | 222 | elif self.opcode == PING: 223 | self._sendMessage(False, PONG, self.data) 224 | 225 | elif self.opcode == PONG: 226 | pass 227 | 228 | else: 229 | if self.frag_start is True: 230 | raise Exception('fragmentation protocol error') 231 | 232 | if self.opcode == TEXT: 233 | try: 234 | self.data = self.data.decode('utf8', errors='strict') 235 | except Exception as exp: 236 | raise Exception('invalid utf-8 payload') 237 | 238 | self.handleMessage() 239 | 240 | 241 | def _handleData(self): 242 | # do the HTTP header and handshake 243 | if self.handshaked is False: 244 | 245 | data = self.client.recv(self.headertoread) 246 | if not data: 247 | raise Exception('remote socket closed') 248 | 249 | else: 250 | # accumulate 251 | self.headerbuffer.extend(data) 252 | 253 | if len(self.headerbuffer) >= self.maxheader: 254 | raise Exception('header exceeded allowable size') 255 | 256 | # indicates end of HTTP header 257 | if b'\r\n\r\n' in self.headerbuffer: 258 | self.request = HTTPRequest(self.headerbuffer) 259 | 260 | # handshake rfc 6455 261 | try: 262 | key = self.request.headers['Sec-WebSocket-Key'] 263 | k = key.encode('ascii') + GUID_STR.encode('ascii') 264 | k_s = base64.b64encode(hashlib.sha1(k).digest()).decode('ascii') 265 | hStr = HANDSHAKE_STR % {'acceptstr': k_s} 266 | self.sendq.append((BINARY, hStr.encode('ascii'))) 267 | self.handshaked = True 268 | self.handleConnected() 269 | except Exception as e: 270 | raise Exception('handshake failed: %s', str(e)) 271 | 272 | # else do normal data 273 | else: 274 | data = self.client.recv(16384) 275 | if not data: 276 | raise Exception("remote socket closed") 277 | 278 | if VER >= 3: 279 | for d in data: 280 | self._parseMessage(d) 281 | else: 282 | for d in data: 283 | self._parseMessage(ord(d)) 284 | 285 | def close(self, status = 1000, reason = u''): 286 | """ 287 | Send Close frame to the client. The underlying socket is only closed 288 | when the client acknowledges the Close frame. 289 | 290 | status is the closing identifier. 291 | reason is the reason for the close. 292 | """ 293 | try: 294 | if self.closed is False: 295 | close_msg = bytearray() 296 | close_msg.extend(struct.pack("!H", status)) 297 | if _check_unicode(reason): 298 | close_msg.extend(reason.encode('utf-8')) 299 | else: 300 | close_msg.extend(reason) 301 | 302 | self._sendMessage(False, CLOSE, close_msg) 303 | 304 | finally: 305 | self.closed = True 306 | 307 | 308 | def _sendBuffer(self, buff, send_all = False): 309 | size = len(buff) 310 | tosend = size 311 | already_sent = 0 312 | 313 | while tosend > 0: 314 | try: 315 | # i should be able to send a bytearray 316 | sent = self.client.send(buff[already_sent:]) 317 | if sent == 0: 318 | raise RuntimeError('socket connection broken') 319 | 320 | already_sent += sent 321 | tosend -= sent 322 | 323 | except socket.error as e: 324 | # if we have full buffers then wait for them to drain and try again 325 | if e.errno in [errno.EAGAIN, errno.EWOULDBLOCK]: 326 | if send_all: 327 | continue 328 | return buff[already_sent:] 329 | else: 330 | raise e 331 | 332 | return None 333 | 334 | def sendFragmentStart(self, data): 335 | """ 336 | Send the start of a data fragment stream to a websocket client. 337 | Subsequent data should be sent using sendFragment(). 338 | A fragment stream is completed when sendFragmentEnd() is called. 339 | 340 | If data is a unicode object then the frame is sent as Text. 341 | If the data is a bytearray object then the frame is sent as Binary. 342 | """ 343 | opcode = BINARY 344 | if _check_unicode(data): 345 | opcode = TEXT 346 | self._sendMessage(True, opcode, data) 347 | 348 | def sendFragment(self, data): 349 | """ 350 | see sendFragmentStart() 351 | 352 | If data is a unicode object then the frame is sent as Text. 353 | If the data is a bytearray object then the frame is sent as Binary. 354 | """ 355 | self._sendMessage(True, STREAM, data) 356 | 357 | def sendFragmentEnd(self, data): 358 | """ 359 | see sendFragmentEnd() 360 | 361 | If data is a unicode object then the frame is sent as Text. 362 | If the data is a bytearray object then the frame is sent as Binary. 363 | """ 364 | self._sendMessage(False, STREAM, data) 365 | 366 | def sendMessage(self, data): 367 | """ 368 | Send websocket data frame to the client. 369 | 370 | If data is a unicode object then the frame is sent as Text. 371 | If the data is a bytearray object then the frame is sent as Binary. 372 | """ 373 | opcode = BINARY 374 | if _check_unicode(data): 375 | opcode = TEXT 376 | self._sendMessage(False, opcode, data) 377 | 378 | 379 | def _sendMessage(self, fin, opcode, data): 380 | 381 | payload = bytearray() 382 | 383 | b1 = 0 384 | b2 = 0 385 | if fin is False: 386 | b1 |= 0x80 387 | b1 |= opcode 388 | 389 | if _check_unicode(data): 390 | data = data.encode('utf-8') 391 | 392 | length = len(data) 393 | payload.append(b1) 394 | 395 | if length <= 125: 396 | b2 |= length 397 | payload.append(b2) 398 | 399 | elif length >= 126 and length <= 65535: 400 | b2 |= 126 401 | payload.append(b2) 402 | payload.extend(struct.pack("!H", length)) 403 | 404 | else: 405 | b2 |= 127 406 | payload.append(b2) 407 | payload.extend(struct.pack("!Q", length)) 408 | 409 | if length > 0: 410 | payload.extend(data) 411 | 412 | self.sendq.append((opcode, payload)) 413 | 414 | 415 | def _parseMessage(self, byte): 416 | # read in the header 417 | if self.state == HEADERB1: 418 | 419 | self.fin = byte & 0x80 420 | self.opcode = byte & 0x0F 421 | self.state = HEADERB2 422 | 423 | self.index = 0 424 | self.length = 0 425 | self.lengtharray = bytearray() 426 | self.data = bytearray() 427 | 428 | rsv = byte & 0x70 429 | if rsv != 0: 430 | raise Exception('RSV bit must be 0') 431 | 432 | elif self.state == HEADERB2: 433 | mask = byte & 0x80 434 | length = byte & 0x7F 435 | 436 | if self.opcode == PING and length > 125: 437 | raise Exception('ping packet is too large') 438 | 439 | if mask == 128: 440 | self.hasmask = True 441 | else: 442 | self.hasmask = False 443 | 444 | if length <= 125: 445 | self.length = length 446 | 447 | # if we have a mask we must read it 448 | if self.hasmask is True: 449 | self.maskarray = bytearray() 450 | self.state = MASK 451 | else: 452 | # if there is no mask and no payload we are done 453 | if self.length <= 0: 454 | try: 455 | self._handlePacket() 456 | finally: 457 | self.state = self.HEADERB1 458 | self.data = bytearray() 459 | 460 | # we have no mask and some payload 461 | else: 462 | #self.index = 0 463 | self.data = bytearray() 464 | self.state = PAYLOAD 465 | 466 | elif length == 126: 467 | self.lengtharray = bytearray() 468 | self.state = LENGTHSHORT 469 | 470 | elif length == 127: 471 | self.lengtharray = bytearray() 472 | self.state = LENGTHLONG 473 | 474 | 475 | elif self.state == LENGTHSHORT: 476 | self.lengtharray.append(byte) 477 | 478 | if len(self.lengtharray) > 2: 479 | raise Exception('short length exceeded allowable size') 480 | 481 | if len(self.lengtharray) == 2: 482 | self.length = struct.unpack_from('!H', self.lengtharray)[0] 483 | 484 | if self.hasmask is True: 485 | self.maskarray = bytearray() 486 | self.state = MASK 487 | else: 488 | # if there is no mask and no payload we are done 489 | if self.length <= 0: 490 | try: 491 | self._handlePacket() 492 | finally: 493 | self.state = HEADERB1 494 | self.data = bytearray() 495 | 496 | # we have no mask and some payload 497 | else: 498 | #self.index = 0 499 | self.data = bytearray() 500 | self.state = PAYLOAD 501 | 502 | elif self.state == LENGTHLONG: 503 | 504 | self.lengtharray.append(byte) 505 | 506 | if len(self.lengtharray) > 8: 507 | raise Exception('long length exceeded allowable size') 508 | 509 | if len(self.lengtharray) == 8: 510 | self.length = struct.unpack_from('!Q', self.lengtharray)[0] 511 | 512 | if self.hasmask is True: 513 | self.maskarray = bytearray() 514 | self.state = MASK 515 | else: 516 | # if there is no mask and no payload we are done 517 | if self.length <= 0: 518 | try: 519 | self._handlePacket() 520 | finally: 521 | self.state = HEADERB1 522 | self.data = bytearray() 523 | 524 | # we have no mask and some payload 525 | else: 526 | #self.index = 0 527 | self.data = bytearray() 528 | self.state = PAYLOAD 529 | 530 | # MASK STATE 531 | elif self.state == MASK: 532 | self.maskarray.append(byte) 533 | 534 | if len(self.maskarray) > 4: 535 | raise Exception('mask exceeded allowable size') 536 | 537 | if len(self.maskarray) == 4: 538 | # if there is no mask and no payload we are done 539 | if self.length <= 0: 540 | try: 541 | self._handlePacket() 542 | finally: 543 | self.state = HEADERB1 544 | self.data = bytearray() 545 | 546 | # we have no mask and some payload 547 | else: 548 | #self.index = 0 549 | self.data = bytearray() 550 | self.state = PAYLOAD 551 | 552 | # PAYLOAD STATE 553 | elif self.state == PAYLOAD: 554 | if self.hasmask is True: 555 | self.data.append( byte ^ self.maskarray[self.index % 4] ) 556 | else: 557 | self.data.append( byte ) 558 | 559 | # if length exceeds allowable size then we except and remove the connection 560 | if len(self.data) >= self.maxpayload: 561 | raise Exception('payload exceeded allowable size') 562 | 563 | # check if we have processed length bytes; if so we are done 564 | if (self.index+1) == self.length: 565 | try: 566 | self._handlePacket() 567 | finally: 568 | #self.index = 0 569 | self.state = HEADERB1 570 | self.data = bytearray() 571 | else: 572 | self.index += 1 573 | 574 | 575 | class SimpleWebSocketServer(object): 576 | def __init__(self, host, port, websocketclass, selectInterval = 0.1): 577 | self.websocketclass = websocketclass 578 | self.serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 579 | self.serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 580 | self.serversocket.bind((host, port)) 581 | self.serversocket.listen(5) 582 | self.selectInterval = selectInterval 583 | self.connections = {} 584 | self.listeners = [self.serversocket] 585 | 586 | def _decorateSocket(self, sock): 587 | return sock 588 | 589 | def _constructWebSocket(self, sock, address): 590 | return self.websocketclass(self, sock, address) 591 | 592 | def close(self): 593 | self.serversocket.close() 594 | 595 | for desc, conn in self.connections.items(): 596 | conn.close() 597 | conn.handleClose() 598 | 599 | 600 | def serveforever(self): 601 | while True: 602 | writers = [] 603 | for fileno in self.listeners: 604 | if fileno == self.serversocket: 605 | continue 606 | client = self.connections[fileno] 607 | if client.sendq: 608 | writers.append(fileno) 609 | 610 | if self.selectInterval: 611 | rList, wList, xList = select(self.listeners, writers, self.listeners, self.selectInterval) 612 | else: 613 | rList, wList, xList = select(self.listeners, writers, self.listeners) 614 | 615 | for ready in wList: 616 | client = self.connections[ready] 617 | try: 618 | while client.sendq: 619 | opcode, payload = client.sendq.popleft() 620 | remaining = client._sendBuffer(payload) 621 | if remaining is not None: 622 | client.sendq.appendleft((opcode, remaining)) 623 | break 624 | else: 625 | if opcode == CLOSE: 626 | raise Exception('received client close') 627 | 628 | except Exception as n: 629 | client.client.close() 630 | client.handleClose() 631 | del self.connections[ready] 632 | self.listeners.remove(ready) 633 | 634 | for ready in rList: 635 | if ready == self.serversocket: 636 | try: 637 | sock, address = self.serversocket.accept() 638 | newsock = self._decorateSocket(sock) 639 | newsock.setblocking(0) 640 | fileno = newsock.fileno() 641 | self.connections[fileno] = self._constructWebSocket(newsock, address) 642 | self.listeners.append(fileno) 643 | except Exception as n: 644 | if sock is not None: 645 | sock.close() 646 | else: 647 | if ready not in self.connections: 648 | continue 649 | client = self.connections[ready] 650 | try: 651 | client._handleData() 652 | except Exception as n: 653 | client.client.close() 654 | client.handleClose() 655 | del self.connections[ready] 656 | self.listeners.remove(ready) 657 | 658 | for failed in xList: 659 | if failed == self.serversocket: 660 | self.close() 661 | raise Exception('server socket failed') 662 | else: 663 | if failed not in self.connections: 664 | continue 665 | client = self.connections[failed] 666 | client.client.close() 667 | client.handleClose() 668 | del self.connections[failed] 669 | self.listeners.remove(failed) 670 | 671 | 672 | class SimpleSSLWebSocketServer(SimpleWebSocketServer): 673 | 674 | def __init__(self, host, port, websocketclass, certfile, 675 | keyfile, version = ssl.PROTOCOL_TLSv1, selectInterval = 0.1): 676 | 677 | SimpleWebSocketServer.__init__(self, host, port, 678 | websocketclass, selectInterval) 679 | 680 | self.context = ssl.SSLContext(version) 681 | self.context.load_cert_chain(certfile, keyfile) 682 | 683 | def close(self): 684 | super(SimpleSSLWebSocketServer, self).close() 685 | 686 | def _decorateSocket(self, sock): 687 | sslsock = self.context.wrap_socket(sock, server_side=True) 688 | return sslsock 689 | 690 | def _constructWebSocket(self, sock, address): 691 | ws = self.websocketclass(self, sock, address) 692 | ws.usingssl = True 693 | return ws 694 | 695 | def serveforever(self): 696 | super(SimpleSSLWebSocketServer, self).serveforever() 697 | -------------------------------------------------------------------------------- /picario.p8: -------------------------------------------------------------------------------- 1 | pico-8 cartridge // http://www.pico-8.com 2 | version 8 3 | __lua__ 4 | cell_size = 16 5 | max_player_size = 64 6 | 7 | debug_mode = true 8 | debug_log = {} 9 | 10 | function debug(str) 11 | if(debug_mode)then 12 | add(debug_log, str) 13 | end 14 | end 15 | 16 | function debug_pair(pair) 17 | if(debug_mode)then 18 | tempstr = "" 19 | for index, num in pairs(pair) do 20 | tempstr = tempstr .. num .. " " 21 | end 22 | add(debug_log, tempstr) 23 | end 24 | end 25 | 26 | --collision stuff 27 | function pixel_to_cell(x, y) 28 | return {flr(x/cell_size)+1, flr(y/cell_size)+1} 29 | end 30 | 31 | function circle_to_cells(c) 32 | local csize = c.size / 250 * max_player_size / 2 33 | top_left = pixel_to_cell(c.x - csize, c.y - csize) 34 | bot_right = pixel_to_cell(c.x + csize, c.y + csize) 35 | 36 | cells = {} 37 | for x = top_left[1], bot_right[1] do 38 | for y = top_left[2], bot_right[2] do 39 | add(cells, {x, y}) 40 | end 41 | end 42 | 43 | return cells 44 | end 45 | 46 | function hash_index(pair) 47 | return 127 * pair[2] + pair[1] 48 | end 49 | 50 | function build_hash(circles) 51 | local buckets = {} 52 | 53 | for k,c in pairs(circles) do 54 | local cells = circle_to_cells(c) 55 | 56 | for cell in all(cells) do 57 | h_index = hash_index(cell) 58 | local bucket = buckets[h_index] or {} 59 | add(bucket, c) 60 | buckets[h_index] = bucket 61 | end 62 | 63 | end 64 | return buckets 65 | end 66 | 67 | function agario_collide(a,b) 68 | if a.id != pid and b.id != pid then 69 | del(collisions,a) 70 | del(collisions,b) 71 | return 72 | end 73 | local asize = flr(a.size / 250 * max_player_size) / 2 74 | local bsize = flr(b.size / 250 * max_player_size) / 2 75 | if (asize > bsize) then 76 | a.size += b.size/5 77 | if a.size > 250 then 78 | a.size = 250 79 | end 80 | del(collisions,b) 81 | objtable["id"..b.id] = create_obj(b.id, rnd(map_size), rnd(map_size), 5) 82 | if b.id != pid then 83 | network_send(objtable["id"..b.id]) 84 | end 85 | elseif (asize < bsize) then 86 | b.size += a.size/5 87 | if b.size > 250 then 88 | b.size = 250 89 | end 90 | del(collisions,a) 91 | objtable["id"..a.id] = create_obj(a.id, rnd(map_size), rnd(map_size), 5) 92 | if a.id != pid then 93 | network_send(objtable["id"..a.id]) 94 | end 95 | end 96 | end 97 | 98 | function query_naive(circles, q) 99 | local results = {} 100 | local qsize = q.size / 250 * max_player_size / 2 101 | for c in all(circles) do 102 | local csize = c.size / 250 * max_player_size / 2 103 | local dx = c.x-q.x 104 | local dy = c.y-q.y 105 | local k = csize+qsize 106 | local d2 = dx*dx+dy*dy 107 | if d2 < k*k then 108 | add(results, c) 109 | end 110 | end 111 | return results 112 | end 113 | 114 | function sweep_naive(circles) 115 | local collisions = {} 116 | local p = get_player() 117 | for q in all(circles) do 118 | if q.id == p.id then 119 | local results = query_naive(circles, q) 120 | for r in all(results) do 121 | if r != q then 122 | add(collisions, {r,q}) 123 | end 124 | end 125 | end 126 | end 127 | 128 | return collisions 129 | end 130 | 131 | function sweep_hash(hash) 132 | local results = {} 133 | for k,b in pairs(hash) do 134 | local t2 = sweep_naive(b) 135 | results = merge(results,t2) 136 | end 137 | return results 138 | end 139 | 140 | --not needed 141 | function query_hash(hash, query) 142 | local results = {} 143 | local cells = circle_to_cells(query) 144 | for cell in all(cells) do 145 | local hindex = hash_index(cell) 146 | local bucket = hash[hindex] or {} 147 | local t2 = query_naive(bucket,query) 148 | results = merge(results,t2) 149 | end 150 | return results 151 | end 152 | 153 | function merge(t1,t2) 154 | for j in all(t2) do 155 | add(t1,j) 156 | end 157 | return t1 158 | end 159 | 160 | function sweep(circles) 161 | last_hash = build_hash(circles) 162 | return sweep_hash(last_hash) 163 | end 164 | 165 | function query(q) 166 | return query_hash(last_hash,q) 167 | end 168 | --collision stuff end 169 | 170 | map_size = 2^(9) - 1 171 | start_size = 4 172 | --acceleration stuff 173 | accel = 0.1 174 | speed = 1.5 175 | target_vx = 0 176 | target_vy = 0 177 | cur_vx = 0 178 | cur_vy = 0 179 | 180 | --game stuff 181 | objtable = {} 182 | gamestart = false 183 | 184 | function _init() 185 | poke(0x5f2d, 1) -- enable mouse 186 | 187 | buckets = {} 188 | 189 | pid = 0 --id of player get from network later 190 | end 191 | 192 | function create_obj(_id, _x, _y, _size) 193 | local obj = { 194 | id=_id, 195 | x=_x, 196 | y=_y, 197 | size=_size, 198 | } 199 | return obj 200 | end 201 | 202 | function get_player() 203 | return objtable["id"..pid] 204 | end 205 | 206 | function update_mouse() 207 | mx = cam_x + stat(32) 208 | my = cam_y + stat(33) 209 | end 210 | 211 | cam_x = 0 212 | cam_y = 0 213 | function camera_move(player) 214 | cam_x = flr(player.x-64) 215 | cam_y = flr(player.y-64) 216 | end 217 | 218 | function player_movement() 219 | local sent = false 220 | local p = get_player() 221 | local ms = stat(34) 222 | if (ms==1) then 223 | dx = mx - p.x 224 | dy = my - p.y 225 | elseif (ms==0) then 226 | if btn(0) then 227 | dx = -1 228 | elseif btn(1) then 229 | dx = 1 230 | else 231 | dx = 0 232 | end 233 | if btn(2) then 234 | dy = -1 235 | elseif btn(3) then 236 | dy = 1 237 | else 238 | dy = 0 239 | end 240 | end 241 | 242 | local maxspeed = speed 243 | if p.size > 50 then 244 | maxspeed = speed - min(p.size / 200, .75) 245 | end 246 | local dm = sqrt(dx^2+dy^2) 247 | if dm < 1 then 248 | if abs(cur_vx) > 0 then 249 | cur_vx -= accel * cur_vx / abs(cur_vx) 250 | if abs(cur_vx - flr(abs(cur_vx))) < .1 then 251 | cur_vx = 0 252 | end 253 | end 254 | if abs(cur_vy) > 0 then 255 | cur_vy -= accel * cur_vy / abs(cur_vy) 256 | if abs(cur_vy - flr(abs(cur_vy))) < .1 then 257 | cur_vy = 0 258 | end 259 | end 260 | else 261 | dx /= dm 262 | dy /= dm 263 | cur_vx += dx * accel 264 | cur_vy += dy * accel 265 | local vmag = sqrt(cur_vx^2+cur_vy^2) 266 | if vmag > maxspeed then 267 | cur_vx /= (vmag / maxspeed) 268 | cur_vy /= (vmag / maxspeed) 269 | end 270 | end 271 | 272 | p.x+=cur_vx 273 | p.y+=cur_vy 274 | if p.x < 0 then 275 | p.x = 0 276 | elseif p.x > map_size then 277 | p.x = map_size 278 | end 279 | if p.y < 0 then 280 | p.y = 0 281 | elseif p.y > map_size then 282 | p.y = map_size 283 | end 284 | if cur_vx != 0 or cur_vy != 0 then 285 | network_send(p) 286 | sent = true 287 | end 288 | camera_move(p) 289 | return sent 290 | end 291 | 292 | last_ms = 0 293 | selected = nil 294 | mx = 0 295 | my = 0 296 | dx = 0 297 | dy = 0 298 | num_collisions = 0 299 | musicon = 1 300 | 301 | function _update60() 302 | if pid == 0 then 303 | pid = peek(0x5f80) 304 | if pid != 0 then 305 | music(0) 306 | gamestart = true 307 | end 308 | return 309 | end 310 | 311 | if not objtable["id"..pid] then 312 | attempt_read() 313 | return 314 | end 315 | 316 | if btnp(4) then 317 | music(musicon * -1) 318 | musicon = (musicon + 1) % 2 319 | end 320 | 321 | local p = get_player() 322 | local sizechange = false 323 | if p.size < 20 then 324 | p.size = 20 325 | sizechange = true 326 | end 327 | 328 | if p.size > 150 then 329 | local per = flr(p.size) / 150 330 | p.size -= per * per 331 | sizechange = true 332 | end 333 | 334 | local didsend = player_movement() 335 | update_mouse() 336 | 337 | if not didsend and sizechange then 338 | network_send(p) 339 | end 340 | 341 | --network stuff 342 | if need_send() then 343 | attempt_send() 344 | end 345 | attempt_read() 346 | --end network stuff 347 | 348 | local tick = stat(1) 349 | collisions = sweep(objtable) 350 | local tock = stat(1) 351 | sweep_time = tock-tick 352 | 353 | num_collisions = #collisions 354 | 355 | for pair in all(collisions) do 356 | agario_collide(pair[1],pair[2]) 357 | end 358 | 359 | --local mx = stat(32) 360 | --local my = stat(33) 361 | --local ms = stat(34) 362 | 363 | --[[if ms > last_ms then 364 | local results = query({x=mx,y=my,size=1}) 365 | if #results > 0 then 366 | selected = results[1] 367 | end 368 | elseif ms < last_ms then 369 | selected = nil 370 | end 371 | last_ms = ms 372 | 373 | 374 | if selected then 375 | local k = 0.0625 376 | selected.x += k*(mx-selected.x) 377 | selected.y += k*(my-selected.y) 378 | end]]-- 379 | 380 | --for h in all(hearts) do 381 | -- h.x = mid(h.r, h.x, 128-h.r) 382 | -- h.y = mid(h.r, h.y, 128-h.r) 383 | --end 384 | end 385 | 386 | function draw_mouse() 387 | line(mx-4,my,mx+4,my,7) 388 | line(mx,my-4,mx,my+4,7) 389 | end 390 | 391 | function draw_grid() 392 | for r = 128, map_size, 128 do 393 | line(r, 0, r, map_size, 5) 394 | line(0, r, map_size, r, 5) 395 | end 396 | end 397 | 398 | function _draw() 399 | if not gamestart then 400 | return 401 | end 402 | cls(0) 403 | palt(11) 404 | 405 | --draw_walls 406 | line(0,0,0,map_size,6) 407 | line(0,0,map_size,0,6) 408 | line(map_size,map_size,map_size,0,6) 409 | line(map_size,map_size,0,map_size,6) 410 | line(-4,-4,-4,map_size+4,8) 411 | line(-4,-4,map_size+4,-4,8) 412 | line(map_size+4,map_size+4,map_size+4,-4,8) 413 | line(map_size+4,map_size+4,-4,map_size+4,8) 414 | draw_grid() 415 | camera(cam_x,cam_y) 416 | 417 | local p = get_player() 418 | 419 | for k, h in pairs(objtable) do 420 | local n = 16+(16*(h.id%7)) 421 | local drawsize = h.size / 250 * max_player_size 422 | sspr(n,0,16,16,flr(h.x)-drawsize/2,flr(h.y)-drawsize/2,drawsize,drawsize) 423 | end 424 | 425 | draw_mouse() 426 | --if selected then 427 | -- local s = selected 428 | -- rect(s.x-s.size,s.y-s.size,s.x+s.size-1,s.y+s.size-1,7) 429 | --end 430 | 431 | --local mx,my = stat(32), stat(33) 432 | --local ms = stat(34)==1 and 1 or 17 433 | --line(mx-4,my,mx+4,my,7) 434 | --line(mx,my-4,mx,my+4,7) 435 | 436 | --print(cur_vx..","..cur_vy,cam_x+1,cam_y+1,7) 437 | --print(dx..","..dy,cam_x+1,cam_y+8,7) 438 | --print("%cpu: "..stat(1),cam_x+1,cam_y+1,7) 439 | --print("#col: "..num_collisions,cam_x+1,cam_y+7,7) 440 | --print(countstuff(),cam_x+1,cam_y+14,7) 441 | 442 | --color() 443 | --cursor(1, 24) 444 | --foreach(debug_log, print) 445 | debug_log = {} 446 | end 447 | 448 | function countstuff() 449 | local n = 0 450 | for k,v in pairs(objtable) do 451 | n += 1 452 | end 453 | return n 454 | end 455 | 456 | --begin network code 457 | outbound_queue = {} 458 | outbound_send = {} 459 | outbound_offset = 0 460 | 461 | _payload_size = 6 462 | 463 | _outbound_we = 0x5f84 464 | _outbound_num_payload = 0x5f85 465 | _outbound_payload = 0x5f86 466 | _outbound_max_payload = 5 467 | 468 | _inbound_we = _outbound_payload + _outbound_max_payload * _payload_size 469 | _inbound_num_payload = _inbound_we + 1 470 | _inbound_payload = _inbound_we + 2 471 | _inbound_max_payload = 15 472 | 473 | function network_send(obj) 474 | add(outbound_queue, obj) 475 | end 476 | 477 | function need_send() 478 | return #outbound_queue > 0 479 | end 480 | 481 | function attempt_send() 482 | local write_enabled = peek(_outbound_we) 483 | if write_enabled == 0 then 484 | --print("waiting to send") 485 | return 486 | end 487 | while (#outbound_send < _outbound_max_payload and #outbound_queue > 0) do 488 | local obj = outbound_queue[1] 489 | del(outbound_queue, obj) 490 | add(outbound_send, obj) 491 | end 492 | --payload number 493 | poke(_outbound_num_payload, #outbound_send) 494 | --payload 495 | outbound_offset = 0 496 | foreach(outbound_send, send_to_js) 497 | --disable write_enabled 498 | poke(_outbound_we, 0) 499 | --print("outbound sent!") 500 | end 501 | 502 | function send_to_js(obj) 503 | --id 504 | outbound_write(obj.id) 505 | --x 506 | outbound_write(flr(obj.x/256)) 507 | outbound_write(obj.x%256) 508 | --y 509 | outbound_write(flr(obj.y/256)) 510 | outbound_write(obj.y%256) 511 | --size 512 | outbound_write(obj.size) 513 | --remove from queue 514 | del(outbound_send, obj) 515 | end 516 | 517 | function outbound_write(byte) 518 | poke(_outbound_payload + outbound_offset, byte) 519 | outbound_offset += 1 520 | end 521 | 522 | function attempt_read() 523 | local write_enabled = peek(_inbound_we) 524 | if write_enabled == 1 then 525 | --print("waiting to read") 526 | return 527 | end 528 | local num = peek(_inbound_num_payload) 529 | for i = 0, num - 1 do 530 | local id = peek(_inbound_payload + i * _payload_size + 0) 531 | local x = peek(_inbound_payload + i * _payload_size + 1) * 256 + peek(_inbound_payload + i * _payload_size + 2) 532 | local y = peek(_inbound_payload + i * _payload_size + 3) * 256 + peek(_inbound_payload + i * _payload_size + 4) 533 | local size = peek(_inbound_payload + i * _payload_size + 5) 534 | if size == 0 then 535 | objtable["id"..id] = nil 536 | else 537 | local obj = create_obj(id, x, y, size) 538 | objtable["id"..id] = obj 539 | end 540 | end 541 | poke(_inbound_we, 1) 542 | end 543 | 544 | --end network code 545 | 546 | __gfx__ 547 | 00000000000000000000000bbbb0000000033bb3b000000000000000000000000000b33b300000000000033b33300000000004444440000000000bb33bb00000 548 | 000000000000000000000bbbbbbbb0000000bb003b00000000bb3bb0b333bb0000000300b3000000000333bb33b330000004444444444000000bb333333bb000 549 | 00700700000000000000bbbbbbbbbb0000000099b99000000b3beeebbeee3bb000000088388000000033b33b33b33b00004477777777440000bbbbb33bbbbb00 550 | 0007700000000000000bbbbbbbbbbbb0000999993999900000eeeee8eeeeee0000088888b88880000333bb3bb3377b3004477777777774400bbbbbbb3b77bbb0 551 | 000770000000000000bb2898228892bb0099999b3aa999000eeeeeee8eeeeee00088778887788800bb333bb3b33b7a334447767676767744bbbbbbbbbbb77bbb 552 | 007007000000000000b288888889882b0999999b9aaaa9900eeeeeee88eefee008877888877778803bb333bb3bbb3aa34477666666667744bbbbbbbbbbb7a7bb 553 | 0000000000000000022289aa88aa98829999999b99a77a908eeeeeeeee8eefee88888888887aa78033bbbb3bb3333aa34477766666666774bbbbbbbbbbbb7abb 554 | 0000000000000000002888a8888a889299999999999a7a998eeeeeeeee8eeffe888888888887aa883333b3bbbbb337a34477666666667774bbbbbbbbbbbb7a7b 555 | 0000000000000000002889888888888299999999999a7a9988eeeeeeee8eeffe8888888888877a88bbb33333b3bbb7a34476666666666774bbbbbbbbbbbb7a7b 556 | 00000000000000000028888989889882999999999999aa9988eeeeeeee8eefee88888888888877883333bb33b333b7734477666666667774bbbbbbbbbbbb7a7b 557 | 00000000000000000002898888888820999999999999aa9988eeeeeeee8effee8888888888887788333bb33b3b33337b4477766666666744bbbbbbbbbbb7aa7b 558 | 000000000000000000028898989892200999999999999a99088eeeeee8eefee8088888888888878803bb33b33bb33bb304476666666667440bbbbbbbbbb7a7bb 559 | 000000000000000000002888889888200999999999999990088eeeeee8eeee8008888888888888800bb33bb3b3b333b004477676767677400bbbbbbbbbbaa7b0 560 | 0000000000000000000002888888820000999999999999000088eeee8eeee80000888888888888000333bb33b3bbb33004447777777774400bbbbbbbbb7a7bb0 561 | 000000000000000000000028989820000009999999999000000888e8eeee800000088888888880000003b333b333b3000004447777744400000bbbbbb777bb00 562 | 000000000000000000000002288200000000999999990000000088888888000000008888888800000000033333330000000004444444000000000bbbbbbbb000 563 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 564 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 565 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 566 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 567 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 568 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 569 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 570 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 571 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 572 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 573 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 574 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 575 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 576 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 577 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 578 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 579 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 580 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 581 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 582 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 583 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 584 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 585 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 586 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 587 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 588 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 589 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 590 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 591 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 592 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 593 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 594 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 595 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 596 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 597 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 598 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 599 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 600 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 601 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 602 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 603 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 604 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 605 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 606 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 607 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 608 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 609 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 610 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 611 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 612 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 613 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 614 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 615 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 616 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 617 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 618 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 619 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 620 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 621 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 622 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 623 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 624 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 625 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 626 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 627 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 628 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 629 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 630 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 631 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 632 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 633 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 634 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 635 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 636 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 637 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 638 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 639 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 640 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 641 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 642 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 643 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 644 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 645 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 646 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 647 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 648 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 649 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 650 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 651 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 652 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 653 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 654 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 655 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 656 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 657 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 658 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 659 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 660 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 661 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 662 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 663 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 664 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 665 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 666 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 667 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 668 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 669 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 670 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 671 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 672 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 673 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 674 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 675 | 676 | __gff__ 677 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 678 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 679 | __map__ 680 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 681 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 682 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 683 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 684 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 685 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 686 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 687 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 688 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 689 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 690 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 691 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 692 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 693 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 694 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 695 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 696 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 697 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 698 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 699 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 700 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 701 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 702 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 703 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 704 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 705 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 706 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 707 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 708 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 709 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 710 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 711 | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 712 | __sfx__ 713 | 000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 714 | 010f00002226022260222602226022000180002200022000222602200022260222602026022260222601800022260222602226022260180001800018000180002226018000222602226020260222602226000000 715 | 010f00002226022260222602226018200192002426025261252612526122260222601800018000202602026020260202601e2601e26018000180001b2601b2601b2601b2601d2601d2601e2601e2601b2601b260 716 | 010f00000f0500f0500f0500f02000000000000f0500f0500f0500f02000000000000f0500f0500f0500f0200b0500b0500b0500b02000000000000b0500b0500b0500b02000000000000b0500b0500b0500b020 717 | 010f0000060500605006050060200000000000060500605006050060200000000000060500605006050060200a0500a0500a0500a02000000000000a0500a0500a0500a02000000000000a0500a0500a0500a020 718 | 010f00001b22022220222202222022220220002200018000220002222022000222202222020220222202222018000222202222022220222201800018000000000000022220180002222022220202202222022220 719 | 010f0000222002222022220222202222018200192002422025221252212522122220222201800018000202202022020220202201e2201e22018000180001b2201b2201b2201b2201d2201d2201e2201e2201b220 720 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 721 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 722 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 723 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 724 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 725 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 726 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 727 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 728 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 729 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 730 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 731 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 732 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 733 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 734 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 735 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 736 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 737 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 738 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 739 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 740 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 741 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 742 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 743 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 744 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 745 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 746 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 747 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 748 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 749 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 750 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 751 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 752 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 753 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 754 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 755 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 756 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 757 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 758 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 759 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 760 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 761 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 762 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 763 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 764 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 765 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 766 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 767 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 768 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 769 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 770 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 771 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 772 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 773 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 774 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 775 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 776 | 001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 777 | __music__ 778 | 01 01050344 779 | 02 02060444 780 | 00 41424344 781 | 00 41424344 782 | 00 41424344 783 | 00 41424344 784 | 00 41424344 785 | 00 41424344 786 | 00 41424344 787 | 00 41424344 788 | 00 41424344 789 | 00 41424344 790 | 00 41424344 791 | 00 41424344 792 | 00 41424344 793 | 00 41424344 794 | 00 41424344 795 | 00 41424344 796 | 00 41424344 797 | 00 41424344 798 | 00 41424344 799 | 00 41424344 800 | 00 41424344 801 | 00 41424344 802 | 00 41424344 803 | 00 41424344 804 | 00 41424344 805 | 00 41424344 806 | 00 41424344 807 | 00 41424344 808 | 00 41424344 809 | 00 41424344 810 | 00 41424344 811 | 00 41424344 812 | 00 41424344 813 | 00 41424344 814 | 00 41424344 815 | 00 41424344 816 | 00 41424344 817 | 00 41424344 818 | 00 41424344 819 | 00 41424344 820 | 00 41424344 821 | 00 41424344 822 | 00 41424344 823 | 00 41424344 824 | 00 41424344 825 | 00 41424344 826 | 00 41424344 827 | 00 41424344 828 | 00 41424344 829 | 00 41424344 830 | 00 41424344 831 | 00 41424344 832 | 00 41424344 833 | 00 41424344 834 | 00 41424344 835 | 00 41424344 836 | 00 41424344 837 | 00 41424344 838 | 00 41424344 839 | 00 41424344 840 | 00 41424344 841 | 00 41424344 842 | 843 | --------------------------------------------------------------------------------