first commit

This commit is contained in:
Marklogo 2024-04-01 01:56:05 +02:00
commit 5c64b4e147
102 changed files with 10838 additions and 0 deletions

25
.eslintrc.js Normal file
View File

@ -0,0 +1,25 @@
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
tsconfigRootDir: __dirname,
sourceType: 'module',
},
plugins: ['@typescript-eslint/eslint-plugin'],
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
],
root: true,
env: {
node: true,
jest: true,
},
ignorePatterns: ['.eslintrc.js'],
rules: {
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
},
};

35
.gitignore vendored Normal file
View File

@ -0,0 +1,35 @@
# compiled output
/dist
/node_modules
# Logs
logs
*.log
npm-debug.log*
pnpm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# OS
.DS_Store
# Tests
/coverage
/.nyc_output
# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

4
.prettierrc Normal file
View File

@ -0,0 +1,4 @@
{
"singleQuote": true,
"trailingComma": "all"
}

73
README.md Normal file
View File

@ -0,0 +1,73 @@
<p align="center">
<a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo-small.svg" width="200" alt="Nest Logo" /></a>
</p>
[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
[circleci-url]: https://circleci.com/gh/nestjs/nest
<p align="center">A progressive <a href="http://nodejs.org" target="_blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
<p align="center">
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/dm/@nestjs/common.svg" alt="NPM Downloads" /></a>
<a href="https://circleci.com/gh/nestjs/nest" target="_blank"><img src="https://img.shields.io/circleci/build/github/nestjs/nest/master" alt="CircleCI" /></a>
<a href="https://coveralls.io/github/nestjs/nest?branch=master" target="_blank"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#9" alt="Coverage" /></a>
<a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
<a href="https://opencollective.com/nest#backer" target="_blank"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
<a href="https://paypal.me/kamilmysliwiec" target="_blank"><img src="https://img.shields.io/badge/Donate-PayPal-ff3f59.svg"/></a>
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://img.shields.io/badge/Support%20us-Open%20Collective-41B883.svg" alt="Support us"></a>
<a href="https://twitter.com/nestframework" target="_blank"><img src="https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow"></a>
</p>
<!--[![Backers on Open Collective](https://opencollective.com/nest/backers/badge.svg)](https://opencollective.com/nest#backer)
[![Sponsors on Open Collective](https://opencollective.com/nest/sponsors/badge.svg)](https://opencollective.com/nest#sponsor)-->
## Description
[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
## Installation
```bash
$ npm install
```
## Running the app
```bash
# development
$ npm run start
# watch mode
$ npm run start:dev
# production mode
$ npm run start:prod
```
## Test
```bash
# unit tests
$ npm run test
# e2e tests
$ npm run test:e2e
# test coverage
$ npm run test:cov
```
## Support
Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
## Stay in touch
- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
- Website - [https://nestjs.com](https://nestjs.com/)
- Twitter - [@nestframework](https://twitter.com/nestframework)
## License
Nest is [MIT licensed](LICENSE).

8
nest-cli.json Normal file
View File

@ -0,0 +1,8 @@
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"deleteOutDir": true
}
}

8983
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

76
package.json Normal file
View File

@ -0,0 +1,76 @@
{
"name": "battleshipserver",
"version": "0.0.1",
"description": "",
"author": "",
"private": true,
"license": "UNLICENSED",
"scripts": {
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@nestjs/common": "^10.0.0",
"@nestjs/core": "^10.0.0",
"@nestjs/mapped-types": "*",
"@nestjs/platform-express": "^10.0.0",
"@nestjs/platform-socket.io": "^10.3.6",
"@nestjs/serve-static": "^4.0.1",
"@nestjs/websockets": "^10.3.6",
"@types/uuid": "^9.0.8",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1",
"socket.io": "^4.7.5",
"uuid": "^9.0.1"
},
"devDependencies": {
"@nestjs/cli": "^10.0.0",
"@nestjs/schematics": "^10.0.0",
"@nestjs/testing": "^10.0.0",
"@types/express": "^4.17.17",
"@types/jest": "^29.5.2",
"@types/node": "^20.3.1",
"@types/supertest": "^2.0.12",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"eslint": "^8.42.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
"jest": "^29.5.0",
"prettier": "^3.0.0",
"source-map-support": "^0.5.21",
"supertest": "^6.3.3",
"ts-jest": "^29.1.0",
"ts-loader": "^9.4.3",
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.1.3"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "src",
"testRegex": ".*\\.spec\\.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"collectCoverageFrom": [
"**/*.(t|j)s"
],
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}

Binary file not shown.

BIN
public/assets/barcos.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

BIN
public/assets/barcos.xcf Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

View File

@ -0,0 +1,5 @@
[.ShellClassInfo]
InfoTip=This folder is shared online.
IconFile=C:\Program Files (x86)\Google\Drive\googledrivesync.exe
IconIndex=12

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,452 @@
{"frames": {
"ship_big_gun.png":
{
"frame": {"x":660,"y":70,"w":32,"h":60},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":32,"h":60},
"sourceSize": {"w":32,"h":60}
},
"ship_big_gun_destroyed.png":
{
"frame": {"x":654,"y":337,"w":32,"h":60},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":32,"h":60},
"sourceSize": {"w":32,"h":60}
},
"ship_big_gun_dual.png":
{
"frame": {"x":660,"y":2,"w":32,"h":66},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":32,"h":66},
"sourceSize": {"w":32,"h":66}
},
"ship_big_gun_dual_destroyed.png":
{
"frame": {"x":674,"y":467,"w":32,"h":66},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":32,"h":66},
"sourceSize": {"w":32,"h":66}
},
"ship_big_gun_dual_hit.png":
{
"frame": {"x":674,"y":399,"w":32,"h":66},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":32,"h":66},
"sourceSize": {"w":32,"h":66}
},
"ship_big_gun_hit.png":
{
"frame": {"x":620,"y":337,"w":32,"h":60},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":32,"h":60},
"sourceSize": {"w":32,"h":60}
},
"ship_gun_base.png":
{
"frame": {"x":720,"y":92,"w":24,"h":24},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":24,"h":24},
"sourceSize": {"w":24,"h":24}
},
"ship_gun_base_big.png":
{
"frame": {"x":674,"y":535,"w":28,"h":28},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":28,"h":28},
"sourceSize": {"w":28,"h":28}
},
"ship_gun_base_big_destroyed.png":
{
"frame": {"x":630,"y":755,"w":28,"h":28},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":28,"h":28},
"sourceSize": {"w":28,"h":28}
},
"ship_gun_base_dark.png":
{
"frame": {"x":694,"y":101,"w":24,"h":24},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":24,"h":24},
"sourceSize": {"w":24,"h":24}
},
"ship_gun_base_dark_destroyed.png":
{
"frame": {"x":686,"y":190,"w":24,"h":24},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":24,"h":24},
"sourceSize": {"w":24,"h":24}
},
"ship_gun_base_destroyed.png":
{
"frame": {"x":660,"y":190,"w":24,"h":24},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":24,"h":24},
"sourceSize": {"w":24,"h":24}
},
"ship_gun_dual_gray.png":
{
"frame": {"x":676,"y":274,"w":34,"h":56},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":34,"h":56},
"sourceSize": {"w":34,"h":56}
},
"ship_gun_dual_gray_destroyed.png":
{
"frame": {"x":676,"y":216,"w":34,"h":56},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":34,"h":56},
"sourceSize": {"w":34,"h":56}
},
"ship_gun_dual_gray_hit.png":
{
"frame": {"x":660,"y":132,"w":34,"h":56},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":34,"h":56},
"sourceSize": {"w":34,"h":56}
},
"ship_gun_dual_green.png":
{
"frame": {"x":712,"y":50,"w":32,"h":40},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":32,"h":40},
"sourceSize": {"w":32,"h":40}
},
"ship_gun_dual_green_destroyed.png":
{
"frame": {"x":360,"y":789,"w":32,"h":40},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":32,"h":40},
"sourceSize": {"w":32,"h":40}
},
"ship_gun_dual_green_hit.png":
{
"frame": {"x":326,"y":789,"w":32,"h":40},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":32,"h":40},
"sourceSize": {"w":32,"h":40}
},
"ship_gun_gray.png":
{
"frame": {"x":714,"y":127,"w":16,"h":40},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":16,"h":40},
"sourceSize": {"w":16,"h":40}
},
"ship_gun_gray_destroyed.png":
{
"frame": {"x":712,"y":175,"w":16,"h":40},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":16,"h":40},
"sourceSize": {"w":16,"h":40}
},
"ship_gun_gray_hit.png":
{
"frame": {"x":730,"y":2,"w":16,"h":40},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":16,"h":40},
"sourceSize": {"w":16,"h":40}
},
"ship_gun_green.png":
{
"frame": {"x":694,"y":53,"w":16,"h":46},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":16,"h":46},
"sourceSize": {"w":16,"h":46}
},
"ship_gun_green_destroyed.png":
{
"frame": {"x":712,"y":2,"w":16,"h":46},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":16,"h":46},
"sourceSize": {"w":16,"h":46}
},
"ship_gun_green_hit.png":
{
"frame": {"x":696,"y":127,"w":16,"h":46},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":16,"h":46},
"sourceSize": {"w":16,"h":46}
},
"ship_gun_huge.png":
{
"frame": {"x":640,"y":477,"w":32,"h":76},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":32,"h":76},
"sourceSize": {"w":32,"h":76}
},
"ship_gun_huge_destroyed.png":
{
"frame": {"x":640,"y":399,"w":32,"h":76},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":32,"h":76},
"sourceSize": {"w":32,"h":76}
},
"ship_gun_huge_hit.png":
{
"frame": {"x":630,"y":677,"w":32,"h":76},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":32,"h":76},
"sourceSize": {"w":32,"h":76}
},
"ship_gun_red.png":
{
"frame": {"x":694,"y":2,"w":16,"h":49},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":16,"h":49},
"sourceSize": {"w":16,"h":49}
},
"ship_gun_red_destroyed.png":
{
"frame": {"x":706,"y":332,"w":16,"h":49},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":16,"h":49},
"sourceSize": {"w":16,"h":49}
},
"ship_gun_red_hit.png":
{
"frame": {"x":688,"y":332,"w":16,"h":49},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":16,"h":49},
"sourceSize": {"w":16,"h":49}
},
"ship_large_body.png":
{
"frame": {"x":450,"y":419,"w":122,"h":368},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":122,"h":368},
"sourceSize": {"w":122,"h":368}
},
"ship_large_body_destroyed.png":
{
"frame": {"x":326,"y":419,"w":122,"h":368},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":122,"h":368},
"sourceSize": {"w":122,"h":368}
},
"ship_medium_body.png":
{
"frame": {"x":194,"y":836,"w":62,"h":179},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":62,"h":179},
"sourceSize": {"w":62,"h":179}
},
"ship_medium_body_b.png":
{
"frame": {"x":130,"y":836,"w":62,"h":179},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":62,"h":179},
"sourceSize": {"w":62,"h":179}
},
"ship_medium_body_b_destroyed.png":
{
"frame": {"x":66,"y":836,"w":62,"h":179},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":62,"h":179},
"sourceSize": {"w":62,"h":179}
},
"ship_medium_body_destroyed.png":
{
"frame": {"x":2,"y":836,"w":62,"h":179},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":62,"h":179},
"sourceSize": {"w":62,"h":179}
},
"ship_small_b_body.png":
{
"frame": {"x":630,"y":570,"w":54,"h":105},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":54,"h":105},
"sourceSize": {"w":54,"h":105}
},
"ship_small_body.png":
{
"frame": {"x":574,"y":677,"w":54,"h":105},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":54,"h":105},
"sourceSize": {"w":54,"h":105}
},
"ship_small_body_b_destroyed.png":
{
"frame": {"x":574,"y":570,"w":54,"h":105},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":54,"h":105},
"sourceSize": {"w":54,"h":105}
},
"ship_small_body_destroyed.png":
{
"frame": {"x":620,"y":230,"w":54,"h":105},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":54,"h":105},
"sourceSize": {"w":54,"h":105}
},
"water_ripple_big_000.png":
{
"frame": {"x":326,"y":2,"w":160,"h":415},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":160,"h":415},
"sourceSize": {"w":160,"h":415}
},
"water_ripple_big_001.png":
{
"frame": {"x":164,"y":419,"w":160,"h":415},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":160,"h":415},
"sourceSize": {"w":160,"h":415}
},
"water_ripple_big_002.png":
{
"frame": {"x":164,"y":2,"w":160,"h":415},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":160,"h":415},
"sourceSize": {"w":160,"h":415}
},
"water_ripple_big_003.png":
{
"frame": {"x":2,"y":419,"w":160,"h":415},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":160,"h":415},
"sourceSize": {"w":160,"h":415}
},
"water_ripple_big_004.png":
{
"frame": {"x":2,"y":2,"w":160,"h":415},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":160,"h":415},
"sourceSize": {"w":160,"h":415}
},
"water_ripple_medium_000.png":
{
"frame": {"x":574,"y":2,"w":84,"h":226},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":84,"h":226},
"sourceSize": {"w":84,"h":226}
},
"water_ripple_medium_001.png":
{
"frame": {"x":488,"y":2,"w":84,"h":226},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":84,"h":226},
"sourceSize": {"w":84,"h":226}
},
"water_ripple_medium_002.png":
{
"frame": {"x":566,"y":789,"w":84,"h":226},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":84,"h":226},
"sourceSize": {"w":84,"h":226}
},
"water_ripple_medium_003.png":
{
"frame": {"x":480,"y":789,"w":84,"h":226},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":84,"h":226},
"sourceSize": {"w":84,"h":226}
},
"water_ripple_medium_004.png":
{
"frame": {"x":394,"y":789,"w":84,"h":226},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":84,"h":226},
"sourceSize": {"w":84,"h":226}
},
"water_ripple_small_000.png":
{
"frame": {"x":574,"y":400,"w":64,"h":168},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":64,"h":168},
"sourceSize": {"w":64,"h":168}
},
"water_ripple_small_001.png":
{
"frame": {"x":554,"y":230,"w":64,"h":168},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":64,"h":168},
"sourceSize": {"w":64,"h":168}
},
"water_ripple_small_002.png":
{
"frame": {"x":488,"y":230,"w":64,"h":168},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":64,"h":168},
"sourceSize": {"w":64,"h":168}
},
"water_ripple_small_003.png":
{
"frame": {"x":324,"y":836,"w":64,"h":168},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":64,"h":168},
"sourceSize": {"w":64,"h":168}
},
"water_ripple_small_004.png":
{
"frame": {"x":258,"y":836,"w":64,"h":168},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":64,"h":168},
"sourceSize": {"w":64,"h":168}
}},
"meta": {
"app": "http://www.texturepacker.com",
"version": "1.0",
"image": "water_units.png",
"format": "RGBA8888",
"size": {"w":1024,"h":1024},
"scale": "1",
"smartupdate": "$TexturePacker:SmartUpdate:0588f1382f7fc792c1ff1dac58116cb7$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

26
public/batalla.html Normal file
View File

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tabler/icons-webfont@2.44.0/tabler-icons.min.css">
<link rel="stylesheet" href="stylegame.css">
<title>BattleShip</title>
</head>
<body>
<div id="container">
<div id="sub-container">
<canvas id="mapa" tabindex="0"></canvas>
</div>
<div id="sub-container">
<canvas id="minimapa" tabindex="1"></canvas>
<textarea id="chat" readonly>Battleship</textarea>
<input type="text" name="" id="">
</div>
</div>
</body>
<script src="socket.io/socket.io.js"></script>
<script type="module" src="./js_game/battleship.js"></script>
</html>

32
public/index.html Normal file
View File

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tabler/icons-webfont@2.44.0/tabler-icons.min.css">
<link rel="stylesheet" href="style.css">
<title>BattleShip</title>
</head>
<body>
<div class="container" style="flex-direction: column; align-items: center; justify-content: center; gap: 0;">
<div>
<h1 style="font-size: 7rem;display: inline;">BattleShip</h1>
<i style="font-size: 2.5rem;"class="ti ti-medal-2"></i>
<i style="font-size: 2.5rem;"class="ti ti-medal-2"></i>
</div>
<form id="login-form" onsubmit="">
<div class="container_col" style="min-width: 20rem;">
<label for="username">Introduce tu nick de batalla</label>
<input id="login-input" name="nick" type="text" autocomplete="off" autocorrect="off" autocapitalize="none"
spellcheck="false" placeholder="Nick..." required>
<input type="submit" value="Conectar">
</div>
</form>
</div>
<script src="socket.io/socket.io.js"></script>
<script src="./js/login.js"></script>
</body>
</html>

23
public/js/login.js Normal file
View File

@ -0,0 +1,23 @@
const socket = io('/login');
const form = document.querySelector('#login-form');
const input = document.querySelector('#login-input');
const userId = localStorage.getItem('userId');
// Función para redirigir a la página 'salageneral.html'
const redirectToGeneralPage = () => {
window.location.href = 'salageneral.html';
};
if (userId) redirectToGeneralPage();
// Escucha el evento de envío del formulario
form.addEventListener('submit', (e) => {
e.preventDefault();
const nick = input.value.trim();
if (nick) {
socket.emit('login', nick, (userInfo) => {
localStorage.setItem('userId', userInfo);
redirectToGeneralPage();
});
}
});

192
public/js/salaespera.js Normal file
View File

@ -0,0 +1,192 @@
class ListaUsuarios {
_usuario = {};
_usuarios = [];
constructor(uuidUsuario, usuarios) {
this._usuario = usuarios.find((usuario) => usuario.uuid === uuidUsuario);
this._usuarios = usuarios.filter((usuario) => usuario.uuid !== uuidUsuario);
}
get usuario() {
return this._usuario;
}
get usuariosConectados() {
return this._usuarios
.filter((usuario) => usuario.conectado)
.sort((a, b) => a.nickname.localeCompare(b.nickname));
}
get usuariosDesconectados() {
return this._usuarios
.filter((usuario) => !usuario.conectado)
.sort((a, b) => a.nickname.localeCompare(b.nickname));
}
actualizaUsuario(usuario) {
const user = this.obtenerUsuarioPorUuid(usuario.uuid);
if (user) {
user.conectado = usuario.conectado;
} else {
this._usuarios.push(usuario);
}
}
obtenerUsuarioPorUuid(uuid) {
return this._usuarios.find((usuario) => usuario.uuid === uuid);
}
}
class ListaPartidas {
_partidas = [];
agregarPartida(partida) {
this._partidas.push(partida);
}
get partidasAbiertas() {
return this._partidas.filter((partida) => partida.abierta);
}
}
const usersConnectUlEl = document.querySelector('#users_connect');
const usersDisconnectUlEl = document.querySelector('#users_disconnect');
const partidasAbiertasEl = document.querySelector('#partidas_abiertas');
const partidasProcesoEl = document.querySelector('#tus_partidas');
const chat = document.getElementById('logchat');
const userId = localStorage.getItem('userId');
const socket = io('/salachat', { closeOnBeforeunload: true, auth: { userId } });
let listaUsuarios;
let listaPartidas = new ListaPartidas();
function unirse(data) {
console.log(data);
}
// Funciones que modifican el DOM
// Añadir lista de usuarios al DOM
function agregarUsuarioToLista(usuario, listaElemento, claseCSS) {
const liUsuario = document.createElement('li');
liUsuario.innerHTML = usuario.nickname;
liUsuario.classList.add(claseCSS);
listaElemento.appendChild(liUsuario);
}
function listarUsuarios() {
usersConnectUlEl.innerHTML = '';
usersDisconnectUlEl.innerHTML = '';
const miUsuario = listaUsuarios.usuario;
agregarUsuarioToLista(miUsuario, usersConnectUlEl, 'spanNickPropio');
const usuariosConectados = listaUsuarios.usuariosConectados;
usuariosConectados.forEach((usuario) => {
agregarUsuarioToLista(usuario, usersConnectUlEl, 'spanNick');
});
const usuariosDesconectados = listaUsuarios.usuariosDesconectados;
usuariosDesconectados.forEach((usuario) => {
agregarUsuarioToLista(usuario, usersDisconnectUlEl, 'spanNickOffline');
});
}
function listarPartidasAbiertas() {
listaPartidas.partidasAbiertas.forEach((partida) => {
cardGameHTML(partida.nickJugadorA, partida.uuid);
});
}
// Añadir msg al chat
function agregaMsg({ uuid, msg }) {
const spanUser = document.createElement('span');
const spanMsg = document.createElement('span');
if (userId === uuid) {
spanUser.classList.add('spanNickPropio');
spanUser.textContent = `Tú: `;
spanMsg.textContent = msg;
} else {
spanUser.classList.add('spanNick');
spanUser.textContent = `${listaUsuarios.obtenerUsuarioPorUuid(uuid).nickname}: `;
spanMsg.textContent = msg;
}
const linea = document.createElement('p');
linea.appendChild(spanUser);
linea.appendChild(spanMsg);
chat.appendChild(linea);
logchat.scrollTop = logchat.scrollHeight;
}
//Añadir mensaje del servidor
function agregaMsgBroadcast(msg) {
const spanMsg = document.createElement('span');
spanMsg.textContent = msg;
spanMsg.classList.add('broadcastMsg');
const linea = document.createElement('p');
linea.appendChild(spanMsg);
chat.appendChild(linea);
logchat.scrollTop = logchat.scrollHeight;
}
const cardGameHTML = (nickname, game_id) => {
var cardGameDiv = document.createElement('div');
cardGameDiv.classList.add('cardGame');
cardGameDiv.innerHTML =
nickname === listaUsuarios.usuario.nickname
? `<span>${nickname}</span>
<span>VS</span>
<span>Esperando rival</button>
`
: `<span>${nickname}</span>
<span>VS</span>
<button onclick="unirse('${game_id}')">Unirse</button>
`;
partidasAbiertasEl.appendChild(cardGameDiv);
};
// Logica de negocio de la aplicacion
//Entra a la sala
const entraSala = (usuarios) => {
listaUsuarios = new ListaUsuarios(userId, usuarios);
listarUsuarios();
};
// Actualiza info Usuarios
const actualizaUsuarios = (usuario) => {
listaUsuarios.actualizaUsuario(usuario);
listarUsuarios();
usuario.conectado
? agregaMsgBroadcast(`${usuario.nickname} se ha conectado`)
: agregaMsgBroadcast(`${usuario.nickname} se ha desconectado`);
};
const agregaPartida = (partida) => {
partidasAbiertasEl.innerHTML = '';
listaPartidas.agregarPartida(partida);
listarPartidasAbiertas();
};
const onCloseClick = () => {
localStorage.removeItem('userId');
window.location.replace('/');
};
// Cerrar sesión
const cerrarSesion = (reason) => {
if (reason === 'io server disconnect') {
localStorage.removeItem('userId');
window.location.replace('/');
}
};
// Enviar mensaje
function enviarMensaje(event) {
if (event.key === 'Enter') {
const mensaje = event.target.value.trim();
if (mensaje != '') {
socket.emit('chatMsg', mensaje);
}
event.target.value = '';
}
}
// Crear partida
const crearPartida = () => {
socket.emit('creaPartida');
};
// Manejadores de eventos del socket
socket.on('onConnectRoom', entraSala);
socket.on('onUserConnectRoom', actualizaUsuarios);
socket.on('chatMsg', agregaMsg);
socket.on('onUserDisconnectRoom', actualizaUsuarios);
socket.on('disconnect', cerrarSesion);
socket.on('on_create_partida', agregaPartida);
// const url = '/batalla.html?game_id=' + encodeURIComponent(partida.uuid);
// window.open(url, '_blank');

View File

@ -0,0 +1,6 @@
const urlParams = new URLSearchParams(window.location.search);
const gameId = urlParams.get('game_id');
const userId = localStorage.getItem('userId');
const socket = io('/batalla', { closeOnBeforeunload: true, auth: { userId, gameId } });

62
public/salageneral.html Normal file
View File

@ -0,0 +1,62 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tabler/icons-webfont@2.44.0/tabler-icons.min.css">
<link rel="stylesheet" href="style.css">
<title>BattleShip</title>
</head>
<body>
<div class="container">
<div class="container_col" style="max-width: 13rem;">
<h3 style="border-bottom: 2px solid #2c5364;">Lista de usuarios</h3>
<div class="container_col" style="border: none; padding: 0;">
<h4>Conectados</h4>
<ul id="users_connect">
</ul>
<br>
<h4>Desconectados</h4>
<ul id="users_disconnect">
</ul>
</div>
<button onclick="onCloseClick();">Cerrar</button>
</div>
<div class="container_col" style="border: none;">
<div id="cabecera" style="display: flex; align-items: center; justify-content: space-between; ">
<div>
<h1 style="font-size: 5rem; display: inline;">Battleship</h1>
<i style="font-size: 2rem;"class="ti ti-medal-2"></i>
<i style="font-size: 2rem;"class="ti ti-medal-2"></i>
</div>
<button onclick="crearPartida();">Crear Partida</button>
</div>
<fieldset id="partidas_abiertas" class="container_games">
<legend>Partidas abiertas</legend>
</fieldset>
<fieldset id="tus_partidas" class="container_games">
<legend>Partidas</legend>
<div class="cardGame">
<span>Marklogo</span>
<span>VS</span>
<button click="">Unirse</button>
</div>
</fieldset>
<div class="container_col" style="overflow-y: hidden;">
<div id="logchat" class="container_col" style="overflow-y: auto; border: none;">
</div>
<input type="text" id="chatinput" onkeyup="enviarMensaje(event)">
</div>
</div>
</div>
<script src="socket.io/socket.io.js"></script>
<script src="./js/salaespera.js"></script>
</body>
</html>

163
public/style.css Normal file
View File

@ -0,0 +1,163 @@
@font-face {
font-family: 'ITC Machine Std Bold';
src: url('./assets/ITC Machine Std Bold.otf') format('opentype');
}
* {
box-sizing: border-box;
min-width: 0;
}
ul,
li {
list-style: square;
margin: 0;
margin-left: 0.8rem;
padding: 0;
}
li {
font-size: small;
color: wheat;
}
h1,
h2,
h3,
h4 {
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
min-width: 800px;
margin: 0;
padding: 0;
}
body {
padding: 1rem;
background: linear-gradient(to bottom right, #0f2027, #203a43, #2c5364);
color: #bf360c;
font-family: 'ITC Machine Std Bold', sans-serif;
}
.container {
height: 100%;
display: flex;
flex-direction: row;
gap: 0.5rem;
}
.container_row,
.container_games {
display: flex;
height: 100%;
gap: 0.2rem;
border: 3px solid red;
padding: 0.4rem;
border: 4px solid #2c5364;
border-radius: 10px;
}
.container_col {
display: flex;
flex-direction: column;
gap: 0.4rem;
padding: 1rem;
width: 100%;
height: 100%;
border: 4px solid #2c5364;
border-radius: 10px;
}
.container_games {
max-height: 9rem;
min-height: 9rem;
padding: 1rem;
gap: 1rem;
align-items: center;
flex-wrap: wrap;
flex-grow: 1;
overflow-y: auto;
}
input[type='submit'],
button {
padding: 0.5rem 1rem;
font-size: 1rem;
border: none;
border-radius: 0.4rem;
background-color: #ff5722; /* Color de fondo naranja */
color: white; /* Color del texto blanco */
cursor: pointer; /* Cambia el cursor al pasar sobre el botón */
transition: background-color 0.3s ease; /* Transición suave al cambiar de color */
}
input[type='submit']:hover,
button:hover {
background-color: #e64a19; /* Color de fondo naranja más oscuro al pasar el cursor */
}
input[type='submit']:active,
button:active {
background-color: #bf360c; /* Color de fondo naranja más oscuro al hacer clic */
}
.cardGame button {
padding: 0 0.4rem;
font-size: medium;
width: 100%;
border-radius: 4px;
}
.cardGame {
min-width: 140px;
width: 140px;
height: 80px;
display: flex;
flex-direction: column;
justify-content: space-between;
border-radius: 10px;
background-color: #162930;
text-align: center;
align-items: center;
padding: 0.4rem;
font-size: small;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
border: 1px solid rgba(0, 0, 0, 0.2);
}
#login-input,
#chatinput {
font-family: 'roboto', sans-serif;
padding: 0.4rem;
font-weight: bold;
border-radius: 0.4rem;
background-color: transparent;
color: wheat;
outline: none;
}
#logchat {
min-width: 15rem;
width: 100%;
max-height: 100%;
padding: 0.1rem;
padding-right: 0.4rem;
font-family: 'roboto', sans-serif;
font-size: small;
font-weight: bold;
border-radius: 0.4rem;
background-color: transparent;
overflow-y: auto;
}
#logchat p {
margin: 0;
}
.broadcastMsg {
display: block;
text-align: right;
font-size: x-small;
color: #72d5ff;
}
.spanNickPropio {
color: #f8c51c;
}
.spanNick {
color: #87db18;
}
.spanNickOffline {
color: #2c5364;
}

115
public/stylegame.css Normal file
View File

@ -0,0 +1,115 @@
@font-face {
font-family: 'ITC Machine Std Bold';
src: url('./assets/ITC Machine Std Bold.otf') format('opentype');
}
* {
box-sizing: border-box;
min-width: 0;
}
h1,h2,h3,h4 {
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
body {
padding: 1rem;
background: linear-gradient(to bottom right, #0f2027, #203a43, #2c5364);
color: white;
font-family: 'ITC Machine Std Bold', sans-serif;
text-align: center;
}
#container {
height: 100%;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 0.5rem;
}
#sub-container {
height: 648px;
display: flex;
flex-direction: column;
border: 4px solid #2c5364;
border-radius: 10px;
overflow: hidden;
}
#input-container {
display: flex;
padding: 1rem;
gap: 0.4rem;
max-width: fit-content;
flex-direction: column;
border: 4px solid #2c5364;
border-radius: 10px;
overflow: hidden;
}
/* Estilo del botón */
#input-container input[type="button"] {
padding: 0.5rem 1rem;
font-size: 1rem;
border: none;
border-radius: 0.4rem;
background-color: #ff5722; /* Color de fondo naranja */
color: white; /* Color del texto blanco */
cursor: pointer; /* Cambia el cursor al pasar sobre el botón */
transition: background-color 0.3s ease; /* Transición suave al cambiar de color */
}
/* Estilo del botón al pasar el cursor */
#input-container input[type="button"]:hover {
background-color: #e64a19; /* Color de fondo naranja más oscuro al pasar el cursor */
}
/* Estilo del botón al hacer clic */
#input-container input[type="button"]:active {
background-color: #bf360c; /* Color de fondo naranja más oscuro al hacer clic */
}
#mapa {
width: 640px;
height: 640px;
background-color: #2c5364;
}
#minimapa {
width: 320px;
height: 320px;
flex-shrink: 0;
background-color: #2c5364;
}
#chat {
font-family: 'ITC Machine Std Bold', sans-serif;
resize: none;
width: 320px;
height: 100%;
background-color: transparent;
color: antiquewhite;
}
.basic-input{
font-family: 'ITC Machine Std Bold', sans-serif;
padding: 0.4rem;
font-size: larger;
border-radius: 0.4rem;
background-color: #2c5364;
color:wheat;
outline: none;
}

