diff --git a/Makefile b/Makefile index a4934f9..eb5bf0f 100644 --- a/Makefile +++ b/Makefile @@ -26,6 +26,7 @@ endif clean: rm -rf $(BEAMDIR)/*.beam ; + rm -rf $(SRCDIR)/*.beam ; rm -rf erl_crush.dump ; echo "==> clean ggs" ; $(MAKE) -C erlang_js/ clean diff --git a/games/Pong/Classes/GGSNetwork.m b/games/Pong/Classes/GGSNetwork.m index a436f13..7b68fdc 100644 --- a/games/Pong/Classes/GGSNetwork.m +++ b/games/Pong/Classes/GGSNetwork.m @@ -11,7 +11,7 @@ @implementation GGSNetwork -#define GGS_HOST @"jeena.net" +#define GGS_HOST @"localhost" #define GGS_PORT 9000 #define NO_TIMEOUT -1 @@ -32,7 +32,7 @@ @synthesize asyncSocket, delegate, gameToken, currentHeaders; - (id)initWithDelegate:(id)_delegate { - if (self = [super init]) { + if ((self = [super init])) { delegate = _delegate; asyncSocket = [[AsyncSocket alloc] initWithDelegate:self]; diff --git a/games/Pong/Pong.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/games/Pong/Pong.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..2c44ce8 --- /dev/null +++ b/games/Pong/Pong.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/games/Pong/Pong.xcodeproj/project.xcworkspace/xcuserdata/jeena.xcuserdatad/UserInterfaceState.xcuserstate b/games/Pong/Pong.xcodeproj/project.xcworkspace/xcuserdata/jeena.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..b1bf0bc --- /dev/null +++ b/games/Pong/Pong.xcodeproj/project.xcworkspace/xcuserdata/jeena.xcuserdatad/UserInterfaceState.xcuserstate @@ -0,0 +1,3044 @@ + + + + + $archiver + NSKeyedArchiver + $objects + + $null + + $class + + CF$UID + 184 + + NS.keys + + + CF$UID + 2 + + + CF$UID + 3 + + + NS.objects + + + CF$UID + 4 + + + CF$UID + 112 + + + + IDEWorkspaceDocument + C791B696-0817-4083-8D95-684ACD41BA88 + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 5 + + + CF$UID + 6 + + + CF$UID + 7 + + + CF$UID + 8 + + + CF$UID + 9 + + + CF$UID + 10 + + + CF$UID + 11 + + + CF$UID + 12 + + + CF$UID + 13 + + + CF$UID + 14 + + + NS.objects + + + CF$UID + 15 + + + CF$UID + 16 + + + CF$UID + 57 + + + CF$UID + 58 + + + CF$UID + 63 + + + CF$UID + 66 + + + CF$UID + 100 + + + CF$UID + 101 + + + CF$UID + 15 + + + CF$UID + 15 + + + + BreakpointsActivated + DefaultEditorStatesForURLs + DebuggingWindowBehavior + ActiveRunDestination + ActiveScheme + LastCompletedPersistentSchemeBasedActivityReport + DocumentWindows + RecentEditorDocumentURLs + AppFocusInMiniDebugging + MiniDebuggingConsole + + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 17 + + + NS.objects + + + CF$UID + 18 + + + + Xcode.IDEKit.EditorDocument.SourceCode + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 19 + + + CF$UID + 23 + + + CF$UID + 25 + + + CF$UID + 27 + + + CF$UID + 29 + + + NS.objects + + + CF$UID + 31 + + + CF$UID + 40 + + + CF$UID + 47 + + + CF$UID + 51 + + + CF$UID + 54 + + + + + $class + + CF$UID + 22 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 20 + + + + $class + + CF$UID + 21 + + NS.string + file://localhost/Users/jeena/Student/GGS/games/Pong/Classes/GGSNetwork.h + + + $classes + + NSMutableString + NSString + NSObject + + $classname + NSMutableString + + + $classes + + NSURL + NSObject + + $classname + NSURL + + + $class + + CF$UID + 22 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 24 + + + + $class + + CF$UID + 21 + + NS.string + file://localhost/Users/jeena/Student/GGS/games/Pong/Classes/PongViewController.m + + + $class + + CF$UID + 22 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 26 + + + + $class + + CF$UID + 21 + + NS.string + file://localhost/Users/jeena/Student/GGS/games/Pong/Classes/GGSNetwork.m + + + $class + + CF$UID + 22 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 28 + + + + $class + + CF$UID + 21 + + NS.string + file://localhost/Users/jeena/Student/GGS/games/Pong/Classes/PongAppDelegate.m + + + $class + + CF$UID + 22 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 30 + + + + $class + + CF$UID + 21 + + NS.string + file://localhost/Users/jeena/Student/GGS/games/Pong/Classes/PongAppDelegate.h + + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 32 + + + CF$UID + 33 + + + CF$UID + 34 + + + CF$UID + 35 + + + NS.objects + + + CF$UID + 36 + + + CF$UID + 37 + + + CF$UID + 15 + + + CF$UID + 38 + + + + PrimaryDocumentTimestamp + PrimaryDocumentVisibleCharacterRange + HideAllIssues + PrimaryDocumentSelectedCharacterRange + 322646167.29056698 + {0, 910} + {0, 0} + + $classes + + NSMutableDictionary + NSDictionary + NSObject + + $classname + NSMutableDictionary + + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 41 + + + CF$UID + 42 + + + CF$UID + 43 + + + CF$UID + 44 + + + NS.objects + + + CF$UID + 45 + + + CF$UID + 46 + + + CF$UID + 15 + + + CF$UID + 38 + + + + PrimaryDocumentTimestamp + PrimaryDocumentVisibleCharacterRange + HideAllIssues + PrimaryDocumentSelectedCharacterRange + 324225931.14446598 + {362, 1156} + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 32 + + + CF$UID + 33 + + + CF$UID + 34 + + + CF$UID + 35 + + + NS.objects + + + CF$UID + 48 + + + CF$UID + 49 + + + CF$UID + 15 + + + CF$UID + 50 + + + + 324221134.73035002 + {506, 1336} + {2711, 5} + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 32 + + + CF$UID + 33 + + + CF$UID + 34 + + + CF$UID + 35 + + + NS.objects + + + CF$UID + 52 + + + CF$UID + 53 + + + CF$UID + 15 + + + CF$UID + 38 + + + + 324221136.37834799 + {1697, 1040} + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 32 + + + CF$UID + 33 + + + CF$UID + 34 + + + CF$UID + 35 + + + NS.objects + + + CF$UID + 55 + + + CF$UID + 56 + + + CF$UID + 15 + + + CF$UID + 38 + + + + 322646160.93821901 + {0, 455} + 0 + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 59 + + + CF$UID + 60 + + + NS.objects + + + CF$UID + 61 + + + CF$UID + 62 + + + + IDEDeviceLocation + IDEDeviceArchitecture + dvtdevice-iphonesimulator:/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.0.sdk-iPhone + i386 + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 64 + + + NS.objects + + + CF$UID + 65 + + + + IDENameString + Pong + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 67 + + + CF$UID + 68 + + + CF$UID + 69 + + + NS.objects + + + CF$UID + 70 + + + CF$UID + 98 + + + CF$UID + 99 + + + + IDEActivityReportCompletionSummaryStringSegments + IDEActivityReportOptions + IDEActivityReportTitle + + $class + + CF$UID + 97 + + NS.objects + + + CF$UID + 71 + + + CF$UID + 78 + + + CF$UID + 82 + + + CF$UID + 87 + + + + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 72 + + + CF$UID + 73 + + + CF$UID + 74 + + + NS.objects + + + CF$UID + 75 + + + CF$UID + 76 + + + CF$UID + 77 + + + + IDEActivityReportStringSegmentPriority + IDEActivityReportStringSegmentBackSeparator + IDEActivityReportStringSegmentStringValue + 2 + + Build + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 72 + + + CF$UID + 73 + + + CF$UID + 74 + + + NS.objects + + + CF$UID + 79 + + + CF$UID + 80 + + + CF$UID + 81 + + + + 4 + : + Pong + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 72 + + + CF$UID + 73 + + + CF$UID + 74 + + + NS.objects + + + CF$UID + 83 + + + CF$UID + 84 + + + CF$UID + 85 + + + + 1 + + + $class + + CF$UID + 86 + + NS.data + + YnBsaXN0MDDUAQIDBAUGOzxYJHZlcnNpb25YJG9iamVjdHNZJGFy + Y2hpdmVyVCR0b3ASAAGGoK0HCA8QGhscJCUrMTQ3VSRudWxs0wkK + CwwNDlxOU0F0dHJpYnV0ZXNWJGNsYXNzWE5TU3RyaW5ngAOADIAC + WVN1Y2NlZWRlZNMKERITFBdXTlMua2V5c1pOUy5vYmplY3RzgAui + FRaABIAFohgZgAaACVZOU0ZvbnRXTlNDb2xvctQKHR4fICEiI1ZO + U05hbWVWTlNTaXplWE5TZkZsYWdzgAiAByNAJgAAAAAAABENEF8Q + EUx1Y2lkYUdyYW5kZS1Cb2xk0iYnKClaJGNsYXNzbmFtZVgkY2xh + c3Nlc1ZOU0ZvbnSiKCpYTlNPYmplY3TTCiwtLi8wXE5TQ29sb3JT + cGFjZVdOU1doaXRlgAoQA0IwANImJzIzV05TQ29sb3KiMirSJic1 + NlxOU0RpY3Rpb25hcnmiNSrSJic4OV8QEk5TQXR0cmlidXRlZFN0 + cmluZ6I6Kl8QEk5TQXR0cmlidXRlZFN0cmluZ18QD05TS2V5ZWRB + cmNoaXZlctE9PlRyb290gAEACAARABoAIwAtADIANwBFAEsAUgBf + AGYAbwBxAHMAdQB/AIYAjgCZAJsAngCgAKIApQCnAKkAsAC4AMEA + yADPANgA2gDcAOUA6AD8AQEBDAEVARwBHwEoAS8BPAFEAUYBSAFL + AVABWAFbAWABbQFwAXUBigGNAaIBtAG3AbwAAAAAAAACAQAAAAAA + AAA/AAAAAAAAAAAAAAAAAAABvg== + + + + $classes + + NSMutableData + NSData + NSObject + + $classname + NSMutableData + + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 72 + + + CF$UID + 88 + + + CF$UID + 89 + + + CF$UID + 74 + + + CF$UID + 90 + + + CF$UID + 91 + + + NS.objects + + + CF$UID + 92 + + + CF$UID + 93 + + + CF$UID + 94 + + + CF$UID + 96 + + + CF$UID + 93 + + + CF$UID + 93 + + + + IDEActivityReportStringSegmentType + IDEActivityReportStringSegmentDate + IDEActivityReportStringSegmentDateStyle + IDEActivityReportStringSegmentTimeStyle + 3 + 1 + + $class + + CF$UID + 95 + + NS.time + 324225926.14380801 + + + $classes + + NSDate + NSObject + + $classname + NSDate + + Today at 16:45 + + $classes + + NSMutableArray + NSArray + NSObject + + $classname + NSMutableArray + + 106 + Pong + + $class + + CF$UID + 97 + + NS.objects + + + CF$UID + 3 + + + + + $class + + CF$UID + 97 + + NS.objects + + + CF$UID + 102 + + + CF$UID + 104 + + + CF$UID + 106 + + + CF$UID + 108 + + + CF$UID + 110 + + + + + $class + + CF$UID + 22 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 103 + + + file://localhost/Users/jeena/Student/GGS/games/Pong/Classes/PongViewController.m + + $class + + CF$UID + 22 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 105 + + + file://localhost/Users/jeena/Student/GGS/games/Pong/Classes/PongAppDelegate.m + + $class + + CF$UID + 22 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 107 + + + file://localhost/Users/jeena/Student/GGS/games/Pong/Classes/GGSNetwork.m + + $class + + CF$UID + 22 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 109 + + + file://localhost/Users/jeena/Student/GGS/games/Pong/Classes/GGSNetwork.h + + $class + + CF$UID + 22 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 111 + + + file://localhost/Users/jeena/Student/GGS/games/Pong/Classes/PongAppDelegate.h + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 113 + + + CF$UID + 114 + + + CF$UID + 115 + + + CF$UID + 116 + + + CF$UID + 117 + + + CF$UID + 118 + + + NS.objects + + + CF$UID + 119 + + + CF$UID + 285 + + + CF$UID + 219 + + + CF$UID + 113 + + + CF$UID + 286 + + + CF$UID + 3 + + + + IDEWorkspaceTabController_C37A21B0-D59C-4189-B137-7086EEE960F1 + IDEOrderedWorkspaceTabControllers + IDEWindowToolbarIsVisible + IDEActiveWorkspaceTabController + IDEWindowFrame + IDEWorkspaceWindowControllerUniqueIdentifier + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 120 + + + CF$UID + 121 + + + CF$UID + 122 + + + CF$UID + 123 + + + CF$UID + 124 + + + CF$UID + 125 + + + CF$UID + 126 + + + CF$UID + 127 + + + NS.objects + + + CF$UID + 128 + + + CF$UID + 219 + + + CF$UID + 57 + + + CF$UID + 229 + + + CF$UID + 236 + + + CF$UID + 275 + + + CF$UID + 15 + + + CF$UID + 284 + + + + IDEEditorArea + IDEShowNavigator + AssistantEditorsLayout + IDEWorkspaceTabControllerUtilityAreaSplitView + IDENavigatorArea + IDEWorkspaceTabControllerDesignAreaSplitView + IDEShowUtilities + IDETabLabel + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 129 + + + CF$UID + 130 + + + CF$UID + 131 + + + CF$UID + 132 + + + CF$UID + 133 + + + CF$UID + 134 + + + CF$UID + 135 + + + CF$UID + 136 + + + NS.objects + + + CF$UID + 137 + + + CF$UID + 157 + + + CF$UID + 190 + + + CF$UID + 219 + + + CF$UID + 57 + + + CF$UID + 220 + + + CF$UID + 228 + + + CF$UID + 219 + + + + layoutTree + IDEEditorMode_Standard + IDEEDitorArea_DebugArea + IDEShowEditor + EditorMode + DebuggerSplitView + DefaultPersistentRepresentations + ShowDebuggerArea + + $class + + CF$UID + 156 + + geniusEditorContextNode + + CF$UID + 0 + + primaryEditorContextNode + + CF$UID + 138 + + rootLayoutTreeNode + + CF$UID + 153 + + + + $class + + CF$UID + 155 + + children + + CF$UID + 0 + + contentType + 1 + documentArchivableRepresentation + + CF$UID + 139 + + orientation + 0 + parent + + CF$UID + 153 + + + + $class + + CF$UID + 152 + + DocumentLocation + + CF$UID + 150 + + DomainIdentifier + + CF$UID + 140 + + IdentifierPath + + CF$UID + 141 + + IndexOfDocumentIdentifier + + CF$UID + 57 + + + Xcode.IDENavigableItemDomain.WorkspaceStructure + + $class + + CF$UID + 149 + + NS.objects + + + CF$UID + 142 + + + CF$UID + 145 + + + CF$UID + 147 + + + + + $class + + CF$UID + 144 + + Identifier + + CF$UID + 143 + + + PongViewController.m + + $classes + + IDEArchivableStringIndexPair + NSObject + + $classname + IDEArchivableStringIndexPair + + + $class + + CF$UID + 144 + + Identifier + + CF$UID + 146 + + + Classes + + $class + + CF$UID + 144 + + Identifier + + CF$UID + 148 + + + Pong + + $classes + + NSArray + NSObject + + $classname + NSArray + + + $class + + CF$UID + 151 + + documentURL + + CF$UID + 24 + + timestamp + + CF$UID + 0 + + + + $classes + + DVTDocumentLocation + NSObject + + $classname + DVTDocumentLocation + + + $classes + + IDENavigableItemArchivableRepresentation + NSObject + + $classname + IDENavigableItemArchivableRepresentation + + + $class + + CF$UID + 155 + + children + + CF$UID + 154 + + contentType + 0 + documentArchivableRepresentation + + CF$UID + 0 + + orientation + 0 + parent + + CF$UID + 0 + + + + $class + + CF$UID + 149 + + NS.objects + + + CF$UID + 138 + + + + + $classes + + IDEWorkspaceTabControllerLayoutTreeNode + NSObject + + $classname + IDEWorkspaceTabControllerLayoutTreeNode + + + $classes + + IDEWorkspaceTabControllerLayoutTree + NSObject + + $classname + IDEWorkspaceTabControllerLayoutTree + + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 158 + + + NS.objects + + + CF$UID + 159 + + + + EditorLayout_PersistentRepresentation + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 160 + + + NS.objects + + + CF$UID + 161 + + + + Main + + $class + + CF$UID + 184 + + NS.keys + + + CF$UID + 162 + + + CF$UID + 163 + + + CF$UID + 164 + + + NS.objects + + + CF$UID + 165 + + + CF$UID + 57 + + + CF$UID + 188 + + + + EditorLayout_StateSavingStateDictionaries + EditorLayout_Selected + EditorLayout_Geometry + + $class + + CF$UID + 149 + + NS.objects + + + CF$UID + 166 + + + + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 167 + + + CF$UID + 168 + + + CF$UID + 169 + + + CF$UID + 170 + + + CF$UID + 171 + + + CF$UID + 172 + + + CF$UID + 173 + + + NS.objects + + + CF$UID + 174 + + + CF$UID + 175 + + + CF$UID + 181 + + + CF$UID + 143 + + + CF$UID + 143 + + + CF$UID + 185 + + + CF$UID + 186 + + + + FileDataType + ArchivableRepresentation + EditorState + NavigableItemName + DocumentNavigableItemName + DocumentExtensionIdentifier + DocumentURL + public.objective-c-source + + $class + + CF$UID + 152 + + DocumentLocation + + CF$UID + 150 + + DomainIdentifier + + CF$UID + 140 + + IdentifierPath + + CF$UID + 176 + + IndexOfDocumentIdentifier + + CF$UID + 57 + + + + $class + + CF$UID + 149 + + NS.objects + + + CF$UID + 177 + + + CF$UID + 178 + + + CF$UID + 179 + + + + + $class + + CF$UID + 144 + + Identifier + + CF$UID + 143 + + + + $class + + CF$UID + 144 + + Identifier + + CF$UID + 146 + + + + $class + + CF$UID + 144 + + Identifier + + CF$UID + 180 + + + Pong + + $class + + CF$UID + 184 + + NS.keys + + + CF$UID + 41 + + + CF$UID + 42 + + + CF$UID + 43 + + + CF$UID + 44 + + + NS.objects + + + CF$UID + 182 + + + CF$UID + 183 + + + CF$UID + 15 + + + CF$UID + 38 + + + + 324225931.14565301 + {362, 1156} + + $classes + + NSDictionary + NSObject + + $classname + NSDictionary + + Xcode.IDEKit.EditorDocument.SourceCode + + $class + + CF$UID + 22 + + NS.base + + CF$UID + 0 + + NS.relative + + CF$UID + 187 + + + file://localhost/Users/jeena/Student/GGS/games/Pong/Classes/PongViewController.m + + $class + + CF$UID + 149 + + NS.objects + + + CF$UID + 189 + + + + {{0, 0}, {1016, 565}} + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 191 + + + CF$UID + 192 + + + CF$UID + 193 + + + CF$UID + 194 + + + CF$UID + 195 + + + CF$UID + 196 + + + NS.objects + + + CF$UID + 93 + + + CF$UID + 197 + + + CF$UID + 199 + + + CF$UID + 93 + + + CF$UID + 202 + + + CF$UID + 213 + + + + LayoutFocusMode + console + variables + LayoutMode + IDEDebuggerAreaSplitView + IDEDebugArea_SplitView + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 198 + + + NS.objects + + + CF$UID + 57 + + + + ConsoleFilterMode + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 200 + + + NS.objects + + + CF$UID + 201 + + + + DBGVariablesViewFilterMode + 2 + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 203 + + + NS.objects + + + CF$UID + 204 + + + + DVTSplitViewItems + + $class + + CF$UID + 97 + + NS.objects + + + CF$UID + 205 + + + CF$UID + 210 + + + + + $class + + CF$UID + 184 + + NS.keys + + + CF$UID + 206 + + + CF$UID + 207 + + + NS.objects + + + CF$UID + 208 + + + CF$UID + 209 + + + + DVTIdentifier + DVTViewMagnitude + VariablesView + 298 + + $class + + CF$UID + 184 + + NS.keys + + + CF$UID + 206 + + + CF$UID + 207 + + + NS.objects + + + CF$UID + 211 + + + CF$UID + 212 + + + + ConsoleArea + 717 + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 203 + + + NS.objects + + + CF$UID + 214 + + + + + $class + + CF$UID + 97 + + NS.objects + + + CF$UID + 215 + + + CF$UID + 217 + + + + + $class + + CF$UID + 184 + + NS.keys + + + CF$UID + 206 + + + CF$UID + 207 + + + NS.objects + + + CF$UID + 208 + + + CF$UID + 216 + + + + 298 + + $class + + CF$UID + 184 + + NS.keys + + + CF$UID + 206 + + + CF$UID + 207 + + + NS.objects + + + CF$UID + 211 + + + CF$UID + 218 + + + + 717 + + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 203 + + + NS.objects + + + CF$UID + 221 + + + + + $class + + CF$UID + 97 + + NS.objects + + + CF$UID + 222 + + + CF$UID + 225 + + + + + $class + + CF$UID + 184 + + NS.keys + + + CF$UID + 206 + + + CF$UID + 207 + + + NS.objects + + + CF$UID + 223 + + + CF$UID + 224 + + + + IDEEditor + 587 + + $class + + CF$UID + 184 + + NS.keys + + + CF$UID + 206 + + + CF$UID + 207 + + + NS.objects + + + CF$UID + 226 + + + CF$UID + 227 + + + + IDEDebuggerArea + 115 + + $class + + CF$UID + 39 + + NS.keys + + NS.objects + + + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 203 + + + NS.objects + + + CF$UID + 230 + + + + + $class + + CF$UID + 97 + + NS.objects + + + CF$UID + 231 + + + CF$UID + 234 + + + + + $class + + CF$UID + 184 + + NS.keys + + + CF$UID + 206 + + + CF$UID + 207 + + + NS.objects + + + CF$UID + 232 + + + CF$UID + 233 + + + + + 478 + + $class + + CF$UID + 184 + + NS.keys + + + CF$UID + 206 + + + CF$UID + 207 + + + NS.objects + + + CF$UID + 232 + + + CF$UID + 235 + + + + 224 + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 237 + + + CF$UID + 238 + + + CF$UID + 239 + + + NS.objects + + + CF$UID + 240 + + + CF$UID + 239 + + + CF$UID + 258 + + + + Xcode.IDEKit.Navigator.Issues + SelectedNavigator + Xcode.IDEKit.Navigator.Structure + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 241 + + + CF$UID + 242 + + + CF$UID + 243 + + + CF$UID + 244 + + + CF$UID + 245 + + + CF$UID + 246 + + + CF$UID + 247 + + + CF$UID + 248 + + + CF$UID + 249 + + + CF$UID + 250 + + + NS.objects + + + CF$UID + 15 + + + CF$UID + 251 + + + CF$UID + 252 + + + CF$UID + 254 + + + CF$UID + 255 + + + CF$UID + 15 + + + CF$UID + 15 + + + CF$UID + 256 + + + CF$UID + 15 + + + CF$UID + 257 + + + + IDEErrorFilteringEnabled + IDEVisibleRect + IDECollapsedFiles + IDEExpandedIssues + IDESelectedNavigables + IDEShowsByType + IDESchemeFilteringEnabled + IDECollapsedTypes + IDERecentFilteringEnabled + IDECollapsedGroups + {{0, 0}, {259, 636}} + + $class + + CF$UID + 253 + + NS.objects + + + + $classes + + NSMutableSet + NSSet + NSObject + + $classname + NSMutableSet + + + $class + + CF$UID + 253 + + NS.objects + + + + $class + + CF$UID + 97 + + NS.objects + + + + $class + + CF$UID + 253 + + NS.objects + + + + $class + + CF$UID + 253 + + NS.objects + + + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 259 + + + CF$UID + 260 + + + CF$UID + 261 + + + CF$UID + 262 + + + CF$UID + 263 + + + CF$UID + 264 + + + CF$UID + 265 + + + NS.objects + + + CF$UID + 266 + + + CF$UID + 15 + + + CF$UID + 267 + + + CF$UID + 15 + + + CF$UID + 15 + + + CF$UID + 269 + + + CF$UID + 272 + + + + IDEVisibleRect + IDEUnsavedDocumentFilteringEnabled + IDENavigatorExpandedItemsBeforeFilteringSet + IDERecentDocumentFilteringEnabled + IDESCMStatusFilteringEnabled + IDESelectedObjects + IDEExpandedItemsSet + {{0, 0}, {259, 658}} + + $class + + CF$UID + 268 + + NS.objects + + + + $classes + + NSSet + NSObject + + $classname + NSSet + + + $class + + CF$UID + 149 + + NS.objects + + + CF$UID + 270 + + + + + $class + + CF$UID + 97 + + NS.objects + + + CF$UID + 271 + + + CF$UID + 146 + + + CF$UID + 143 + + + + Pong + + $class + + CF$UID + 268 + + NS.objects + + + CF$UID + 273 + + + CF$UID + 274 + + + + + $class + + CF$UID + 97 + + NS.objects + + + CF$UID + 271 + + + + + $class + + CF$UID + 97 + + NS.objects + + + CF$UID + 271 + + + CF$UID + 146 + + + + + $class + + CF$UID + 39 + + NS.keys + + + CF$UID + 203 + + + NS.objects + + + CF$UID + 276 + + + + + $class + + CF$UID + 97 + + NS.objects + + + CF$UID + 277 + + + CF$UID + 279 + + + CF$UID + 281 + + + + + $class + + CF$UID + 184 + + NS.keys + + + CF$UID + 206 + + + CF$UID + 207 + + + NS.objects + + + CF$UID + 124 + + + CF$UID + 278 + + + + 260 + + $class + + CF$UID + 184 + + NS.keys + + + CF$UID + 206 + + + CF$UID + 207 + + + NS.objects + + + CF$UID + 120 + + + CF$UID + 280 + + + + 1016 + + $class + + CF$UID + 184 + + NS.keys + + + CF$UID + 206 + + + CF$UID + 207 + + + NS.objects + + + CF$UID + 282 + + + CF$UID + 283 + + + + IDEUtilitiesArea + 260 + PongViewController.m + + $class + + CF$UID + 149 + + NS.objects + + + CF$UID + 113 + + + + {{0, 0}, {1276, 778}} + + $top + + State + + CF$UID + 1 + + + $version + 100000 + + diff --git a/games/Pong/Pong.xcodeproj/xcuserdata/jeena.xcuserdatad/xcschemes/Pong.xcscheme b/games/Pong/Pong.xcodeproj/xcuserdata/jeena.xcuserdatad/xcschemes/Pong.xcscheme new file mode 100644 index 0000000..5ff41ee --- /dev/null +++ b/games/Pong/Pong.xcodeproj/xcuserdata/jeena.xcuserdatad/xcschemes/Pong.xcscheme @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/games/Pong/Pong.xcodeproj/xcuserdata/jeena.xcuserdatad/xcschemes/xcschememanagement.plist b/games/Pong/Pong.xcodeproj/xcuserdata/jeena.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..5bd0d76 --- /dev/null +++ b/games/Pong/Pong.xcodeproj/xcuserdata/jeena.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + Pong.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 1D6058900D05DD3D006BFB54 + + primary + + + + + diff --git a/python_client b/python_client index 10feefd..50e8dbd 100755 --- a/python_client +++ b/python_client @@ -60,7 +60,8 @@ while True: s.close() -""" +time.sleep(2) + HOST = 'localhost' # The remote host PORT = int(sys.argv[1]) # The same port as used by the server s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) @@ -81,4 +82,3 @@ print "Token:", token print "Data: ", ' '.join(data.split(" ")[1:]) s.close() -""" diff --git a/python_client_reconnect b/python_client_reconnect new file mode 100755 index 0000000..2a41b70 --- /dev/null +++ b/python_client_reconnect @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +import sys, time, socket + +HOST = 'localhost' # The remote host +PORT = int(sys.argv[1]) # The same port as used by the server +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +s.connect((HOST, PORT)) +# Call that function! + +print "Calling myFun" +s.send( +"Token: %s\n\ +Server-Command: call\n\ +Content-Type: text\n\ +Content-Length: 6\n\ +\n\ +myFun" % raw_input("Token >> ")) +fs = s.makefile() +data = fs.readline() +print "Data: ", ' '.join(data.split(" ")[1:]) + +s.close() diff --git a/src/ggs_dispatcher.erl b/src/ggs_dispatcher.erl index 11dd729..fdd28c6 100644 --- a/src/ggs_dispatcher.erl +++ b/src/ggs_dispatcher.erl @@ -58,7 +58,8 @@ handle_info({tcp_closed, Socket}, State) -> %% and when it does, we accept the connection. handle_info(timeout, LSock) -> {ok, Sock} = gen_tcp:accept(LSock), - spawn(ggs_player, start_link, [Sock]), + ggs_player:start(Sock), + erlang:display("handle_info"), {noreply, LSock, 0}. terminate(normal, _State) -> diff --git a/src/ggs_player.erl b/src/ggs_player.erl index 0323bcc..9b31d3d 100644 --- a/src/ggs_player.erl +++ b/src/ggs_player.erl @@ -1,49 +1,65 @@ --module(ggs_player). --export([start_link/1, notify/3, get_token/1, stop/2]). --record(pl_state, - {token, % Player's token - socket, % Player's socket - table}). % Player's table - %% @doc This module handles communication between a player and GGS. This module is -%%responsible for: -%% * The storage of the player socket, player token and a table token. -%% * Ability to fetch a player token. -%% * Forwarding messages from players to the game -%% * Remove a player from GGS +%% responsible for: +%% * The storage of the player socket, player token and a table token. +%% * Ability to fetch a player token. +%% * Forwarding messages from players to the game +%% * Remove a player from GGS + +-module(ggs_player). +-behaviour(gen_server). +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). + +-export([start/1, notify/3, notify_game/2, get_token/1, stop/1]). + +-vsn(1.0). + +-record(state, { + token, + socket, + table, + protocol }). %% @doc Spawns a process representing the player in GGS. Takes the player socket as %% an argument for storage and later usage. Creates a unique player token %% identifying the player. %% @spec start_link(Socket::socket()) -> {ok, Pid} | {error, Reason} -start_link(Socket) -> - % The socket is in 'active' mode, and that means we are pushed any data - % that arrives on it, we do not need to recv() manually. Since the socket - % was opened in our parent process, we need to change the owner of it to - % us, otherwise these messages end up in our parent. - ggs_protocol:start_link(), - erlang:port_connect(Socket, self()), +start(Socket) -> + gen_server:start(?MODULE, [Socket], []). + +init([Socket]) -> + {ok, Protocol} = ggs_protocol:start_link(), {ok, Token} = ggs_coordinator:join_lobby(), - TableStatus = ggs_coordinator:join_table("1337"), - case TableStatus of - {ok, Table} -> - notify(self(), self(), {"hello", Token}), - loop(#pl_state{socket = Socket, token = Token, table = Table}); + + case ggs_coordinator:join_table("1337") of + {ok, T} -> + Table = T; {error, no_such_table} -> ggs_coordinator:create_table({force, "1337"}), - {ok, Table} = ggs_coordinator:join_table("1337"), - notify(self(), self(), {"hello", Token}), - loop(#pl_state{socket = Socket, token = Token, table = Table}) - end. + {ok, T} = ggs_coordinator:join_table("1337"), + Table = T + end, + + State = #state{ + token = Token, + socket = Socket, + table = Table, + protocol = Protocol + }, + erlang:display(State), + {ok, State}. %% @doc Handles incoming messages from the GGS and forwards them through the player %% socket to the player. %% @spec notify(Player::Pid(), From::Pid(), %% {Command::String(), Message::string()}) -> ok -notify(Player, From, Message) -> - {Cmd, Data} = Message, - Parsed = ggs_protocol:create_message(Cmd, "text","text", Data), - Player ! {notify, From, Parsed}. +notify(Player, _From, Message) -> + gen_server:cast(Player, {notify, Message}). + +%% @doc Handles incomming messages form a client and forwards them +%% through to the game_vm +notify_game(Player, Message) -> + gen_server:cast(Player, Message). %% @doc Get the player token uniquely representing the player. %% @spec get_token() -> string() @@ -54,31 +70,37 @@ get_token(_Player) -> %% together with the table token. It should also close the player socket and the %% process should return in the end. %% @spec stop(Table::pid()) -> Reason::string() -stop(_Player,_Table) -> - ggs_logger:not_implemented(). +stop(Player) -> + gen_server:cast(Player, stop). %% Internals +handle_call({notify, Message}, _From, #state { protocol = Protocol, socket = Socket } = State) -> + gen_tcp:send(Socket, ggs_protocol:create_message(Protocol, Message)), + {noreply, State}; -loop(#pl_state{token = _Token, socket = Socket, table = Table} = State) -> - receive - {tcp, Socket, Data} -> % Just echo for now.. - Parsed = ggs_protocol:parse(Data), - loop(State); - {notify, _From, Message} -> - gen_tcp:send(Socket, Message), - loop(State); - % Below are messages generated by the parser - {game_cmd,Cmd, _Headers, Data} -> - ggs_table:notify(Table, self(), {game, Cmd, Data}), - loop(State); - {srv_cmd,"define", _Headers, Data} -> - ggs_table:notify(Table, self(), {server, define, Data}), - loop(State); - {tcp_closed, _Socket} -> - io:format("Client disconnected, but THIS IS NOT SUPPORTED YET!~n"), - loop(State); - Other -> - io:format("Got UNKNOWN message: "), - erlang:display(Other), - io:format("~n") - end. +handle_call({game_cmd, Command, _Headers, Data}, _From, #state { table = Table } = State) -> + ggs_table:notify(Table, self(), {game, Command, Data}), + {noreply, State}; + +handle_call({srv_cmd, "define", _Headers, Data}, _From, #state { table = Table } = State) -> + ggs_table:notify(Table, self(), {server, define, Data}), + {noreply, State}; + + +handle_call(_Request, _From, St) -> {stop, unimplemented, St}. + +handle_cast({tcp, _Socket, Data}, #state { protocol = Protocol } = _State) -> + ggs_protocol:parse(Protocol, Data); + +handle_cast(_Request, St) -> {stop, unimplemented, St}. + +handle_info(_Info, St) -> {stop, unimplemented, St}. + +terminate(_Reason, State) -> + ggs_protocol:stop(State#state.protocol), + ggs_table:remove_player(State#state.table, self()), + % ggs_coordinator:remove_player(self(), self()), % not implemented yet + % TODO: release Socket + ok. + +code_change(_OldVsn, St, _Extra) -> {ok, St}. diff --git a/src/ggs_protocol.erl b/src/ggs_protocol.erl index 36a96d6..b0c16e8 100644 --- a/src/ggs_protocol.erl +++ b/src/ggs_protocol.erl @@ -4,12 +4,12 @@ %% message. -module(ggs_protocol). --export([parse/1, getToken/1, create_message/4, +-export([parse/2, getToken/1, create_message/4, expect_headers/2, expect_data_section/2, expect_headers/3, expect_data_section/3]). %% tests --export([test/0, to_dictionary/2]). +-export([to_dictionary/2]). % gen_fsm callbacks.. -export([init/1, handle_info/2, terminate/2, code_change/3, start_link/0]). @@ -18,17 +18,17 @@ -define(SERVER, ?MODULE). %% JONTES TESTS -test() -> - start_link(), - parse("Token: %s\nServer-Command: define\nContent-Type: text\nContent-Length: 9\n\nHELLOWORLDToken: %s\nServer-Command: define\nContent-Type: text\nContent-Length: 9\n\nHELLOWORLDToken: %s\nServer-Command: define\n"), - to_dictionary(["Hello: world", "Hi: there!"], []). +%test() -> +% start_link(), +% parse("Token: %s\nServer-Command: define\nContent-Type: text\nContent-Length: 9\n\nHELLOWORLDToken: %s\nServer-Command: define\nContent-Type: text\nContent-Length: 9\n\nHELLOWORLDToken: %s\nServer-Command: define\n"), +% to_dictionary(["Hello: world", "Hi: there!"], []). %% END TESTS %% API Functions -parse(Data) -> +parse(Protocol, Data) -> lists:foreach(fun(X) -> - gen_fsm:sync_send_event(?SERVER, {char, X}) + gen_fsm:sync_send_event(Protocol, {char, X}) end, Data). @@ -52,6 +52,9 @@ getToken(Parsed) -> false end. +create_message({Command, Data}) -> + create_message(Command, "text", "text", Data). + %% Assemble a message which can b %e used as a reply to a client create_message(Cmd, Enc, Acc, Data) -> diff --git a/src/ggs_protocol.erl.orig b/src/ggs_protocol.erl.orig new file mode 100644 index 0000000..61d424b --- /dev/null +++ b/src/ggs_protocol.erl.orig @@ -0,0 +1,146 @@ +%% Parse a string formatted with the GGS protocol using +%% an FSM. Each char is put into the FSM, which incrementally +%% builds a list of strings which represent the complete +%% message. + +-module(ggs_protocol). +-export([parse/1, getToken/1, create_message/4, + expect_headers/2, expect_data_section/2, + expect_headers/3, expect_data_section/3]). + +%% tests +-export([test/0, to_dictionary/2]). + +% gen_fsm callbacks.. +-export([init/1, handle_info/2, terminate/2, code_change/3, start_link/0]). + + +-define(SERVER, ?MODULE). + +%% JONTES TESTS +test() -> + start_link(), + parse("Token: %s\nServer-Command: define\nContent-Type: text\nContent-Length: 9\n\nHELLOWORLDToken: %s\nServer-Command: define\nContent-Type: text\nContent-Length: 9\n\nHELLOWORLDToken: %s\nServer-Command: define\n"), + to_dictionary(["Hello: world", "Hi: there!"], []). +%% END TESTS + + +%% API Functions +parse(Data) -> + lists:foreach(fun(X) -> + gen_fsm:sync_send_event(?SERVER, {char, X}) + end, Data). + + +start_link() -> + gen_fsm:start_link({local, ?SERVER}, ?MODULE, [], []). + +% Start state: {[""],0}, meaning: +% - Start with no strings parsed +% - Start with a data-section-lengths of 0 +init([]) -> + {ok,expect_headers,{[""], 0}}. + + + +getToken(Parsed) -> + + case lists:keyfind(token, 1, Parsed) of + {_, Value} -> + Value; + false -> + false + end. +<<<<<<< Updated upstream +======= + + +create_message(Protocol, {Command, Data}) { + create_message(Command, "text", "text", Data), +} +>>>>>>> Stashed changes + +%% Assemble a message which can b +%e used as a reply to a client +create_message(Cmd, Enc, Acc, Data) -> + Length = integer_to_list(string:len(Data)), + Msg = "Client-Command: " ++ Cmd ++ "\n" ++ + "Client-Encoding: " ++ Enc ++ "\n" ++ + "Content-Size: " ++ Length ++ "\n" ++ + "GGS-Version: 1.0\n" ++ + "Accept: " ++ Acc ++ "\n" ++ + "\n" ++ + Data, + Msg. + +%%% Transitions +expect_headers(_Event, State) -> + {next_state, expect_headers, State}. +expect_data_section(_Event, State) -> + {next_state, expect_data_section, State}. + + +%%% End transitions +expect_headers({char, $\n}, _From, {Strings, Remains}) -> + [LastMessage|_] = Strings, + case LastMessage of + "" -> % We have a data section.. Last line should thus be the content length. + [LastMessage, SecondLast | _] = Strings, + case re:split(SecondLast, ": ", [{return, list}]) of + ["Content-Length", X] -> + {Int,_} = string:to_integer(X), + {reply, ok, expect_data_section, {[""|Strings], Int}}; + Other -> ok + end; + Other -> + {reply,ok,expect_headers, {[""|Strings], Remains}} + end; + +expect_headers({char, Char}, _From, {[Current|Rest], Remains}) -> + NewCurrent = Current ++ [Char], + {reply,ok, expect_headers, {[NewCurrent|Rest], Remains}}. + + +expect_data_section({char, Char}, From, {Strings, Remains}) -> + case Remains of + 0 -> + [LastMsg,_|Rest] = Strings, + NewMsg = LastMsg ++ [Char], + Result = [NewMsg|Rest], + {Pid,_} = From, + erlang:display(From), + Pid ! (prettify(to_dictionary(Rest, []), NewMsg)), + {reply, ok, expect_headers, {[""], 0}}; + Other -> [LastMsg|Rest] = Strings, + NewMsg = LastMsg ++ [Char], + {reply, ok, expect_data_section, {[NewMsg|Rest], Remains-1}} + end. +handle_call(_Msg, _From, State) -> + {noreply, State}. +handle_info(_Msg, State) -> + {noreply, State}. +terminate(_Reason, _State) -> + ok. +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + + +prettify(Args, Data) -> + case lists:keyfind("Server-Command", 1, Args) of + {_, Value} -> + {srv_cmd, Value, Args, Data}; + _Other -> + case lists:keyfind("Game-Command", 1, Args) of + {_, Value} -> + {game_cmd, Value, Args, Data}; + _ -> + ok + end + end. + +to_dictionary([], Dict) -> + Dict; +to_dictionary([S|Strings], Dict) -> + [First, Snd] = re:split(S, ": ", [{return, list}]), + to_dictionary(Strings, [{First, Snd}|Dict]). + diff --git a/src/ggs_server.erl b/src/ggs_server.erl new file mode 100644 index 0000000..40bb88f --- /dev/null +++ b/src/ggs_server.erl @@ -0,0 +1,142 @@ +-module(ggs_server). +-behaviour(gen_server). + +%% API +-export([start_link/1, + start_link/0, + stop/0 + ]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, + handle_info/2, terminate/2, code_change/3]). + + +-define(SERVER, ?MODULE). +-define(DEFAULT_PORT, 1055). + +-record(state, {port, lsock, client_vm_map = []}). + +%%%==================================================== +%%% API +%%%==================================================== + +%%----------------------------------------------------- +%% @doc Starts the server +%% @end +%%----------------------------------------------------- +start_link(Port) -> + gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []). + +start_link() -> + start_link(?DEFAULT_PORT). + +%%----------------------------------------------------- +%% @doc Stops the server. +%% @spec stop() -> ok +%% @end +%%----------------------------------------------------- +stop() -> + gen_server:cast(?SERVER, stop). + +%%----------------------------------------------------- +%% gen_server callbacks +%%----------------------------------------------------- + +init([Port]) -> + case gen_server:call(ggs_backup, get_backup) of + {backup_state, not_initialized} -> + {ok, LSock} = gen_tcp:listen(Port, [{active, true}, + {reuseaddr, true}]), + {ok, #state{port = Port, lsock = LSock}, 0}; + {backup_state, State} -> + {ok, LSock} = gen_tcp:listen(Port, [{active, true}, + {reuseaddr, true}]), + {ok, State#state{lsock = LSock}, 0} + end. + +handle_call({backup_state, OldState}, _From, _State) -> + io:format("Received old state from backup~n"), + {noreply, OldState}. + + +handle_info({tcp, Socket, RawData}, State) -> + ggs_protocol:parse(RawData), + {noreply, State#state{lsock = Socket}}; + +handle_info({tcp_closed, Socket}, State) -> + gen_tcp:close(Socket), + {stop, "Client closed socket", State}; + +handle_info(timeout, #state{lsock = LSock} = State) -> + {ok, _Sock} = gen_tcp:accept(LSock), + {noreply, State}; + +handle_info(Other, _State) -> + erlang:display(Other). + +terminate(_Reason, _State) -> + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%%----------------------------------------------------- +%% Internal functions +%%----------------------------------------------------- +handle_cast(stop, State) -> + {stop, normal, State}; + +% Handle javascript defines +handle_cast({srv_cmd, "define", Headers, Data}, State) -> + Token = ggs_protocol:getToken(Headers), + GameVM = getJSVM(Token, State), + ggs_vm_runner:define(GameVM, Data), + send(State#state.lsock, "Token", "Okay, defined that for you!"), + {noreply, State}; + +% Handle javascript calls +handle_cast({srv_cmd, "call", Headers, Data}, State) -> + Token = ggs_protocol:getToken(Headers), + io:format("Got call request: ~p~n", [Data]), + GameVM = getJSVM(Token, State), + Ret = ggs_vm_runner:user_command(GameVM, "User", Data, []), + send(State#state.lsock, Token, "JS says:", binary_to_list(Ret)), + {noreply, State}; + +% Set the new state to the reference generated, and JSVM associated +%handle_cast({server, hello, Headers}, State) -> +handle_cast({srv_cmd, "hello", Headers, _Data}, State) -> + GameToken = case proplist:get_value(game_token, Headers) of + undefined -> getNewToken(); + GT -> GT + end, + ClientToken = getNewToken(), + OldMap = State#state.client_vm_map, + GameVM = getJSVM(ClientToken, State), + NewState = State#state{client_vm_map = OldMap ++ [{ClientToken, GameVM, GameToken}]}, + gen_server:cast(ggs_backup, {set_backup, NewState}), + {noreply, NewState}. + + +%%----------------------------------------------------- +%% Helpers +%%----------------------------------------------------- +getNewToken() -> + string:strip(os:cmd("uuidgen"), right, $\n ). + +getJSVM(ClientToken, State) -> + VMs = State#state.client_vm_map, + {value, {_,VM}} = lists:keysearch(ClientToken, 1, VMs), + VM. + +getGameVMByGameToken(GameToken, State) -> + VMs = State#state.client_vm_map, + {value, {_,VM}} = lists:keysearch(GameToken, 3, VMs), + VM. + +send(Socket, RefID, String) -> + gen_tcp:send(Socket, string:join([RefID,String,"\n"], " ")). + +send(Socket, RefID, String1, String2) -> + gen_tcp:send(Socket, string:join([RefID,String1, String2,"\n"], " ")). diff --git a/src/ggs_vm_runner.erl b/src/ggs_vm_runner.erl new file mode 100644 index 0000000..e149c51 --- /dev/null +++ b/src/ggs_vm_runner.erl @@ -0,0 +1,42 @@ +-module(ggs_vm_runner). +-export([start_link/0, define/2, user_command/4]). + +%Mattias +start_link() -> + erlang_js:start(), + PortPid = spawn_link( fun() -> + process_flag(trap_exit, true), + {ok, Port} = js_driver:new(), + js:define(Port, <<"function userCommand(user, command, args){return 'Hello world';}">>), + loop(Port) + end ), + PortPid. + + +loop(Port) -> + receive + {define, SourceCode} -> + ok = js:define(Port, list_to_binary(SourceCode)), + loop(Port); + {user_command, User, Command, Args, From, Ref} -> + {ok, Ret} = js:call(Port, <<"userCommand">>, + [ list_to_binary(User), + list_to_binary(Command), + list_to_binary(Args) + ]), + From ! {Ref, Ret}, + loop(Port) + end. + + +define(GameVM, SourceCode) -> + GameVM ! {define,SourceCode}. + +user_command(GameVM, User, Command, Args) -> + Ref = make_ref(), + GameVM ! {user_command, User, Command, Args, self(), Ref}, + receive + {Ref, RetVal} -> + RetVal; + Other -> Other + end. diff --git a/tests/ggs_player_test.erl b/tests/ggs_player_test.erl index efe7530..1782842 100644 --- a/tests/ggs_player_test.erl +++ b/tests/ggs_player_test.erl @@ -4,7 +4,7 @@ %% @doc start_link should always return ok for any valid socket. A valid socket %% should always return {ok, Pid} and {error, Reason} otherwise. start_link_test() -> - ggs_logger:not_implemented(). + {ok, Player} = ggs_player:start_link(Sock). %% @doc Given that start_link returned {ok, Player}. Notify shall always return ok and %% deliver a specified message through the socket.