Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
.DS_Store
.env
.vscode
*.vscode
*/.vscode
*/.env
*.env

# Byte-compiled / optimized / DLL files
__pycache__/
Expand Down
3 changes: 3 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ django-cors-headers = "*"
gunicorn = "*"
django-heroku = "*"
django-rest-api = "*"
psycopg2-binary = "*"
dj-database-url = "*"
whitenoise = "*"

[dev-packages]

Expand Down
216 changes: 124 additions & 92 deletions Pipfile.lock

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
**TRELLO LINK**
[LambdaMUD - Adam Reid](https://trello.com/b/kN49HB0N/lambdamud-adam-reid)

# Adventure Project Week

This week you'll be implementing a frontend interface for a multi-user
Expand Down
18 changes: 14 additions & 4 deletions adv_project/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import os
from decouple import config
import dj_database_url

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
Expand All @@ -26,8 +27,9 @@
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = config('DEBUG', cast=bool)

ALLOWED_HOSTS = []

ALLOWED_HOSTS = ['*']
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

# Application definition

Expand All @@ -54,14 +56,15 @@
SITE_ID = 1

MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
]

Expand Down Expand Up @@ -96,6 +99,8 @@
}
}

db_from_env = dj_database_url.config(conn_max_age=500)
DATABASES['default'].update(db_from_env)

# Password validation
# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators
Expand Down Expand Up @@ -128,7 +133,10 @@
),
}

CORS_ORIGIN_ALLOW_ALL=True
CORS_ORIGIN_ALLOW_ALL=False
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = ('localhost:3000', '127.0.0.1:3000',)
CORS_ORIGIN_REGEX_WHITELIST=('localhost:3000', '127.0.0.1:3000')

# Internationalization
# https://docs.djangoproject.com/en/2.1/topics/i18n/
Expand All @@ -148,6 +156,8 @@
# https://docs.djangoproject.com/en/2.1/howto/static-files/

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

import django_heroku
django_heroku.settings(locals())
del DATABASES['default']['OPTIONS']['sslmode']
2 changes: 2 additions & 0 deletions adv_project/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from django.urls import path, include
from django.conf.urls import include

# imports the necessary url paths and functions into the given paths

urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('api.urls')),
Expand Down
49 changes: 46 additions & 3 deletions adventure/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@
from .models import *
from rest_framework.decorators import api_view
import json
import datetime

# instantiate pusher
pusher = Pusher(app_id=config('PUSHER_APP_ID'), key=config('PUSHER_KEY'), secret=config('PUSHER_SECRET'), cluster=config('PUSHER_CLUSTER'))

@csrf_exempt
@api_view(["GET"])
def initialize(request):
# generates and returns a uuid for our newly logged in player.
# this uuid will be used to subscribe to a pusher channel, as well as keep track of which players are where
user = request.user
player = user.player
player_id = player.id
Expand All @@ -26,6 +29,8 @@ def initialize(request):
# @csrf_exempt
@api_view(["POST"])
def move(request):
# parses movement commands from the interface
# broadcasts a message to other players in the room that the player has entered/left
dirs={"n": "north", "s": "south", "e": "east", "w": "west"}
reverse_dirs = {"n": "south", "s": "north", "e": "west", "w": "east"}
player = request.user.player
Expand Down Expand Up @@ -54,14 +59,52 @@ def move(request):
pusher.trigger(f'p-channel-{p_uuid}', u'broadcast', {'message':f'{player.user.username} has walked {dirs[direction]}.'})
for p_uuid in nextPlayerUUIDs:
pusher.trigger(f'p-channel-{p_uuid}', u'broadcast', {'message':f'{player.user.username} has entered from the {reverse_dirs[direction]}.'})
return JsonResponse({'name':player.user.username, 'title':nextRoom.title, 'description':nextRoom.description, 'players':players, 'error_msg':""}, safe=True)
return JsonResponse({'name':player.user.username, 'title':nextRoom.title, 'description':nextRoom.description, 'players':players, 'error_msg':"", 'timestamp': f'{datetime.datetime.now()}'}, safe=True)
else:
players = room.playerNames(player_id)
return JsonResponse({'name':player.user.username, 'title':room.title, 'description':room.description, 'players':players, 'error_msg':"You cannot move that way."}, safe=True)
return JsonResponse({'name':player.user.username, 'title':room.title, 'description':room.description, 'players':players, 'error_msg':"You cannot move that way.", 'timestamp': f'{datetime.datetime.now()}'}, safe=True)