20
src/app.module.ts Normal file
View File

@ -0,0 +1,20 @@
import { join } from 'path';
import { Module } from '@nestjs/common';
import { ServeStaticModule } from '@nestjs/serve-static';
import { LoginModule } from './login/login.module';
import { SalaChatModule } from './sala-chat/sala-chat.module';
import { BatallaModule } from './batalla/batalla.module';
@Module({
imports: [
ServeStaticModule.forRoot({
rootPath: join(__dirname, '..', 'public'),
}),
LoginModule,
SalaChatModule,
BatallaModule,
],
controllers: [],
providers: []
})
export class AppModule {}

View File

@ -0,0 +1,19 @@
import { OnGatewayConnection, OnGatewayDisconnect, WebSocketGateway } from '@nestjs/websockets';
import { BatallaService } from './batalla.service';
import { Socket } from 'socket.io';
@WebSocketGateway({ namespace: 'batalla' })
export class BatallaGateway implements OnGatewayConnection, OnGatewayDisconnect {
constructor(private readonly batallaService: BatallaService) {}
handleConnection(client: Socket) {
const {userId,gameId}=client.handshake.auth
}
handleDisconnect(client: Socket) {
}
}

View File

@ -0,0 +1,8 @@
import { Module } from '@nestjs/common';
import { BatallaService } from './batalla.service';
import { BatallaGateway } from './batalla.gateway';
@Module({
providers: [BatallaGateway, BatallaService],
})
export class BatallaModule {}

