Here is a simple server in Python that will connect a number of Scratch workstations together in a single network. They will all share broadcasts with each other and variables. No extra software is required on the workstations, but you need to know their IP address and they need to Enable Sensors on the machines in order for the connection to work. Some students used this to develop some network games. They discovered a hack to keep variables local: lists are not shared on the network, so if you want to keep a bunch of variables local, just create a list and access the variables as item X of the list.
If you find yourself continually connecting to the same machines, you can create a conf file (see comments in the code) and pass that as an arg to the server when starting it.
#!/usr/bin/python
# Scratch server
# Copyright (C) 2010 ken restivo <ken aaattt restivo.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# based on ideas from
# Scratch Multiplayer Socket Server Demo
# http://scratchconnections.wik.is/Projects/Two-player_Network_Pong
#
# version 5.1.1 (Jul-31-2009)
# by Stefano Federici (on Scratch: "s_federici", email: federici.stefano@gmail.com)
#
# version 5.1 (Oct-16-2008)
# by Agnes Chang (on Scratch: "kradeki", email: kradeki@gmail.com)
#
#
# To add machines to connect to at startup, create a conf file and pass it
# in as an argument to the program.
# conf files have the format:
#
# [machines]
# 127.0.0.1: 42001
# 192.167.80.5: 42001
#
from array import array
import socket
import time
import thread
import ConfigParser
import sys
import os
#####################
class ScratchServer:
machines = [['127.0.0.1', 42001, None],
#['127.0.0.1', 42002, None]
]
log = False
BUFSIZE = 4096
config = None
def __init__(self):
return
def start(self):
for i in xrange(len(self.machines)):
thread.start_new_thread(self.clientThread, (i,))
print "threads spawned"
def clientThread(self,i):
data = None
while 1:
s = None
print("connecting to %s on %s..." %(
self.machines[i][0],
self.machines[i][1]))
while self.machines[i][2] == None:
try:
s = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
s.connect((self.machines[i][0],
self.machines[i][1]))
self.machines[i][2] = s
except socket.error:
time.sleep(30)
print("connected to %s on %s..." %(self.machines[i][0],
self.machines[i][1]))
while 1:
try:
data = s.recv(self.BUFSIZE)
except socket.error:
self.machines[i][2] = None
if not data: break
if self.log == True:
print("received from %s (%s) >> %s" % (
self.machines[i][0],
self.machines[i][1],
data[4:]))
self.send_to_except(data, i)
s.close()
self.machines[i][2] = None
time.sleep(30)
def build_command(self,cmd):
n = len(cmd)
a = array('c')
a.append(chr((n >> 24) & 0xFF))
a.append(chr((n >> 16) & 0xFF))
a.append(chr((n >> 8) & 0xFF))
a.append(chr(n & 0xFF))
return a.tostring() + cmd
def send_to_except(self, fmt_cmd, mine):
for i in xrange(len(self.machines)):
if self.machines[i][2] != None and mine != i:
try:
self.machines[i][2].send(fmt_cmd)
except socket.error:
self.machines[i][2].close()
self.machines[i][2] = None
def send_signal(self, broadcast):
self.send_to_except(self.build_command('broadcast "%s"' % (
str(broadcast))),
-1)
if self.log == True:
print '"' + broadcast + '" has been broadcasted.'
def send_sensor(self, updateN, updateV):
self.send_to_except(
self.build_command('sensor-update "%s" "%s"' % (
str(updateN), str(updateV))),
-1)
print '"' + updateN + '" has been updated to "' + updateV + '"'
def add_machine(self, addr, port):
for i in self.machines:
if self.machines[0] == addr and self.machines[1] == port:
print "machine %s at %s is already added" % (
addr, port)
return
self.machines.append([addr, port, None])
thread.start_new_thread(self.clientThread,
(len(self.machines)-1,))
def stop(self):
print "closing connections..."
for i in xrange(len(self.machines)):
if self.machines[i][2] != None:
self.machines[i][2].close()
def parse_config(self, filename):
try:
self.config = ConfigParser.ConfigParser()
self.config.read(filename)
for i in self.config.options('machines'):
self.add_machine(i,
int(self.config.get(
'machines', i)))
except ConfigParser.MissingSectionHeaderError:
print "your conf file %s is not correctly written" % (
filename)
sys.exit(1)
##########################
class ScratchServerUI:
server = None
def __init__(self):
self.server = ScratchServer()
return
def send_signal(self):
broadcast = raw_input("Broadcast: ")
if broadcast == None or broadcast == '':
return
self.server.send_signal(broadcast)
def send_sensor(self):
updateN = raw_input("Sensor Name: ")
if updateN == None or updateN == '':
return
updateV = raw_input("Sensor Value: ")
self.server.send_sensor(updateN, updateV)
def add_machine(self):
addr = raw_input("Hostname or IP address: ")
if addr == None or addr == '':
return
port = raw_input("Port: (default 42001 ")
try:
p=int(port)
except ValueError:
p=42001
self.server.add_machine(addr, int(p))
def list_machines(self):
print "Machines and connections"
print "--- Num Address Port Status ---"
for i in xrange(len(self.server.machines)):
m=self.server.machines[i]
if m[2] == None:
status = "connecting..."
else:
status = "CONNECTED"
print("--- #%d. %s (%s) => %s" % (i, m[0],
m[1], status))
def menu(self):
print """1) broadcast signal
2) set sensor variable
3) connect to a machine
4) list machines
5) toggle logging (currently %s)
0) quit""" % (self.server.log)
def parse_config(self):
try:
filename=sys.argv[1]
except IndexError:
return
if os.path.isfile(filename) == False:
print """file '%s' does not exist.
either start without a conf file, or supply an actual file""" % (
filename)
sys.exit()
print "using config file %s..." % (filename)
self.server.parse_config(filename)
def main_loop(self):
while 1:
self.menu()
command = raw_input("Command (0-4): ")
if command == "1":
self.send_signal()
elif command == "2":
self.send_sensor()
elif command == "3":
self.add_machine()
elif command == "4":
self.list_machines()
elif command == "5":
self.server.log = not self.server.log
elif command == "0":
self.server.stop()
print "quitting..."
exit()
else:
print '"%s" is not a valid command.' % (command)
def run(self):
self.parse_config()
self.server.start()
self.main_loop()
#################
# MAIN
ui = ScratchServerUI()
ui.run()Offline
johnnydean1 wrote:
*butp*
Bring up this post?
Offline
this should be stickied!
<when green flag clicked>
<{ I HAVE NOT DONE THIS ONLINE BLOCK THING IN LONG TIME }>
Offline
Interesting, just like Mesh. Maybe I'll try this out later.
Offline
So this would be a server?
Once you get a host, would mesh games be able to support more than 2 players on the server?


Offline