@csrf_exempt
@api_view(["POST"])
def say(request):
# IMPLEMENT
return JsonResponse({'error':"Not yet implemented"}, safe=True, status=500)

# parse the message from the request body
body = json.loads(request.body)
message = body['message']

# collect player and room information
player = request.user.player
player_id = player.id
player_uuid = player.uuid
room = player.room()
# collect all UUIDs of players in the current room
currentPlayerUUIDs = room.playerUUIDs(player_id)
# send message to current user's channel
pusher.trigger(f'p-channel-{player_uuid}', u'broadcast', {u'message': f'{player.user.username}: {message}', u'timestamp': f'{datetime.datetime.now()}', 'type':'say'})
# print(datetime.datetime)
# send message to all other users in the room
for p_uuid in currentPlayerUUIDs:
pusher.trigger(f'p-channel-{p_uuid}', u'broadcast', {u'message': f'{player.user.username}: {message}', u'timestamp': f'{datetime.datetime.now()}', 'type':'say'})

return JsonResponse({'message':"New say posted."}, safe=True, status=200)

@csrf_exempt
@api_view(["POST"])
def shout(request):
body = json.loads(request.body)
message = body['message']

player = request.user.player
player_id = player.id
player_uuid = player.uuid
allPlayers = Player.objects.all()
allPlayerUUIDs = []
room = player.room()
for p_all in allPlayers:
allPlayerUUIDs.append(p_all.uuid)

for p_uuid in allPlayerUUIDs:
pusher.trigger(f'p-channel-{p_uuid}', u'broadcast', {u'message': f'{player.user.username}({room.title}): {message}', u'timestamp': f'{datetime.datetime.now()}', 'type':'shout'})
return JsonResponse({'message':"New shout posted."}, safe=True, status=200)
2 changes: 1 addition & 1 deletion adventure/apps.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.apps import AppConfig


# desegnates the name of the application
class AdventureConfig(AppConfig):
name = 'adventure'
39 changes: 39 additions & 0 deletions adventure/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Generated by Django 2.1.1 on 2018-12-10 19:49

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid


class Migration(migrations.Migration):

initial = True

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name='Player',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('currentRoom', models.IntegerField(default=0)),
('uuid', models.UUIDField(default=uuid.uuid4, unique=True)),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='Room',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(default='DEFAULT TITLE', max_length=50)),
('description', models.CharField(default='DEFAULT DESCRIPTION', max_length=500)),
('n_to', models.IntegerField(default=0)),
('s_to', models.IntegerField(default=0)),
('e_to', models.IntegerField(default=0)),
('w_to', models.IntegerField(default=0)),
],
),
]
2 changes: 2 additions & 0 deletions adventure/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from rest_framework.authtoken.models import Token
import uuid

# initializes the models we'll be using to create Rooms and Players

class Room(models.Model):
title = models.CharField(max_length=50, default="DEFAULT TITLE")
description = models.CharField(max_length=500, default="DEFAULT DESCRIPTION")
Expand Down
2 changes: 2 additions & 0 deletions adventure/urls.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from django.conf.urls import url
from . import api

# designates which api functions to call when requests are send to the given URL
urlpatterns = [
url('init', api.initialize),
url('move', api.move),
url('say', api.say),
url('shout', api.shout)
]
2 changes: 1 addition & 1 deletion api/apps.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.apps import AppConfig


# designates the name of the API
class ApiConfig(AppConfig):
name = 'api'
2 changes: 2 additions & 0 deletions api/urls.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from django.urls import include, path
from django.conf.urls import url

# tells us to include authorization urls for given paths

urlpatterns = [
path('', include('rest_auth.urls')),
path('registration/', include('rest_auth.registration.urls')),
Expand Down
1 change: 1 addition & 0 deletions util/create_world.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.contrib.auth.models import User
from adventure.models import Player, Room

# initializes our world and creates rooms and players

Room.objects.all().delete()

Expand Down