View File

@ -0,0 +1,4 @@
import { Injectable } from '@nestjs/common';
@Injectable()
export class BatallaService {}

29
src/battleship/barco.ts Normal file
View File

@ -0,0 +1,29 @@
export const BarcoTipo = Object.freeze({
FRAGATA: 1,
DESTRUCTOR: 2,
ACORAZADO: 3,
PORTAAVIONES: 4,
});
export default class Barco {
constructor(
public id: number,
public x: number,
public y: number,
public longitud: number,
public orientacion: string,
public impactos: number = 0,
public destruido = false,
) {}
recibirImpacto() {
this.impactos++;
if (this.impactos >= this.longitud) {
this.destruido = true;
}
}
haSidoDestruido(): boolean {
return this.destruido;
}
}

View File

@ -0,0 +1,57 @@
import Jugador from './jugador';
export default class BattleshipGame{
public jugadorA: Jugador;
public jugadorB: Jugador;
turnoActual: Jugador | null;
constructor(
public idPartida: string,
) {
this.turnoActual = null;
}
setJugadorA(jugador:Jugador){
this.jugadorA=jugador;
}
setJugadorB(jugador:Jugador){
this.jugadorB=jugador;
}
iniciaPartida() {
this.turnoActual = this.jugadorA;
// Iniciar el primer turno
this.realizarTurno();
}
realizarTurno() {
// Realizar las acciones correspondientes al turno actual
// Por ejemplo, mostrar el mapa del turno actual, solicitar un disparo, etc.
// Implementa esta parte según sea necesario
// Luego, alternar el turno al otro jugador
this.turnoActual =
this.turnoActual === this.jugadorA ? this.jugadorB : this.jugadorA;
// Verificar si se ha alcanzado el final del juego
if (this.haFinalizado()) {
this.finalizaPartida();
} else {
// Si no ha finalizado, continuar con el próximo turno
this.realizarTurno();
}
}
haFinalizado(): boolean {
// Aquí debes implementar la lógica para verificar si el juego ha finalizado
// Por ejemplo, si todos los barcos de uno de los jugadores han sido destruidos
// Devuelve true si el juego ha finalizado, de lo contrario, devuelve false
// Implementa esta parte según sea necesario
return false;
}
finalizaPartida() {
// Aquí debes implementar la lógica para finalizar el juego
// Por ejemplo, mostrar el resultado (quién ganó, etc.)
// Implementa esta parte según sea necesario
}
}

