/
RSPRover.cs
418 lines (358 loc) · 12.6 KB
/
RSPRover.cs
1
'From MIT Squeak 0.9.4 (June 1, 2003) [No updates present.] on 30 August 2016 at 6:59:49 pm'!"Change Set: RSPRoverDate: 27 August 2016Author: EiichiroItoThis is change file of RSPRover(Remote Sensor Protocol Rover) program"!Object subclass: #Base64Decoder instanceVariableNames: 'out in ' classVariableNames: 'DecoderTable ' poolDictionaries: '' category: 'Decoder-Base64'!Object subclass: #Base64Encoder instanceVariableNames: 'out in count ' classVariableNames: 'DecoderTable EncoderTable ' poolDictionaries: '' category: 'Decoder-Base64'!Object subclass: #ScratchServer instanceVariableNames: 'stage userName serverSocket incomingUDPSocket peerSockets peerNames sensors lastSentValues incomingBroadcasts outgoingBroadcasts in broadcastCache imageForm ' classVariableNames: '' poolDictionaries: '' category: 'Scratch-Networking'!!Base64Decoder methodsFor: 'private' stamp: 'EiichiroIto 8/27/2016 10:00'!decode | t1 t2 t3 t4 t5 t6 t7 t8 | [true] whileTrue: [t1 _ self next. t1 ifNil: [^ self]. t2 _ self next. t2 ifNil: [^ self]. t5 _ self class decoderTable at: t1. t6 _ self class decoderTable at: t2. self put: (t5 << 2 bitOr: t6 >> 4). t3 _ self next. t3 ifNil: [^ self]. t7 _ self class decoderTable at: t3. self put: ((t6 bitAnd: 15) << 4 bitOr: t7 >> 2). t4 _ self next. t4 ifNil: [^ self]. t8 _ self class decoderTable at: t4. self put: ((t7 bitAnd: 3) << 6 bitOr: t8)]! !!Base64Decoder methodsFor: 'private' stamp: 'EiichiroIto 8/27/2016 10:00'!next | t1 | in atEnd ifTrue: [^ nil]. t1 _ in next. t1 = $= ifTrue: [^ nil]. ^ t1! !!Base64Decoder methodsFor: 'private' stamp: 'EiichiroIto 8/27/2016 10:00'!put: t1 out nextPut: t1! !!Base64Decoder methodsFor: 'accessing' stamp: 'EiichiroIto 8/27/2016 10:00'!decode: t1 in _ ReadStream on: t1. out _ WriteStream on: ByteArray new. self decode. ^ out contents! !!Base64Decoder class methodsFor: 'initialization' stamp: 'EiichiroIto 8/27/2016 10:00'!initialize DecoderTable _ nil! !!Base64Decoder class methodsFor: 'private' stamp: 'EiichiroIto 8/27/2016 10:00'!defaultDecoderTable ^ Dictionary newFrom: ('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' asArray withIndexCollect: [:t1 :t2 | t1 -> (t2 - 1)])! !!Base64Decoder class methodsFor: 'accessing' stamp: 'EiichiroIto 8/27/2016 10:00'!decoderTable ^ DecoderTable ifNil: [DecoderTable _ self defaultDecoderTable]! !!Base64Encoder methodsFor: 'private' stamp: 'EiichiroIto 8/27/2016 10:00'!encode | t1 t2 | [true] whileTrue: [t1 _ self next. t1 ifNil: [^ self]. t2 _ t1 >> 2. self put: (self class encoderTable at: t2 + 1). t2 _ (t1 bitAnd: 3) << 4. t1 _ self next. t1 ifNil: [^ self put: (self class encoderTable at: t2 + 1)]. t2 _ t2 bitOr: t1 >> 4. self put: (self class encoderTable at: t2 + 1). t2 _ (t1 bitAnd: 15) << 2. t1 _ self next. t1 ifNil: [^ self put: (self class encoderTable at: t2 + 1)]. t2 _ t2 bitOr: t1 >> 6. self put: (self class encoderTable at: t2 + 1). t2 _ t1 bitAnd: 63. self put: (self class encoderTable at: t2 + 1)]! !!Base64Encoder methodsFor: 'private' stamp: 'EiichiroIto 8/27/2016 10:00'!next in atEnd ifTrue: [^ nil]. ^ in next! !!Base64Encoder methodsFor: 'private' stamp: 'EiichiroIto 8/27/2016 10:00'!put: t1 out nextPut: t1. count _ count + 1 \\ 4! !!Base64Encoder methodsFor: 'accessing' stamp: 'EiichiroIto 8/27/2016 10:00'!encode: t1 in _ ReadStream on: t1. out _ WriteStream on: String new. count _ 0. self encode. count > 0 ifTrue: [4 - count timesRepeat: [self put: $=]]. ^ out contents! !!Base64Encoder class methodsFor: 'initialization' stamp: 'EiichiroIto 8/27/2016 10:00'!initialize EncoderTable _ nil! !!Base64Encoder class methodsFor: 'accessing' stamp: 'EiichiroIto 8/27/2016 10:00'!encoderTable ^ EncoderTable ifNil: [EncoderTable _ self defaultEncoderTable]! !!Base64Encoder class methodsFor: 'private' stamp: 'EiichiroIto 8/27/2016 10:00'!defaultEncoderTable ^ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' asArray! !!ScratchFrameMorph methodsFor: 'intialization' stamp: 'EiichiroIto 8/30/2016 18:54'!createMenuPanel "Create and add a panel containing the menus and close button." | menuSpecs m | "create panel" menuPanel _ AlignmentMorph new color: Color transparent; centering: #center; inset: 0; height: 0. "will grow as needed" self addShortcutButtonsTo: menuPanel. "menuSpecs defines the menus" menuSpecs _ #( "name selector" (File fileMenu:) (Edit editMenu:) (Share shareMenu:) (Help helpMenu:) ). menuSpecs do: [:spec | m _ ScratchMenuTitleMorph new contents: (spec at: 1) localized; target: self selector: (spec at: 2). menuPanel addMorphBack: m. #helpMenu: = (spec at: 2) ifFalse: [ menuPanel addMorphBack: (Morph new color: Color transparent; extent: 12@5)]]. topPane addMorph: menuPanel.! !!ScratchFrameMorph methodsFor: 'menu/button actions' stamp: 'EiichiroIto 8/30/2016 18:54'!addServerCommandsTo: menu "Add Scratch server commands to the given menu." | disable endCmd | disable _ false. "make this true to disable this feature" disable ifTrue: [^ self]. menu addLine. (workPane scratchServer notNil and: [workPane scratchServer sessionInProgress]) ifTrue: [ menu add: 'Show IP Address' action: #showNetworkAddress. endCmd _ workPane scratchServer isHosting ifTrue: ['Stop Hosting Mesh'] ifFalse: ['Leave Mesh']. menu add: endCmd action: #exitScratchSession] ifFalse: [ menu add: 'Host Mesh' action: #startHostingScratchSession. menu add: 'Join Mesh' action: #joinScratchSession].! !!ScratchFrameMorph methodsFor: 'menu/button actions' stamp: 'EiichiroIto 8/27/2016 19:07'!shareMenu: aMenuTitleMorph | menu | menu _ CustomMenu new. self addServerCommandsTo: menu. menu localize. menu invokeOn: self at: aMenuTitleMorph bottomLeft + (0 @ 10)! !!ScratchServer methodsFor: 'accessing' stamp: 'EiichiroIto 8/30/2016 18:54'!imageForm ^ imageForm! !!ScratchServer methodsFor: 'private-incoming commands' stamp: 'EiichiroIto 8/30/2016 18:54'!dispatch: aString from: requestSock "Dispatch an incoming command from a remote Scratch." | cmd op | aString size = 0 ifTrue: [ requestSock sendMessage: 'version "ScratchServer 2.0 alpha"'. ^ self]. op _ self opcodeFrom: aString. op size = 0 ifTrue: [^ self]. (#('broadcast' 'sensor-update' 'peer-name' 'send-vars' 'jpg' 'gif' 'png') includes: op) ifFalse: [^ self]. cmd _ self parse: aString. 'broadcast' = op ifTrue: [ self doBroadcast: cmd from: requestSock. ^ self resend: aString toPeersExcept: requestSock]. 'sensor-update' = op ifTrue: [ self doSensorUpdate: cmd from: requestSock. ^ self resend: aString toPeersExcept: requestSock]. 'peer-name' = op ifTrue: [^ self doPeerName: cmd from: requestSock]. 'send-vars' = op ifTrue: [ self doSendVars: cmd from: requestSock. ^ self resend: aString toPeersExcept: requestSock]. 'jpg' = op ifTrue: [ self doJpg: cmd from: requestSock. ^ self resend: aString toPeersExcept: requestSock]. 'gif' = op ifTrue: [ self doGif: cmd from: requestSock. ^ self resend: aString toPeersExcept: requestSock]. 'png' = op ifTrue: [ self doPng: cmd from: requestSock. ^ self resend: aString toPeersExcept: requestSock].! !!ScratchServer methodsFor: 'private-incoming commands' stamp: 'EiichiroIto 8/30/2016 18:54'!doGif: cmd from: requestSocket | b64Data rawData | cmd size = 2 ifFalse: [^ self]. ((b64Data _ cmd at: 2) isKindOf: String) ifFalse: [^ self]. rawData _ Base64Decoder new decode: b64Data. imageForm _ (GIFReadWriter on: (ReadStream on: rawData)) nextImage. incomingBroadcasts removeAllSuchThat: [:each | each = 'photoReceived']. incomingBroadcasts add: 'photoReceived'! !!ScratchServer methodsFor: 'private-incoming commands' stamp: 'EiichiroIto 8/30/2016 18:54'!doJpg: cmd from: requestSocket | b64Data rawData | cmd size = 2 ifFalse: [^ self]. ((b64Data _ cmd at: 2) isKindOf: String) ifFalse: [^ self]. rawData _ Base64Decoder new decode: b64Data. imageForm _ FastJPEG uncompress: rawData. incomingBroadcasts removeAllSuchThat: [:each | each = 'photoReceived']. incomingBroadcasts add: 'photoReceived'! !!ScratchServer methodsFor: 'private-incoming commands' stamp: 'EiichiroIto 8/30/2016 18:54'!doPng: cmd from: requestSocket | b64Data rawData | cmd size = 2 ifFalse: [^ self]. ((b64Data _ cmd at: 2) isKindOf: String) ifFalse: [^ self]. rawData _ Base64Decoder new decode: b64Data. imageForm _ (PNGReadWriter on: (ReadStream on: rawData)) nextImage. incomingBroadcasts removeAllSuchThat: [:each | each = 'photoReceived']. incomingBroadcasts add: 'photoReceived'! !!ScriptableScratchMorph methodsFor: 'looks ops' stamp: 'EiichiroIto 8/30/2016 18:42'!deleteCostume self deleteMedia: costume! !!ScriptableScratchMorph methodsFor: 'looks ops' stamp: 'EiichiroIto 8/30/2016 18:42'!duplicateCostume self duplicateMedia: costume. self lookLike: media last! !!ScriptableScratchMorph methodsFor: 'looks ops' stamp: 'EiichiroIto 8/30/2016 18:43'!numCostumes ^ (media reject: [:each | each isSound]) size! !!ScriptableScratchMorph methodsFor: 'looks ops' stamp: 'EiichiroIto 8/30/2016 18:43'!prevCostume self costumeIndex: self costumeIndex - 1! !!ScriptableScratchMorph methodsFor: 'looks ops' stamp: 'EiichiroIto 8/30/2016 18:54'!setReceivedPhoto | form | owner scratchServer ifNil: [^ self]. form _ owner scratchServer imageForm. form ifNil: [^ self]. costume form: form. self costumeChanged! !!ScratchSpriteMorph class methodsFor: 'block specs' stamp: 'EiichiroIto 8/30/2016 18:54'!blockSpecs | blocks | blocks _ #( 'motion' ('move %n steps' - forward:) ('turn %n degrees' - turnRight: 15) "icon shows turn direction" ('turn %n degrees' - turnLeft: 15) "icon shows turn direction" - ('point in direction %d' - heading: 90) ('point towards %m' - pointTowards:) - ('go to x:%n y:%n' - gotoX:y: 0 0) ('go to %m' - gotoSpriteOrMouse:) ('glide %n secs to x:%n y:%n' t glideSecs:toX:y:elapsed:from: 1 50 50) - ('change x by %n' - changeXposBy: 10) ('set x to %n' - xpos: 0) ('change y by %n' - changeYposBy: 10) ('set y to %n' - ypos: 0) - ('if on edge, bounce' - bounceOffEdge) - ('x position' r xpos) ('y position' r ypos) ('direction' r heading) 'pen' ('clear' - clearPenTrails) - ('pen down' - putPenDown) ('pen up' - putPenUp) - ('set pen color to %c' - penColor:) ('change pen color by %n' - changePenHueBy:) ('set pen color to %n' - setPenHueTo: 0) - ('change pen shade by %n' - changePenShadeBy:) ('set pen shade to %n' - setPenShadeTo: 50) - ('change pen size by %n' - changePenSizeBy: 1) ('set pen size to %n' - penSize: 1) - ('stamp' - stampCostume) ). blocks _ blocks, #( 'looks' ('switch to costume %l' - lookLike:) ('next costume' - nextCostume) ('previous costume' - prevCostume) ('costume #' r costumeIndex) ('set received photo' - setReceivedPhoto) ('number of costumes' r numCostumes) ('duplicate costume' - duplicateCostume) ('delete costume' - deleteCostume) - ('say %s for %n secs' t say:duration:elapsed:from: 'Hello!!' 2) ('say %s' - say: 'Hello!!') ('think %s for %n secs' t think:duration:elapsed:from: 'Hmm...' 2) ('think %s' - think: 'Hmm...') - ('change %g effect by %n' - changeGraphicEffect:by: 'color' 25) ('set %g effect to %n' - setGraphicEffect:to: 'color' 0) ('clear graphic effects' - filterReset) - ('change size by %n' - changeSizeBy:) ('set size to %n%' - setSizeTo: 100) ('size' r scale) - ('show' - show) ('hide' - hide) - ('go to front' - comeToFront) ('go back %n layers' - goBackByLayers: 1) 'sensing' ('touching %m?' b touching:) ('touching color %C?' b touchingColor:) ('color %C is touching %C?' b color:sees:) - ('ask %s and wait' s doAsk 'What''s your name?') ('answer' r answer) - ('mouse x' r mouseX) ('mouse y' r mouseY) ('mouse down?' b mousePressed) - ('key %k pressed?' b keyPressed: 'space') - ('distance to %m' r distanceTo:) - ('reset timer' - timerReset) ('timer' r timer) - ('%a of %m' r getAttribute:of:) - ('loudness' r soundLevel) ('loud?' b isLoud) ~ ('%H sensor value' r sensor: 'slider') ('sensor %h?' b sensorPressed: 'button pressed') ). ^ blocks, super blockSpecs! !Base64Encoder initialize!Base64Decoder initialize!