├── .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 | 
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 |
--------------------------------------------------------------------------------