49
src/battleship/jugador.ts Normal file
View File

@ -0,0 +1,49 @@
import Barco, { BarcoTipo } from './barco';
import Mapa, { EstadoCelda } from './mapa';
export default class Jugador {
public mapaFlota: Mapa = new Mapa();
public mapaDeAtaques: Mapa = new Mapa();
public jugadorPreparado: boolean = false;
public barcos: Barco[] = [
new Barco(1, 0, 0, BarcoTipo.PORTAAVIONES, 'VERTICAL'),
new Barco(2, 1, 0, BarcoTipo.ACORAZADO, 'VERTICAL'),
new Barco(3, 2, 0, BarcoTipo.ACORAZADO, 'VERTICAL'),
new Barco(4, 3, 0, BarcoTipo.ACORAZADO, 'VERTICAL'),
new Barco(5, 4, 0, BarcoTipo.DESTRUCTOR, 'VERTICAL'),
new Barco(6, 5, 0, BarcoTipo.DESTRUCTOR, 'VERTICAL'),
new Barco(7, 6, 0, BarcoTipo.DESTRUCTOR, 'VERTICAL'),
new Barco(8, 7, 0, BarcoTipo.FRAGATA, 'VERTICAL'),
new Barco(9, 8, 0, BarcoTipo.FRAGATA, 'VERTICAL'),
];
constructor(public nickname: string) {}
prepararFlota(barcos: Barco[]) {
this.barcos = barcos;
this.mapaFlota.setBarcos(this.barcos);
this.jugadorPreparado = true;
}
setBarcos(barcos: Barco[]) {
this.mapaFlota.setBarcos(barcos);
}
realizarDisparo(x: number, y: number, rival: Jugador): boolean {
const acierto = rival.mapaFlota.verificaDisparo(x, y);
this.mapaDeAtaques.marcaDisparo(x,y,acierto ? EstadoCelda.Golpe : EstadoCelda.Agua);
return acierto;
}
haPerdido(): boolean {
for (const barco of this.barcos) {
if (!barco.destruido) {
return false;
}
}
return true;
}
}

