├── .gitignore ├── Podfile ├── Podfile.lock ├── README.md ├── TicTacIOiOS.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── TicTacIOiOS.xccheckout └── xcshareddata │ └── xcschemes │ └── TicTacIOiOS.xcscheme ├── TicTacIOiOS.xcworkspace ├── contents.xcworkspacedata └── xcuserdata │ └── eriklittle.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── TicTacIOiOS ├── AppDelegate.swift ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist └── ViewController.swift └── server ├── index.js ├── package-lock.json └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | # Created by https://www.gitignore.io/api/swift,xcode,cocoapods 4 | # Edit at https://www.gitignore.io/?templates=swift,xcode,cocoapods 5 | 6 | ### CocoaPods ### 7 | ## CocoaPods GitIgnore Template 8 | 9 | # CocoaPods - Only use to conserve bandwidth / Save time on Pushing 10 | # - Also handy if you have a large number of dependant pods 11 | # - AS PER https://guides.cocoapods.org/using/using-cocoapods.html NEVER IGNORE THE LOCK FILE 12 | Pods/ 13 | 14 | ### Swift ### 15 | # Xcode 16 | # 17 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 18 | 19 | ## Build generated 20 | build/ 21 | DerivedData/ 22 | 23 | ## Various settings 24 | *.pbxuser 25 | !default.pbxuser 26 | *.mode1v3 27 | !default.mode1v3 28 | *.mode2v3 29 | !default.mode2v3 30 | *.perspectivev3 31 | !default.perspectivev3 32 | xcuserdata/ 33 | 34 | ## Other 35 | *.moved-aside 36 | *.xccheckout 37 | *.xcscmblueprint 38 | 39 | ## Obj-C/Swift specific 40 | *.hmap 41 | *.ipa 42 | *.dSYM.zip 43 | *.dSYM 44 | 45 | ## Playgrounds 46 | timeline.xctimeline 47 | playground.xcworkspace 48 | 49 | # Swift Package Manager 50 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 51 | # Packages/ 52 | # Package.pins 53 | # Package.resolved 54 | .build/ 55 | 56 | # CocoaPods 57 | # We recommend against adding the Pods directory to your .gitignore. However 58 | # you should judge for yourself, the pros and cons are mentioned at: 59 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 60 | # Pods/ 61 | # Add this line if you want to avoid checking in source code from the Xcode workspace 62 | # *.xcworkspace 63 | 64 | # Carthage 65 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 66 | # Carthage/Checkouts 67 | 68 | Carthage/Build 69 | 70 | # fastlane 71 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 72 | # screenshots whenever they are needed. 73 | # For more information about the recommended setup visit: 74 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 75 | 76 | fastlane/report.xml 77 | fastlane/Preview.html 78 | fastlane/screenshots/**/*.png 79 | fastlane/test_output 80 | 81 | # Code Injection 82 | # After new code Injection tools there's a generated folder /iOSInjectionProject 83 | # https://github.com/johnno1962/injectionforxcode 84 | 85 | iOSInjectionProject/ 86 | 87 | ### Xcode ### 88 | # Xcode 89 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 90 | 91 | ## User settings 92 | 93 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 94 | 95 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 96 | 97 | ### Xcode Patch ### 98 | *.xcodeproj/* 99 | !*.xcodeproj/project.pbxproj 100 | !*.xcodeproj/xcshareddata/ 101 | !*.xcworkspace/contents.xcworkspacedata 102 | /*.gcno 103 | **/xcshareddata/WorkspaceSettings.xcsettings 104 | 105 | # End of https://www.gitignore.io/api/swift,xcode,cocoapods 106 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | inhibit_all_warnings! 2 | platform :ios, '10.3' 3 | use_frameworks! 4 | 5 | target 'TicTacIOiOS' do 6 | pod 'Socket.IO-Client-Swift' 7 | end 8 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Socket.IO-Client-Swift (15.0.0): 3 | - Starscream (~> 3.1) 4 | - Starscream (3.1.0) 5 | 6 | DEPENDENCIES: 7 | - Socket.IO-Client-Swift 8 | 9 | SPEC REPOS: 10 | https://github.com/cocoapods/specs.git: 11 | - Socket.IO-Client-Swift 12 | - Starscream 13 | 14 | SPEC CHECKSUMS: 15 | Socket.IO-Client-Swift: c039a808195d22a7192962841b8c035cb61ea49e 16 | Starscream: 08172b481e145289c4930cb567230fb55897cfa4 17 | 18 | PODFILE CHECKSUM: e002494b44290ce63aa66185271909e9beb70283 19 | 20 | COCOAPODS: 1.5.3 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # socket.io-client-swift-example 2 | An example of socket.io-client for Swift in the form of a TicTacToe app 3 | 4 |
5 | ![](http://i.imgur.com/wOkugkml.jpg) 6 |
7 | -------------------------------------------------------------------------------- /TicTacIOiOS.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 74AC61241AAB680200DE3B77 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74AC61231AAB680200DE3B77 /* AppDelegate.swift */; }; 11 | 74AC61261AAB680200DE3B77 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74AC61251AAB680200DE3B77 /* ViewController.swift */; }; 12 | 74AC61291AAB680200DE3B77 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 74AC61271AAB680200DE3B77 /* Main.storyboard */; }; 13 | 74AC612B1AAB680200DE3B77 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 74AC612A1AAB680200DE3B77 /* Images.xcassets */; }; 14 | 74AC612E1AAB680200DE3B77 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 74AC612C1AAB680200DE3B77 /* LaunchScreen.xib */; }; 15 | 8903DD217631710EA469A221 /* Pods_TicTacIOiOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C4D38710F1D246426EA4AF67 /* Pods_TicTacIOiOS.framework */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXFileReference section */ 19 | 74AC611E1AAB680200DE3B77 /* TicTacIOiOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TicTacIOiOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; 20 | 74AC61221AAB680200DE3B77 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 21 | 74AC61231AAB680200DE3B77 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 22 | 74AC61251AAB680200DE3B77 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 23 | 74AC61281AAB680200DE3B77 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 24 | 74AC612A1AAB680200DE3B77 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 25 | 74AC612D1AAB680200DE3B77 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 26 | 74AC61381AAB680200DE3B77 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 27 | 74AC61391AAB680200DE3B77 /* TicTacIOiOSTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TicTacIOiOSTests.swift; sourceTree = ""; }; 28 | 9DA35544BB9186C1DB93230D /* Pods-TicTacIOiOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TicTacIOiOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-TicTacIOiOS/Pods-TicTacIOiOS.debug.xcconfig"; sourceTree = ""; }; 29 | ABB571E3D80B0B587ABC4EF3 /* Pods-TicTacIOiOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TicTacIOiOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-TicTacIOiOS/Pods-TicTacIOiOS.release.xcconfig"; sourceTree = ""; }; 30 | C4D38710F1D246426EA4AF67 /* Pods_TicTacIOiOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TicTacIOiOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | /* End PBXFileReference section */ 32 | 33 | /* Begin PBXFrameworksBuildPhase section */ 34 | 74AC611B1AAB680200DE3B77 /* Frameworks */ = { 35 | isa = PBXFrameworksBuildPhase; 36 | buildActionMask = 2147483647; 37 | files = ( 38 | 8903DD217631710EA469A221 /* Pods_TicTacIOiOS.framework in Frameworks */, 39 | ); 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXFrameworksBuildPhase section */ 43 | 44 | /* Begin PBXGroup section */ 45 | 0FA4C23F62622646B0E971BC /* Frameworks */ = { 46 | isa = PBXGroup; 47 | children = ( 48 | C4D38710F1D246426EA4AF67 /* Pods_TicTacIOiOS.framework */, 49 | ); 50 | name = Frameworks; 51 | sourceTree = ""; 52 | }; 53 | 2E1A36EBC6ED79A51BDB3158 /* Pods */ = { 54 | isa = PBXGroup; 55 | children = ( 56 | 9DA35544BB9186C1DB93230D /* Pods-TicTacIOiOS.debug.xcconfig */, 57 | ABB571E3D80B0B587ABC4EF3 /* Pods-TicTacIOiOS.release.xcconfig */, 58 | ); 59 | name = Pods; 60 | sourceTree = ""; 61 | }; 62 | 74AC61151AAB680200DE3B77 = { 63 | isa = PBXGroup; 64 | children = ( 65 | 74AC61201AAB680200DE3B77 /* TicTacIOiOS */, 66 | 74AC61361AAB680200DE3B77 /* TicTacIOiOSTests */, 67 | 74AC611F1AAB680200DE3B77 /* Products */, 68 | 2E1A36EBC6ED79A51BDB3158 /* Pods */, 69 | 0FA4C23F62622646B0E971BC /* Frameworks */, 70 | ); 71 | sourceTree = ""; 72 | }; 73 | 74AC611F1AAB680200DE3B77 /* Products */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | 74AC611E1AAB680200DE3B77 /* TicTacIOiOS.app */, 77 | ); 78 | name = Products; 79 | sourceTree = ""; 80 | }; 81 | 74AC61201AAB680200DE3B77 /* TicTacIOiOS */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | 74AC61231AAB680200DE3B77 /* AppDelegate.swift */, 85 | 74AC61251AAB680200DE3B77 /* ViewController.swift */, 86 | 74AC61271AAB680200DE3B77 /* Main.storyboard */, 87 | 74AC612A1AAB680200DE3B77 /* Images.xcassets */, 88 | 74AC612C1AAB680200DE3B77 /* LaunchScreen.xib */, 89 | 74AC61211AAB680200DE3B77 /* Supporting Files */, 90 | ); 91 | path = TicTacIOiOS; 92 | sourceTree = ""; 93 | }; 94 | 74AC61211AAB680200DE3B77 /* Supporting Files */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | 74AC61221AAB680200DE3B77 /* Info.plist */, 98 | ); 99 | name = "Supporting Files"; 100 | sourceTree = ""; 101 | }; 102 | 74AC61361AAB680200DE3B77 /* TicTacIOiOSTests */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | 74AC61391AAB680200DE3B77 /* TicTacIOiOSTests.swift */, 106 | 74AC61371AAB680200DE3B77 /* Supporting Files */, 107 | ); 108 | path = TicTacIOiOSTests; 109 | sourceTree = ""; 110 | }; 111 | 74AC61371AAB680200DE3B77 /* Supporting Files */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 74AC61381AAB680200DE3B77 /* Info.plist */, 115 | ); 116 | name = "Supporting Files"; 117 | sourceTree = ""; 118 | }; 119 | /* End PBXGroup section */ 120 | 121 | /* Begin PBXNativeTarget section */ 122 | 74AC611D1AAB680200DE3B77 /* TicTacIOiOS */ = { 123 | isa = PBXNativeTarget; 124 | buildConfigurationList = 74AC613D1AAB680200DE3B77 /* Build configuration list for PBXNativeTarget "TicTacIOiOS" */; 125 | buildPhases = ( 126 | 023D7CA9F94CDFE0FFFEBF63 /* [CP] Check Pods Manifest.lock */, 127 | 74AC611A1AAB680200DE3B77 /* Sources */, 128 | 74AC611B1AAB680200DE3B77 /* Frameworks */, 129 | 74AC611C1AAB680200DE3B77 /* Resources */, 130 | 9B9A31B1DF14A3A9593E84AA /* [CP] Embed Pods Frameworks */, 131 | ); 132 | buildRules = ( 133 | ); 134 | dependencies = ( 135 | ); 136 | name = TicTacIOiOS; 137 | productName = TicTacIOiOS; 138 | productReference = 74AC611E1AAB680200DE3B77 /* TicTacIOiOS.app */; 139 | productType = "com.apple.product-type.application"; 140 | }; 141 | /* End PBXNativeTarget section */ 142 | 143 | /* Begin PBXProject section */ 144 | 74AC61161AAB680200DE3B77 /* Project object */ = { 145 | isa = PBXProject; 146 | attributes = { 147 | LastSwiftUpdateCheck = 0700; 148 | LastUpgradeCheck = 1020; 149 | ORGANIZATIONNAME = "Erik Little"; 150 | TargetAttributes = { 151 | 74AC611D1AAB680200DE3B77 = { 152 | CreatedOnToolsVersion = 6.3; 153 | LastSwiftMigration = 0830; 154 | }; 155 | }; 156 | }; 157 | buildConfigurationList = 74AC61191AAB680200DE3B77 /* Build configuration list for PBXProject "TicTacIOiOS" */; 158 | compatibilityVersion = "Xcode 3.2"; 159 | developmentRegion = English; 160 | hasScannedForEncodings = 0; 161 | knownRegions = ( 162 | English, 163 | en, 164 | Base, 165 | ); 166 | mainGroup = 74AC61151AAB680200DE3B77; 167 | productRefGroup = 74AC611F1AAB680200DE3B77 /* Products */; 168 | projectDirPath = ""; 169 | projectRoot = ""; 170 | targets = ( 171 | 74AC611D1AAB680200DE3B77 /* TicTacIOiOS */, 172 | ); 173 | }; 174 | /* End PBXProject section */ 175 | 176 | /* Begin PBXResourcesBuildPhase section */ 177 | 74AC611C1AAB680200DE3B77 /* Resources */ = { 178 | isa = PBXResourcesBuildPhase; 179 | buildActionMask = 2147483647; 180 | files = ( 181 | 74AC61291AAB680200DE3B77 /* Main.storyboard in Resources */, 182 | 74AC612E1AAB680200DE3B77 /* LaunchScreen.xib in Resources */, 183 | 74AC612B1AAB680200DE3B77 /* Images.xcassets in Resources */, 184 | ); 185 | runOnlyForDeploymentPostprocessing = 0; 186 | }; 187 | /* End PBXResourcesBuildPhase section */ 188 | 189 | /* Begin PBXShellScriptBuildPhase section */ 190 | 023D7CA9F94CDFE0FFFEBF63 /* [CP] Check Pods Manifest.lock */ = { 191 | isa = PBXShellScriptBuildPhase; 192 | buildActionMask = 2147483647; 193 | files = ( 194 | ); 195 | inputPaths = ( 196 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 197 | "${PODS_ROOT}/Manifest.lock", 198 | ); 199 | name = "[CP] Check Pods Manifest.lock"; 200 | outputPaths = ( 201 | "$(DERIVED_FILE_DIR)/Pods-TicTacIOiOS-checkManifestLockResult.txt", 202 | ); 203 | runOnlyForDeploymentPostprocessing = 0; 204 | shellPath = /bin/sh; 205 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 206 | showEnvVarsInLog = 0; 207 | }; 208 | 9B9A31B1DF14A3A9593E84AA /* [CP] Embed Pods Frameworks */ = { 209 | isa = PBXShellScriptBuildPhase; 210 | buildActionMask = 2147483647; 211 | files = ( 212 | ); 213 | inputPaths = ( 214 | "${SRCROOT}/Pods/Target Support Files/Pods-TicTacIOiOS/Pods-TicTacIOiOS-frameworks.sh", 215 | "${BUILT_PRODUCTS_DIR}/Socket.IO-Client-Swift/SocketIO.framework", 216 | "${BUILT_PRODUCTS_DIR}/Starscream/Starscream.framework", 217 | ); 218 | name = "[CP] Embed Pods Frameworks"; 219 | outputPaths = ( 220 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SocketIO.framework", 221 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Starscream.framework", 222 | ); 223 | runOnlyForDeploymentPostprocessing = 0; 224 | shellPath = /bin/sh; 225 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-TicTacIOiOS/Pods-TicTacIOiOS-frameworks.sh\"\n"; 226 | showEnvVarsInLog = 0; 227 | }; 228 | /* End PBXShellScriptBuildPhase section */ 229 | 230 | /* Begin PBXSourcesBuildPhase section */ 231 | 74AC611A1AAB680200DE3B77 /* Sources */ = { 232 | isa = PBXSourcesBuildPhase; 233 | buildActionMask = 2147483647; 234 | files = ( 235 | 74AC61261AAB680200DE3B77 /* ViewController.swift in Sources */, 236 | 74AC61241AAB680200DE3B77 /* AppDelegate.swift in Sources */, 237 | ); 238 | runOnlyForDeploymentPostprocessing = 0; 239 | }; 240 | /* End PBXSourcesBuildPhase section */ 241 | 242 | /* Begin PBXVariantGroup section */ 243 | 74AC61271AAB680200DE3B77 /* Main.storyboard */ = { 244 | isa = PBXVariantGroup; 245 | children = ( 246 | 74AC61281AAB680200DE3B77 /* Base */, 247 | ); 248 | name = Main.storyboard; 249 | sourceTree = ""; 250 | }; 251 | 74AC612C1AAB680200DE3B77 /* LaunchScreen.xib */ = { 252 | isa = PBXVariantGroup; 253 | children = ( 254 | 74AC612D1AAB680200DE3B77 /* Base */, 255 | ); 256 | name = LaunchScreen.xib; 257 | sourceTree = ""; 258 | }; 259 | /* End PBXVariantGroup section */ 260 | 261 | /* Begin XCBuildConfiguration section */ 262 | 74AC613B1AAB680200DE3B77 /* Debug */ = { 263 | isa = XCBuildConfiguration; 264 | buildSettings = { 265 | ALWAYS_SEARCH_USER_PATHS = NO; 266 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 267 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 268 | CLANG_CXX_LIBRARY = "libc++"; 269 | CLANG_ENABLE_MODULES = YES; 270 | CLANG_ENABLE_OBJC_ARC = YES; 271 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 272 | CLANG_WARN_BOOL_CONVERSION = YES; 273 | CLANG_WARN_COMMA = YES; 274 | CLANG_WARN_CONSTANT_CONVERSION = YES; 275 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 276 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 277 | CLANG_WARN_EMPTY_BODY = YES; 278 | CLANG_WARN_ENUM_CONVERSION = YES; 279 | CLANG_WARN_INFINITE_RECURSION = YES; 280 | CLANG_WARN_INT_CONVERSION = YES; 281 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 282 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 283 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 284 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 285 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 286 | CLANG_WARN_STRICT_PROTOTYPES = YES; 287 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 288 | CLANG_WARN_UNREACHABLE_CODE = YES; 289 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 290 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 291 | COPY_PHASE_STRIP = NO; 292 | DEBUG_INFORMATION_FORMAT = dwarf; 293 | ENABLE_STRICT_OBJC_MSGSEND = YES; 294 | ENABLE_TESTABILITY = YES; 295 | GCC_C_LANGUAGE_STANDARD = gnu99; 296 | GCC_DYNAMIC_NO_PIC = NO; 297 | GCC_NO_COMMON_BLOCKS = YES; 298 | GCC_OPTIMIZATION_LEVEL = 0; 299 | GCC_PREPROCESSOR_DEFINITIONS = ( 300 | "DEBUG=1", 301 | "$(inherited)", 302 | ); 303 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 304 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 305 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 306 | GCC_WARN_UNDECLARED_SELECTOR = YES; 307 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 308 | GCC_WARN_UNUSED_FUNCTION = YES; 309 | GCC_WARN_UNUSED_VARIABLE = YES; 310 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 311 | MTL_ENABLE_DEBUG_INFO = YES; 312 | ONLY_ACTIVE_ARCH = YES; 313 | SDKROOT = iphoneos; 314 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 315 | SWIFT_VERSION = 5.0; 316 | TARGETED_DEVICE_FAMILY = "1,2"; 317 | }; 318 | name = Debug; 319 | }; 320 | 74AC613C1AAB680200DE3B77 /* Release */ = { 321 | isa = XCBuildConfiguration; 322 | buildSettings = { 323 | ALWAYS_SEARCH_USER_PATHS = NO; 324 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 325 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 326 | CLANG_CXX_LIBRARY = "libc++"; 327 | CLANG_ENABLE_MODULES = YES; 328 | CLANG_ENABLE_OBJC_ARC = YES; 329 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 330 | CLANG_WARN_BOOL_CONVERSION = YES; 331 | CLANG_WARN_COMMA = YES; 332 | CLANG_WARN_CONSTANT_CONVERSION = YES; 333 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 334 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 335 | CLANG_WARN_EMPTY_BODY = YES; 336 | CLANG_WARN_ENUM_CONVERSION = YES; 337 | CLANG_WARN_INFINITE_RECURSION = YES; 338 | CLANG_WARN_INT_CONVERSION = YES; 339 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 340 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 341 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 342 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 343 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 344 | CLANG_WARN_STRICT_PROTOTYPES = YES; 345 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 346 | CLANG_WARN_UNREACHABLE_CODE = YES; 347 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 348 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 349 | COPY_PHASE_STRIP = NO; 350 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 351 | ENABLE_NS_ASSERTIONS = NO; 352 | ENABLE_STRICT_OBJC_MSGSEND = YES; 353 | GCC_C_LANGUAGE_STANDARD = gnu99; 354 | GCC_NO_COMMON_BLOCKS = YES; 355 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 356 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 357 | GCC_WARN_UNDECLARED_SELECTOR = YES; 358 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 359 | GCC_WARN_UNUSED_FUNCTION = YES; 360 | GCC_WARN_UNUSED_VARIABLE = YES; 361 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 362 | MTL_ENABLE_DEBUG_INFO = NO; 363 | SDKROOT = iphoneos; 364 | SWIFT_COMPILATION_MODE = wholemodule; 365 | SWIFT_VERSION = 5.0; 366 | TARGETED_DEVICE_FAMILY = "1,2"; 367 | VALIDATE_PRODUCT = YES; 368 | }; 369 | name = Release; 370 | }; 371 | 74AC613E1AAB680200DE3B77 /* Debug */ = { 372 | isa = XCBuildConfiguration; 373 | baseConfigurationReference = 9DA35544BB9186C1DB93230D /* Pods-TicTacIOiOS.debug.xcconfig */; 374 | buildSettings = { 375 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 376 | INFOPLIST_FILE = TicTacIOiOS/Info.plist; 377 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 378 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 379 | PRODUCT_BUNDLE_IDENTIFIER = "com.milkbartube.$(PRODUCT_NAME:rfc1034identifier)"; 380 | PRODUCT_NAME = "$(TARGET_NAME)"; 381 | SWIFT_OBJC_BRIDGING_HEADER = ""; 382 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 383 | SWIFT_VERSION = 5.0; 384 | }; 385 | name = Debug; 386 | }; 387 | 74AC613F1AAB680200DE3B77 /* Release */ = { 388 | isa = XCBuildConfiguration; 389 | baseConfigurationReference = ABB571E3D80B0B587ABC4EF3 /* Pods-TicTacIOiOS.release.xcconfig */; 390 | buildSettings = { 391 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 392 | INFOPLIST_FILE = TicTacIOiOS/Info.plist; 393 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 394 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 395 | PRODUCT_BUNDLE_IDENTIFIER = "com.milkbartube.$(PRODUCT_NAME:rfc1034identifier)"; 396 | PRODUCT_NAME = "$(TARGET_NAME)"; 397 | SWIFT_OBJC_BRIDGING_HEADER = ""; 398 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 399 | SWIFT_VERSION = 5.0; 400 | }; 401 | name = Release; 402 | }; 403 | /* End XCBuildConfiguration section */ 404 | 405 | /* Begin XCConfigurationList section */ 406 | 74AC61191AAB680200DE3B77 /* Build configuration list for PBXProject "TicTacIOiOS" */ = { 407 | isa = XCConfigurationList; 408 | buildConfigurations = ( 409 | 74AC613B1AAB680200DE3B77 /* Debug */, 410 | 74AC613C1AAB680200DE3B77 /* Release */, 411 | ); 412 | defaultConfigurationIsVisible = 0; 413 | defaultConfigurationName = Release; 414 | }; 415 | 74AC613D1AAB680200DE3B77 /* Build configuration list for PBXNativeTarget "TicTacIOiOS" */ = { 416 | isa = XCConfigurationList; 417 | buildConfigurations = ( 418 | 74AC613E1AAB680200DE3B77 /* Debug */, 419 | 74AC613F1AAB680200DE3B77 /* Release */, 420 | ); 421 | defaultConfigurationIsVisible = 0; 422 | defaultConfigurationName = Release; 423 | }; 424 | /* End XCConfigurationList section */ 425 | }; 426 | rootObject = 74AC61161AAB680200DE3B77 /* Project object */; 427 | } 428 | -------------------------------------------------------------------------------- /TicTacIOiOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TicTacIOiOS.xcodeproj/project.xcworkspace/xcshareddata/TicTacIOiOS.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 469C9D5A-212B-439B-B930-A5ABB47F1955 9 | IDESourceControlProjectName 10 | TicTacIOiOS 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 01C4019DAB2F13C7FB458F088D0A991884C46F1A 14 | https://github.com/socketio/socket.io-client-swift 15 | D9E1DCB9D67A66BF9037B8BEE764D8E4A3609BDF 16 | https://github.com/nuclearace/socket.io-client-swift-example.git 17 | 18 | IDESourceControlProjectPath 19 | TicTacIOiOS.xcodeproj 20 | IDESourceControlProjectRelativeInstallPathDictionary 21 | 22 | 01C4019DAB2F13C7FB458F088D0A991884C46F1A 23 | ../../TicTacIOiOS/SocketIOClientSwift/ 24 | D9E1DCB9D67A66BF9037B8BEE764D8E4A3609BDF 25 | ../.. 26 | 27 | IDESourceControlProjectURL 28 | https://github.com/nuclearace/socket.io-client-swift-example.git 29 | IDESourceControlProjectVersion 30 | 111 31 | IDESourceControlProjectWCCIdentifier 32 | D9E1DCB9D67A66BF9037B8BEE764D8E4A3609BDF 33 | IDESourceControlProjectWCConfigurations 34 | 35 | 36 | IDESourceControlRepositoryExtensionIdentifierKey 37 | public.vcs.git 38 | IDESourceControlWCCIdentifierKey 39 | 01C4019DAB2F13C7FB458F088D0A991884C46F1A 40 | IDESourceControlWCCName 41 | SocketIOClientSwift 42 | 43 | 44 | IDESourceControlRepositoryExtensionIdentifierKey 45 | public.vcs.git 46 | IDESourceControlWCCIdentifierKey 47 | D9E1DCB9D67A66BF9037B8BEE764D8E4A3609BDF 48 | IDESourceControlWCCName 49 | TicTacIOiOS 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /TicTacIOiOS.xcodeproj/xcshareddata/xcschemes/TicTacIOiOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 67 | 68 | 78 | 80 | 86 | 87 | 88 | 89 | 90 | 91 | 97 | 99 | 105 | 106 | 107 | 108 | 110 | 111 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /TicTacIOiOS.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TicTacIOiOS.xcworkspace/xcuserdata/eriklittle.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuclearace/socket.io-client-swift-example/e6a8f465cf39ee32e17598ce27c89af3c9917b78/TicTacIOiOS.xcworkspace/xcuserdata/eriklittle.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /TicTacIOiOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // TicTacIOiOS 4 | // 5 | // Created by Erik Little on 3/7/15. 6 | // 7 | 8 | import UIKit 9 | 10 | @UIApplicationMain 11 | class AppDelegate: UIResponder, UIApplicationDelegate { 12 | 13 | var window: UIWindow? 14 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { 15 | return true 16 | } 17 | 18 | func applicationWillResignActive(_ application: UIApplication) { 19 | } 20 | 21 | func applicationDidEnterBackground(_ application: UIApplication) { 22 | 23 | } 24 | 25 | func applicationWillEnterForeground(_ application: UIApplication) { 26 | } 27 | 28 | func applicationDidBecomeActive(_ application: UIApplication) { 29 | 30 | } 31 | 32 | func applicationWillTerminate(_ application: UIApplication) { 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /TicTacIOiOS/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /TicTacIOiOS/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 32 | 46 | 60 | 71 | 82 | 96 | 110 | 121 | 130 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | -------------------------------------------------------------------------------- /TicTacIOiOS/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /TicTacIOiOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSAppTransportSecurity 6 | 7 | NSAllowsArbitraryLoads 8 | 9 | 10 | CFBundleDevelopmentRegion 11 | en 12 | CFBundleExecutable 13 | $(EXECUTABLE_NAME) 14 | CFBundleIdentifier 15 | $(PRODUCT_BUNDLE_IDENTIFIER) 16 | CFBundleInfoDictionaryVersion 17 | 6.0 18 | CFBundleName 19 | $(PRODUCT_NAME) 20 | CFBundlePackageType 21 | APPL 22 | CFBundleShortVersionString 23 | 1.0 24 | CFBundleSignature 25 | ???? 26 | CFBundleVersion 27 | 1 28 | LSRequiresIPhoneOS 29 | 30 | UILaunchStoryboardName 31 | LaunchScreen 32 | UIMainStoryboardFile 33 | Main 34 | UIRequiredDeviceCapabilities 35 | 36 | armv7 37 | 38 | UISupportedInterfaceOrientations 39 | 40 | UIInterfaceOrientationPortrait 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UISupportedInterfaceOrientations~ipad 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationPortraitUpsideDown 48 | UIInterfaceOrientationLandscapeLeft 49 | UIInterfaceOrientationLandscapeRight 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /TicTacIOiOS/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // TicTacIOiOS 4 | // 5 | // Created by Erik Little on 3/7/15. 6 | // 7 | 8 | import UIKit 9 | import SocketIO 10 | 11 | class ViewController: UIViewController, UIAlertViewDelegate { 12 | @IBOutlet weak var btn0:UIButton! 13 | @IBOutlet weak var btn1:UIButton! 14 | @IBOutlet weak var btn2:UIButton! 15 | @IBOutlet weak var btn3:UIButton! 16 | @IBOutlet weak var btn4:UIButton! 17 | @IBOutlet weak var btn5:UIButton! 18 | @IBOutlet weak var btn6:UIButton! 19 | @IBOutlet weak var btn7:UIButton! 20 | @IBOutlet weak var btn8:UIButton! 21 | @IBOutlet weak var label:UILabel! 22 | let manager = SocketManager(socketURL: URL(string: "http://localhost:8900")!, config: [.log(true), .compress]) 23 | var socket:SocketIOClient! 24 | var name: String? 25 | var resetAck: SocketAckEmitter? 26 | 27 | override func viewDidLoad() { 28 | super.viewDidLoad() 29 | socket = manager.defaultSocket 30 | 31 | addHandlers() 32 | socket.connect() 33 | 34 | let grad = CAGradientLayer() 35 | grad.frame = self.view.bounds 36 | 37 | let colors = [UIColor(red: 127, green: 0, blue: 127, alpha: 1).cgColor, 38 | UIColor(red: 0, green: 0, blue: 0, alpha: 1).cgColor] 39 | 40 | grad.colors = colors 41 | view.layer.insertSublayer(grad, at: 0) 42 | } 43 | 44 | func addHandlers() { 45 | socket.on("startGame") {[weak self] data, ack in 46 | self?.handleStart() 47 | return 48 | } 49 | 50 | socket.on("name") {[weak self] data, ack in 51 | if let name = data[0] as? String { 52 | self?.name = name 53 | } 54 | } 55 | 56 | socket.on("playerMove") {[weak self] data, ack in 57 | if let name = data[0] as? String, let x = data[1] as? Int, let y = data[2] as? Int { 58 | self?.handlePlayerMove(name, coord: (x, y)) 59 | } 60 | } 61 | 62 | socket.on("win") {[weak self] data, ack in 63 | if let name = data[0] as? String, let typeDict = data[1] as? NSDictionary { 64 | self?.handleWin(name, type: typeDict) 65 | } 66 | } 67 | 68 | socket.on("draw") {[weak self] data, ack in 69 | self?.handleDraw() 70 | return 71 | } 72 | 73 | socket.on("currentTurn") {[weak self] data, ack in 74 | if let name = data[0] as? String { 75 | self?.handleCurrentTurn(name) 76 | 77 | } 78 | } 79 | 80 | socket.on("gameReset") {[weak self] data, ack in 81 | guard let sself = self else { return } 82 | self?.resetAck = ack 83 | self?.present(sself.alertController, animated: true, completion: nil) 84 | } 85 | 86 | socket.on("gameOver") {data, ack in 87 | exit(0) 88 | } 89 | 90 | socket.onAny {print("Got event: \($0.event), with items: \($0.items!)")} 91 | } 92 | 93 | @IBAction func btnClicked(_ btn: UIButton) { 94 | let coord:(x: Int, y: Int) 95 | 96 | switch btn.tag { 97 | case 0: 98 | coord = (0, 0) 99 | case 1: 100 | coord = (0, 1) 101 | case 2: 102 | coord = (0, 2) 103 | case 3: 104 | coord = (1, 0) 105 | case 4: 106 | coord = (1, 1) 107 | case 5: 108 | coord = (1, 2) 109 | case 6: 110 | coord = (2, 0) 111 | case 7: 112 | coord = (2, 1) 113 | case 8: 114 | coord = (2, 2) 115 | default: 116 | coord = (-1, -1) 117 | } 118 | 119 | socket.emit("playerMove", coord.x, coord.y) 120 | } 121 | 122 | func drawWinLine(_ type: NSDictionary) { 123 | let winType = type["type"] as! String 124 | let to: CGPoint 125 | let from: CGPoint 126 | 127 | if winType == "row" { 128 | let row = type["num"] as! Int 129 | 130 | switch row { 131 | case 0: 132 | to = btn2.center 133 | from = btn0.center 134 | case 1: 135 | to = btn3.center 136 | from = btn5.center 137 | case 2: 138 | to = btn6.center 139 | from = btn8.center 140 | default: 141 | to = CGPoint(x: 0.0, y: 0.0) 142 | from = CGPoint(x: 0.0, y: 0.0) 143 | } 144 | } else if winType == "col" { 145 | let row = type["num"] as! Int 146 | 147 | switch row { 148 | case 0: 149 | to = btn6.center 150 | from = btn0.center 151 | case 1: 152 | to = btn7.center 153 | from = btn1.center 154 | case 2: 155 | to = btn2.center 156 | from = btn8.center 157 | default: 158 | to = CGPoint(x: 0.0, y: 0.0) 159 | from = CGPoint(x: 0.0, y: 0.0) 160 | } 161 | } else { 162 | let coord = type["coord"] as! NSDictionary 163 | let x = coord["x"] as! Int 164 | let y = coord["y"] as! Int 165 | 166 | switch (x, y) { 167 | case (0, 0): 168 | to = btn8.center 169 | from = btn0.center 170 | case (0, 2): 171 | to = btn6.center 172 | from = btn2.center 173 | case (2, 2): 174 | to = btn0.center 175 | from = btn8.center 176 | case (2, 0): 177 | to = btn2.center 178 | from = btn6.center 179 | default: 180 | to = CGPoint(x: 0.0, y: 0.0) 181 | from = CGPoint(x: 0.0, y: 0.0) 182 | } 183 | } 184 | 185 | let path = UIBezierPath() 186 | path.move(to: from) 187 | path.addLine(to: to) 188 | 189 | let shapeLayer = CAShapeLayer() 190 | shapeLayer.path = path.cgPath 191 | shapeLayer.strokeColor = UIColor.white.cgColor 192 | shapeLayer.lineWidth = 3.0 193 | shapeLayer.fillColor = UIColor.clear.cgColor 194 | view.layer.addSublayer(shapeLayer) 195 | } 196 | 197 | func handleCurrentTurn(_ name: String) { 198 | if name == self.name! { 199 | label.text = "Your turn!" 200 | } else { 201 | label.text = "Opponents turn!" 202 | } 203 | } 204 | 205 | func handleDraw() { 206 | label.text = "Draw!" 207 | } 208 | 209 | func handleGameReset() { 210 | btn0.setTitle("-", for: UIControl.State()) 211 | btn1.setTitle("-", for: UIControl.State()) 212 | btn2.setTitle("-", for: UIControl.State()) 213 | btn3.setTitle("-", for: UIControl.State()) 214 | btn4.setTitle("-", for: UIControl.State()) 215 | btn5.setTitle("-", for: UIControl.State()) 216 | btn6.setTitle("-", for: UIControl.State()) 217 | btn7.setTitle("-", for: UIControl.State()) 218 | btn8.setTitle("-", for: UIControl.State()) 219 | 220 | btn0.isEnabled = true 221 | btn1.isEnabled = true 222 | btn2.isEnabled = true 223 | btn3.isEnabled = true 224 | btn4.isEnabled = true 225 | btn5.isEnabled = true 226 | btn6.isEnabled = true 227 | btn7.isEnabled = true 228 | btn8.isEnabled = true 229 | 230 | view.layer.sublayers?.removeLast() 231 | label.text = "Waiting for Opponent" 232 | } 233 | 234 | func handlePlayerMove(_ name: String, coord: (Int, Int)) { 235 | switch coord { 236 | case (0, 0): 237 | btn0.setTitle(name, for: .disabled) 238 | btn0.isEnabled = false 239 | case (0, 1): 240 | btn1.setTitle(name, for: .disabled) 241 | btn1.isEnabled = false 242 | case (0, 2): 243 | btn2.setTitle(name, for: .disabled) 244 | btn2.isEnabled = false 245 | case (1, 0): 246 | btn3.setTitle(name, for: .disabled) 247 | btn3.isEnabled = false 248 | case (1, 1): 249 | btn4.setTitle(name, for: .disabled) 250 | btn4.isEnabled = false 251 | case (1, 2): 252 | btn5.setTitle(name, for: .disabled) 253 | btn5.isEnabled = false 254 | case (2, 0): 255 | btn6.setTitle(name, for: .disabled) 256 | btn6.isEnabled = false 257 | case (2, 1): 258 | btn7.setTitle(name, for: .disabled) 259 | btn7.isEnabled = false 260 | case (2, 2): 261 | btn8.setTitle(name, for: .disabled) 262 | btn8.isEnabled = false 263 | default: 264 | return 265 | } 266 | } 267 | 268 | func handleStart() { 269 | if name == "X" { 270 | label.text = "Your turn!" 271 | } else { 272 | label.text = "Opponents turn" 273 | } 274 | } 275 | 276 | func handleWin(_ name: String, type: NSDictionary) { 277 | label.text = "Player \(name) won!" 278 | drawWinLine(type) 279 | } 280 | 281 | var alertController: UIAlertController { 282 | let alert = UIAlertController(title: "Play Again?", 283 | message: "Do you want to play another round?", 284 | preferredStyle: .alert) 285 | alert.addAction(UIAlertAction(title: "No", style: .cancel, handler: { [weak self] action in 286 | self?.resetAck?.with(false) 287 | })) 288 | alert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { [weak self] action in 289 | self?.handleGameReset() 290 | self?.resetAck?.with(true) 291 | })) 292 | return alert 293 | } 294 | } 295 | 296 | -------------------------------------------------------------------------------- /server/index.js: -------------------------------------------------------------------------------- 1 | var app = require('http').createServer() 2 | 3 | app.listen(8900) 4 | 5 | function Player(socket) { 6 | var self = this 7 | this.socket = socket 8 | this.name = "" 9 | this.game = {} 10 | 11 | this.socket.on("playerMove", function(x, y) { 12 | self.game.playerMove(self, x, y) 13 | }) 14 | } 15 | 16 | Player.prototype.joinGame = function(game) { 17 | this.game = game 18 | } 19 | 20 | function Game() { 21 | this.io = require('socket.io')(app) 22 | this.board = [ 23 | ["", "", ""], 24 | ["", "", ""], 25 | ["", "", ""] 26 | ] 27 | this.player1 = null 28 | this.player2 = null 29 | this.currentTurn = "X" 30 | this.moveCount = 0 31 | this.started = false 32 | this.addHandlers() 33 | } 34 | 35 | Game.prototype.addHandlers = function() { 36 | var game = this 37 | 38 | this.io.sockets.on("connection", function(socket) { 39 | game.addPlayer(new Player(socket)) 40 | }) 41 | } 42 | 43 | Game.prototype.addPlayer = function(player) { 44 | console.log("adding player") 45 | if (this.player1 === null) { 46 | this.player1 = player 47 | this.player1["game"] = this 48 | this.player1["name"] = "X" 49 | this.player1.socket.emit("name", "X") 50 | } else if (this.player2 === null) { 51 | this.player2 = player 52 | this.player2["game"] = this 53 | this.player2["name"] = "O" 54 | this.player2.socket.emit("name", "O") 55 | this.startGame() 56 | } 57 | } 58 | 59 | Game.prototype.announceWin = function(player, type) { 60 | this.player1.socket.emit("win", player["name"], type) 61 | this.player2.socket.emit("win", player["name"], type) 62 | this.resetGame() 63 | } 64 | 65 | Game.prototype.gameOver = function() { 66 | this.player1.socket.emit("gameOver") 67 | this.player2.socket.emit("gameOver") 68 | } 69 | 70 | Game.prototype.playerMove = function(player, x, y) { 71 | if (player["name"] !== this.currentTurn || x >= 3 || y >= 3) { 72 | return 73 | } 74 | 75 | this.player1.socket.emit("playerMove", player["name"], x, y) 76 | this.player2.socket.emit("playerMove", player["name"], x, y) 77 | this.board[x][y] = player["name"] 78 | 79 | var n = 3 80 | //check row 81 | for (var i = 0; i < n; i++) { 82 | if (this.board[x][i] !== player["name"]) { 83 | break 84 | } 85 | 86 | if (i === n - 1) { 87 | this.announceWin(player, { 88 | type: "row", 89 | num: x 90 | }) 91 | return 92 | } 93 | } 94 | 95 | // Check col 96 | for (var i = 0; i < n; i++) { 97 | if (this.board[i][y] !== player["name"]) { 98 | break 99 | } 100 | 101 | if (i === n - 1) { 102 | this.announceWin(player, { 103 | type: "col", 104 | num: y 105 | }) 106 | return 107 | } 108 | } 109 | 110 | // Check diags 111 | if (x === y) { 112 | for (var i = 0; i < n; i++) { 113 | if (this.board[i][i] !== player["name"]) { 114 | break 115 | } 116 | 117 | if (i == n - 1) { 118 | this.announceWin(player, { 119 | type: "diag", 120 | coord: { 121 | x: x, 122 | y: y 123 | }, 124 | anti: false 125 | }) 126 | return 127 | } 128 | } 129 | } 130 | 131 | for (var i = 0; i < n; i++) { 132 | if (this.board[i][(n - 1) - i] !== player["name"]) { 133 | break 134 | } 135 | 136 | if (i === n - 1) { 137 | this.announceWin(player, { 138 | type: "diag", 139 | coord: { 140 | x: x, 141 | y: y 142 | }, 143 | anti: true 144 | }) 145 | return 146 | } 147 | } 148 | 149 | if (this.moveCount === (Math.pow(n, 2) - 1)) { 150 | this.player1.socket.emit("draw") 151 | this.player2.socket.emit("draw") 152 | this.resetGame() 153 | return 154 | } 155 | 156 | this.moveCount++ 157 | if (player["name"] === "X") { 158 | this.currentTurn = "O" 159 | this.player1.socket.emit("currentTurn", "O") 160 | this.player2.socket.emit("currentTurn", "O") 161 | } else { 162 | this.currentTurn = "X" 163 | this.player1.socket.emit("currentTurn", "X") 164 | this.player2.socket.emit("currentTurn", "X") 165 | } 166 | } 167 | 168 | Game.prototype.resetGame = function() { 169 | var self = this 170 | var player1Ans = null 171 | var player2Ans = null 172 | 173 | var reset = function() { 174 | if (player1Ans === null || player2Ans === null) { 175 | return 176 | } else if ((player1Ans & player2Ans) === 0) { 177 | self.gameOver() 178 | process.exit(0) 179 | } 180 | 181 | self.board = [ 182 | ["", "", ""], 183 | ["", "", ""], 184 | ["", "", ""] 185 | ] 186 | self.moveCount = 0 187 | 188 | if (self.player1["name"] === "X") { 189 | self.player1["name"] = "O" 190 | self.player1.socket.emit("name", "O") 191 | self.player2["name"] = "X" 192 | self.player2.socket.emit("name", "X") 193 | } else { 194 | self.player1["name"] = "X" 195 | self.player1.socket.emit("name", "X") 196 | self.player2["name"] = "O" 197 | self.player2.socket.emit("name", "O") 198 | } 199 | 200 | self.startGame() 201 | } 202 | 203 | this.player1.socket.emit("gameReset", function(ans) { 204 | player1Ans = ans 205 | reset() 206 | }) 207 | this.player2.socket.emit("gameReset", function(ans) { 208 | player2Ans = ans 209 | reset() 210 | }) 211 | } 212 | 213 | Game.prototype.startGame = function() { 214 | this.player1.socket.emit("startGame") 215 | this.player2.socket.emit("startGame") 216 | } 217 | 218 | // Start the game server 219 | var game = new Game() 220 | -------------------------------------------------------------------------------- /server/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": true, 3 | "lockfileVersion": 1, 4 | "dependencies": { 5 | "accepts": { 6 | "version": "1.3.7", 7 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 8 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 9 | "requires": { 10 | "mime-types": "~2.1.24", 11 | "negotiator": "0.6.2" 12 | } 13 | }, 14 | "after": { 15 | "version": "0.8.2", 16 | "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", 17 | "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" 18 | }, 19 | "arraybuffer.slice": { 20 | "version": "0.0.7", 21 | "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", 22 | "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" 23 | }, 24 | "async-limiter": { 25 | "version": "1.0.0", 26 | "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", 27 | "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" 28 | }, 29 | "backo2": { 30 | "version": "1.0.2", 31 | "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", 32 | "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" 33 | }, 34 | "base64-arraybuffer": { 35 | "version": "0.1.5", 36 | "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", 37 | "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" 38 | }, 39 | "base64id": { 40 | "version": "1.0.0", 41 | "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", 42 | "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=" 43 | }, 44 | "better-assert": { 45 | "version": "1.0.2", 46 | "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", 47 | "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", 48 | "requires": { 49 | "callsite": "1.0.0" 50 | } 51 | }, 52 | "blob": { 53 | "version": "0.0.5", 54 | "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", 55 | "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" 56 | }, 57 | "callsite": { 58 | "version": "1.0.0", 59 | "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", 60 | "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" 61 | }, 62 | "component-bind": { 63 | "version": "1.0.0", 64 | "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", 65 | "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" 66 | }, 67 | "component-emitter": { 68 | "version": "1.2.1", 69 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", 70 | "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" 71 | }, 72 | "component-inherit": { 73 | "version": "0.0.3", 74 | "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", 75 | "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" 76 | }, 77 | "cookie": { 78 | "version": "0.3.1", 79 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 80 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 81 | }, 82 | "debug": { 83 | "version": "4.1.1", 84 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 85 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 86 | "requires": { 87 | "ms": "^2.1.1" 88 | } 89 | }, 90 | "engine.io": { 91 | "version": "3.3.2", 92 | "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.3.2.tgz", 93 | "integrity": "sha512-AsaA9KG7cWPXWHp5FvHdDWY3AMWeZ8x+2pUVLcn71qE5AtAzgGbxuclOytygskw8XGmiQafTmnI9Bix3uihu2w==", 94 | "requires": { 95 | "accepts": "~1.3.4", 96 | "base64id": "1.0.0", 97 | "cookie": "0.3.1", 98 | "debug": "~3.1.0", 99 | "engine.io-parser": "~2.1.0", 100 | "ws": "~6.1.0" 101 | }, 102 | "dependencies": { 103 | "debug": { 104 | "version": "3.1.0", 105 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 106 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 107 | "requires": { 108 | "ms": "2.0.0" 109 | } 110 | }, 111 | "ms": { 112 | "version": "2.0.0", 113 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 114 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 115 | } 116 | } 117 | }, 118 | "engine.io-client": { 119 | "version": "3.3.2", 120 | "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.3.2.tgz", 121 | "integrity": "sha512-y0CPINnhMvPuwtqXfsGuWE8BB66+B6wTtCofQDRecMQPYX3MYUZXFNKDhdrSe3EVjgOu4V3rxdeqN/Tr91IgbQ==", 122 | "requires": { 123 | "component-emitter": "1.2.1", 124 | "component-inherit": "0.0.3", 125 | "debug": "~3.1.0", 126 | "engine.io-parser": "~2.1.1", 127 | "has-cors": "1.1.0", 128 | "indexof": "0.0.1", 129 | "parseqs": "0.0.5", 130 | "parseuri": "0.0.5", 131 | "ws": "~6.1.0", 132 | "xmlhttprequest-ssl": "~1.5.4", 133 | "yeast": "0.1.2" 134 | }, 135 | "dependencies": { 136 | "debug": { 137 | "version": "3.1.0", 138 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 139 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 140 | "requires": { 141 | "ms": "2.0.0" 142 | } 143 | }, 144 | "ms": { 145 | "version": "2.0.0", 146 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 147 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 148 | } 149 | } 150 | }, 151 | "engine.io-parser": { 152 | "version": "2.1.3", 153 | "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", 154 | "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", 155 | "requires": { 156 | "after": "0.8.2", 157 | "arraybuffer.slice": "~0.0.7", 158 | "base64-arraybuffer": "0.1.5", 159 | "blob": "0.0.5", 160 | "has-binary2": "~1.0.2" 161 | } 162 | }, 163 | "has-binary2": { 164 | "version": "1.0.3", 165 | "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", 166 | "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", 167 | "requires": { 168 | "isarray": "2.0.1" 169 | } 170 | }, 171 | "has-cors": { 172 | "version": "1.1.0", 173 | "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", 174 | "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" 175 | }, 176 | "indexof": { 177 | "version": "0.0.1", 178 | "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", 179 | "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" 180 | }, 181 | "isarray": { 182 | "version": "2.0.1", 183 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", 184 | "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" 185 | }, 186 | "mime-db": { 187 | "version": "1.40.0", 188 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", 189 | "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" 190 | }, 191 | "mime-types": { 192 | "version": "2.1.24", 193 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", 194 | "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", 195 | "requires": { 196 | "mime-db": "1.40.0" 197 | } 198 | }, 199 | "ms": { 200 | "version": "2.1.1", 201 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 202 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 203 | }, 204 | "negotiator": { 205 | "version": "0.6.2", 206 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 207 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 208 | }, 209 | "object-component": { 210 | "version": "0.0.3", 211 | "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", 212 | "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=" 213 | }, 214 | "parseqs": { 215 | "version": "0.0.5", 216 | "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", 217 | "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", 218 | "requires": { 219 | "better-assert": "~1.0.0" 220 | } 221 | }, 222 | "parseuri": { 223 | "version": "0.0.5", 224 | "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", 225 | "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", 226 | "requires": { 227 | "better-assert": "~1.0.0" 228 | } 229 | }, 230 | "socket.io": { 231 | "version": "2.2.0", 232 | "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.2.0.tgz", 233 | "integrity": "sha512-wxXrIuZ8AILcn+f1B4ez4hJTPG24iNgxBBDaJfT6MsyOhVYiTXWexGoPkd87ktJG8kQEcL/NBvRi64+9k4Kc0w==", 234 | "requires": { 235 | "debug": "~4.1.0", 236 | "engine.io": "~3.3.1", 237 | "has-binary2": "~1.0.2", 238 | "socket.io-adapter": "~1.1.0", 239 | "socket.io-client": "2.2.0", 240 | "socket.io-parser": "~3.3.0" 241 | } 242 | }, 243 | "socket.io-adapter": { 244 | "version": "1.1.1", 245 | "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", 246 | "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=" 247 | }, 248 | "socket.io-client": { 249 | "version": "2.2.0", 250 | "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.2.0.tgz", 251 | "integrity": "sha512-56ZrkTDbdTLmBIyfFYesgOxsjcLnwAKoN4CiPyTVkMQj3zTUh0QAx3GbvIvLpFEOvQWu92yyWICxB0u7wkVbYA==", 252 | "requires": { 253 | "backo2": "1.0.2", 254 | "base64-arraybuffer": "0.1.5", 255 | "component-bind": "1.0.0", 256 | "component-emitter": "1.2.1", 257 | "debug": "~3.1.0", 258 | "engine.io-client": "~3.3.1", 259 | "has-binary2": "~1.0.2", 260 | "has-cors": "1.1.0", 261 | "indexof": "0.0.1", 262 | "object-component": "0.0.3", 263 | "parseqs": "0.0.5", 264 | "parseuri": "0.0.5", 265 | "socket.io-parser": "~3.3.0", 266 | "to-array": "0.1.4" 267 | }, 268 | "dependencies": { 269 | "debug": { 270 | "version": "3.1.0", 271 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 272 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 273 | "requires": { 274 | "ms": "2.0.0" 275 | } 276 | }, 277 | "ms": { 278 | "version": "2.0.0", 279 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 280 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 281 | } 282 | } 283 | }, 284 | "socket.io-parser": { 285 | "version": "3.3.0", 286 | "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", 287 | "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", 288 | "requires": { 289 | "component-emitter": "1.2.1", 290 | "debug": "~3.1.0", 291 | "isarray": "2.0.1" 292 | }, 293 | "dependencies": { 294 | "debug": { 295 | "version": "3.1.0", 296 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 297 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 298 | "requires": { 299 | "ms": "2.0.0" 300 | } 301 | }, 302 | "ms": { 303 | "version": "2.0.0", 304 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 305 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 306 | } 307 | } 308 | }, 309 | "to-array": { 310 | "version": "0.1.4", 311 | "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", 312 | "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" 313 | }, 314 | "ws": { 315 | "version": "6.1.4", 316 | "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", 317 | "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", 318 | "requires": { 319 | "async-limiter": "~1.0.0" 320 | } 321 | }, 322 | "xmlhttprequest-ssl": { 323 | "version": "1.5.5", 324 | "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", 325 | "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" 326 | }, 327 | "yeast": { 328 | "version": "0.1.2", 329 | "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", 330 | "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" 331 | } 332 | } 333 | } 334 | -------------------------------------------------------------------------------- /server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "socket.io": "" 4 | } 5 | } 6 | --------------------------------------------------------------------------------