68
src/battleship/mapa.ts Normal file
View File

@ -0,0 +1,68 @@
import Barco, { BarcoTipo } from './barco';
export enum EstadoCelda {
Vacio = 0,
Agua = -1,
Golpe = -2,
}
export default class Mapa {
celdas: number[][] = [];
barcosMapa: Map<number, Barco> = new Map<number, Barco>();
constructor() {
for (let i = 0; i < 10; i++) {
this.celdas[i] = [];
for (let j = 0; j < 10; j++) {
this.celdas[i][j] = 0;
}
}
}
setBarcos(barcos: Barco | Barco[]) {
const barcosArray = Array.isArray(barcos) ? barcos : [barcos];
for (const barco of barcosArray) {
const incFila = barco.orientacion === 'VERTICAL' ? 1 : 0;
const incColumna = barco.orientacion === 'HORIZONTAL' ? 1 : 0;
for (let i = 0; i < barco.longitud; i++) {
const fila = barco.y + i * incFila;
const columna = barco.x + i * incColumna;
this.celdas[fila][columna] = barco.id;
}
this.barcosMapa.set(barco.id, barco);
}
}
getEstadoCelda(x: number, y: number): EstadoCelda {
return this.celdas[x][y];
}
getBarcoEnCelda(x: number, y: number): Barco | null {
const barcoId = this.celdas[x][y];
if (barcoId > 0) {
return this.barcosMapa.get(barcoId) || null;
}
return null;
}
marcaDisparo(x:number,y:number,valor:number){
this.celdas[x][y]=valor;
}
getInformacionBarcos(): Barco[] {
return Array.from(this.barcosMapa.values());
}
verificaDisparo(x: number, y: number): boolean {
if (this.celdas[x][y] > 0) {
const barco = this.getBarcoEnCelda(x,y);
if (barco) {
barco.recibirImpacto();
this.celdas[x][y] = EstadoCelda.Golpe;
return true;
}
} else {
this.celdas[x][y] = EstadoCelda.Agua;
}
return false;
}
}

View File

@ -0,0 +1,18 @@
import { OnGatewayConnection, OnGatewayDisconnect, OnGatewayInit, SubscribeMessage, WebSocketGateway } from '@nestjs/websockets';
import { LoginService } from './login.service';
import { Socket } from 'socket.io';
@WebSocketGateway({namespace:'login'})
export class LoginGateway implements OnGatewayConnection, OnGatewayDisconnect{
constructor(private readonly loginService: LoginService) {}
handleConnection(client: any, ...args: any[]) {
}
handleDisconnect(client: any) {
}
@SubscribeMessage('login')
handleLogin(client: Socket, nick: string){
return this.loginService.login(nick);
}
}

12
src/login/login.module.ts Normal file
View File

@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { LoginService } from './login.service';
import { LoginGateway } from './login.gateway';
import { SharedModule } from 'src/shared/shared.module';
@Module({
imports:[SharedModule],
providers: [LoginGateway,LoginService],
})
export class LoginModule {}

View File

@ -0,0 +1,18 @@
import { Injectable } from '@nestjs/common';
import { UsuariosService } from 'src/shared/usuarios.service';
@Injectable()
export class LoginService {
constructor(private readonly usuariosService: UsuariosService){}
login(nickname:string){
const usuario=this.usuariosService.obtenerUsuarioPorNickname(nickname);
if (usuario){
return usuario.uuid
} else {
return this.usuariosService.creaUsuario(nickname);
}
}
}

8
src/main.ts Normal file
View File

@ -0,0 +1,8 @@
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();

View File

@ -0,0 +1,61 @@
import {
OnGatewayConnection,
OnGatewayDisconnect,
SubscribeMessage,
WebSocketGateway,
WebSocketServer,
} from '@nestjs/websockets';
import { SalaChatService } from './sala-chat.service';
import { Server, Socket } from 'socket.io';
@WebSocketGateway({ namespace: 'salachat' })
export class SalaChatGateway
implements OnGatewayConnection, OnGatewayDisconnect
{
@WebSocketServer()
server: Server;
constructor(private readonly salaChatService: SalaChatService) {}
handleConnection(client: Socket) {
const userId = client.handshake.auth.userId;
const userConectado = this.salaChatService.conectaUsuarioUUID(userId);
if (userConectado){
client.join('chat_general');
client.emit('onConnectRoom',this.salaChatService.listaUsuariosSinPartidas);
client.broadcast.to('chat_general').emit('onUserConnectRoom',userConectado);
}else{
client.disconnect();
}
}
handleDisconnect(client: Socket) {
const userId = client.handshake.auth.userId;
const userDesconectado = this.salaChatService.desconectaUsuarioUUID(userId);
if (userDesconectado){
client.broadcast.to('chat_general').emit('onUserDisconnectRoom',userDesconectado);
}
client.leave('chat_general');
}
@SubscribeMessage('chatMsg')
handleMsg(client: Socket, msg: string) {
const userId = client.handshake.auth.userId;
const user = this.salaChatService.getUsuarioUUID(userId);
if (user) {
this.server.to('chat_general').emit('chatMsg', { uuid:userId, msg });
} else {
client.disconnect();
}
}
sendBroadcastMsg(msg:string){
this.server.to('chat_general').emit('broadcastMsg',msg);
}
@SubscribeMessage('creaPartida')
handleCreaPartida(client: Socket) {
const userId = client.handshake.auth.userId;
const partida= this.salaChatService.creaPartida(userId);
this.server.to('chat_general').emit('on_create_partida',partida);
}
}

View File

@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';
import { SalaChatService } from './sala-chat.service';
import { SalaChatGateway } from './sala-chat.gateway';
import { SharedModule } from 'src/shared/shared.module';
@Module({
imports:[SharedModule],
providers: [SalaChatGateway, SalaChatService],
})
export class SalaChatModule {}

View File

@ -0,0 +1,58 @@
import { Injectable } from '@nestjs/common';
import { Partida, PartidasService } from 'src/shared/partidas.service';
import { UsuariosService } from 'src/shared/usuarios.service';
@Injectable()
export class SalaChatService {
constructor(
private readonly usuariosService: UsuariosService,
private readonly partidasService: PartidasService,
) {}
get listaUsuariosSinPartidas() {
return Array.from(this.usuariosService.usuarios.values()).map(
({ uuid, nickname, conectado }) => ({
uuid,
nickname,
conectado,
}),
);
}
getUsuarioUUID(uuid: string) {
return this.usuariosService.getUsuarioByUUID(uuid);
}
conectaUsuarioUUID(uuid: string) {
const user = this.usuariosService.getUsuarioByUUID(uuid);
if (user) {
user.conectado = true;
return {
uuid: user.uuid,
nickname: user.nickname,
conectado: user.conectado,
};
} else {
return undefined;
}
}
desconectaUsuarioUUID(uuid: string) {
const user = this.usuariosService.getUsuarioByUUID(uuid);
if (user) {
user.conectado = false;
return {
uuid: user.uuid,
nickname: user.nickname,
conectado: user.conectado,
};
} else {
return undefined;
}
}
creaPartida(uuidJugadorCreador: string) {
const partida = this.partidasService.creaPartida(uuidJugadorCreador);
this.usuariosService.addPartidaToUsuario(uuidJugadorCreador, partida);
return partida;
}
}

View File

@ -0,0 +1,35 @@
import { v4 as uuidv4 } from 'uuid';
import { Injectable } from '@nestjs/common';
import { UsuariosService } from './usuarios.service';
export class Partida {
constructor(
public uuid: string,
public uuidJugadorA: string,
public nickJugadorA: string = '',
public uuidJugadorB: string = null,
public nickJugadorB: string = null,
public abierta: boolean = true,
) {}
}
@Injectable()
export class PartidasService {
private _partidas: Map<string, Partida> = new Map<string, Partida>();
constructor(private readonly usuariosService: UsuariosService) {}
get partidasAbiertas(): Partida[] {
return Array.from(this._partidas.values()).filter(
(partida) => partida.abierta,
);
}
creaPartida(uuidJugadorA: string) {
const uuid = uuidv4();
const nickJugadorA=this.usuariosService.usuarios.get(uuidJugadorA).nickname;
const partida = new Partida(uuid, uuidJugadorA,nickJugadorA);
this._partidas.set(uuid, partida);
return partida;
}
}

View File

@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { UsuariosService } from './usuarios.service';
import { PartidasService } from './partidas.service';
@Module({
providers:[UsuariosService, PartidasService],
exports:[UsuariosService, PartidasService]
})
export class SharedModule {}

View File

@ -0,0 +1,49 @@
import { v4 as uuidv4 } from 'uuid';
import { Injectable, Scope } from '@nestjs/common';
import { Partida } from './partidas.service';
class Usuario {
partidas: Partida[] = [];
constructor(
public uuid: string,
public nickname: string,
public conectado: boolean = false,
) {}
}
@Injectable()
export class UsuariosService {
private _usuarios: Map<string, Usuario> = new Map<string, Usuario>();
get usuarios() {
return this._usuarios;
}
getUsuarioByUUID(uuid: string) {
return this._usuarios.get(uuid) ? this._usuarios.get(uuid) : undefined;
}
creaUsuario(nickname: string) {
const uuid = uuidv4();
const usuario = new Usuario(uuid, nickname);
this._usuarios.set(uuid, usuario);
return usuario.uuid;
}
obtenerUsuarioPorNickname(nickname: string): Usuario | undefined {
for (const usuario of this._usuarios.values()) {
if (usuario.nickname === nickname) {
return usuario;
}
}
return undefined;
}
addPartidaToUsuario(uuid: string, partida: Partida) {
this._usuarios.get(uuid).partidas.push(partida);
}
getPartidasUsuario(uuid: string) {
return this._usuarios.get(uuid).partidas;
}
}

Some files were not shown because too many files have changed in this diff Show More