main.py 6.86 KB
#!/usr/bin/env python

"""
MudServer author: Mark Frimston - mfrimston@gmail.com

Micropython port and expansion author: Barry Ruffner - barryruffner@gmail.com
"""

from time import sleep
from math import floor
from sys import platform

from mudserver import MudServer
from commandhandler import CommandHandler
from utils import load_object_from_file, save_object_to_file

if 'esp' in platform:
    from gc import collect, mem_free
    from machine import Pin
# import the MUD server class


print('STARTING MUD\r\n\r\n\r\n')

# Setup button so when pressed the mud goes in to wifi hotspot mode on 192.168.4.1
if 'esp' in platform:
    flash_button = Pin(0, Pin.IN, Pin.PULL_UP)

# stores the players in the game
players = {}

# start the server
globals()['mud'] = MudServer()


def show_prompt(pid):
    if "prompt" not in players[pid]:
        players[pid]["prompt"] = "> "
    if 'hp' not in players[pid]:
        players[pid]["hp"] = 100
    if 'mp' not in players[pid]:
        players[pid]["mp"] = 100
    if 'sta' not in players[pid]:
        players[pid]["sta"] = 10

    prompt = players[pid]["prompt"].replace('%st', str(floor(players[pid]['sta']))).replace('%hp', str(floor(players[pid]["hp"]))).replace('%mp', str(floor(players[pid]["mp"])))
    mud.send_message(pid, "\r\n" + prompt, '')

tick = 0.0
spawn = 0.0
cmd_handler = CommandHandler()

# main game loop. We loop forever (i.e. until the program is terminated)
while True:
    if 'esp' in platform:
        collect()
        if flash_button.value() == 0:
            break
    # pause for 1/5 of a second on each loop, so that we don't constantly
    sleep(0.002)
    if 'esp' in platform:
        tick += 0.001
    else:
        tick += 0.0005
    if spawn >= 10:
        spawn = 0
        try:
            ldict = {}
            with open('spawner.txt', 'r', encoding='utf-8') as f:
                exec(f.read(), globals(), ldict)
        except Exception as e:
            print('spawner error:')
            print(e)
        if 'esp' in platform:
            collect()
    if tick >= 1:
        if 'esp' in platform:
            print(mem_free())
        spawn += tick
        tick = 0
        # try:
        ldict = {}
        if 'esp' in platform:
            print(mem_free())
            collect()
        with open('mobs.txt', 'r', encoding='utf-8') as f:
            exec(f.read(), globals(), ldict)
        if 'esp' in platform:
            collect()
        # except Exception as e:
        #     print('mob error:')
        #     print(e)
    # 'update' must be called in the loop to keep the game running and give
    # us up-to-date information
    mud.update()

    # go through any newly connected players
    for id in mud.get_new_players():

        # add the new player to the dictionary, noting that they've not been
        # named yet.
        # The dictionary key is the player's id number. We set their room to
        # None initially until they have entered a name
        # Try adding more player stats - level, gold, inventory, etc
        players[id] = load_object_from_file("defaultplayer.json")
        with open('welcome.txt', 'r', encoding='utf-8') as f:
            for line in f:
                mud.send_message(id, line, "\r")
        # send the new player a prompt for their name
        #bytes_to_send = bytearray([mud._TN_INTERPRET_AS_COMMAND, mud._TN_WONT, mud._ECHO])
        #mud.raw_send(id, bytes_to_send)
        mud.send_message(id, "What is your name?")

    # go through any recently disconnected players
    for id in mud.get_disconnected_players():

        # if for any reason the player isn't in the player map, skip them and
        # move on to the next one
        if id not in players:
            continue

        # go through all the players in the game
        for pid, pl in players.items():
            # send each player a message to tell them about the diconnected
            # player
            if players[pid]["name"] is not None:
                mud.send_message(pid, "{} quit the game".format(players[pid]["name"]))

        # remove the player's entry in the player dictionary
        if players[id]["name"] is not None:
            save_object_to_file(players[id], "players/{}.json".format(players[id]["name"]))
        del(players[id])

    # go through any new commands sent from players
    for id, command, params in mud.get_commands():

        # if for any reason the player isn't in the player map, skip them and
        # move on to the next one
        if id not in players:
            continue

        # if the player hasn't given their name yet, use this first command as
        # their name and move them to the starting room.
        if players[id]["name"] is None:
            if command.strip() == '' or len(command) > 12 or not command.isalnum() or command is None:
                mud.send_message(id, "Invalid Name")
                print("Bad guy!")
                print(mud.get_remote_ip(id))
                continue
            already_logged_in = False
            for pid, pl in players.items():
                if players[pid]["name"] == command:
                    mud.send_message(id, "{} is already logged in.".format(command))
                    mud.disconnect_player(id)
                    already_logged_in = True
            if already_logged_in:
                continue
            players[id]["name"] = command

            mud.remote_echo(id, False)
            mud.send_message(id, "Enter Password: ")

        elif players[id]["password"] is None:
            if command.strip() == '' or command is None:
                mud.send_message(id, "Invalid Password")
                continue

            # TODO: Write password shadow file

            loaded_player = load_object_from_file("players/{}.json".format(players[pid]["name"]))
            if loaded_player is None:
                players[id]["password"] = True
                players[id]["room"] = "Tavern"
            else:
                players[id] = loaded_player

            # go through all the players in the game
            for pid, pl in players.items():
                # send each player a message to tell them about the new player
                mud.send_message(pid, "{} entered the game".format(players[id]["name"]))

            mud.remote_echo(id, True)
            # send the new player a welcome message
            mud.send_message(id, "\r\n\r\nWelcome to the game, {}. ".format(players[id]["name"]) +
                             "\r\nType 'help' for a list of commands. Have fun!\r\n\r\n")

            # send the new player the description of their current room

            cmd_handler.parse(id, 'look', '', mud, players)
            show_prompt(id)
        else:
            if 'esp' in platform:
                collect()

            cmd_handler.parse(id, command, params, mud, players)
            show_prompt(id)

# Start WIFI Setup
if 'esp' in platform:
    if flash_button.value() == 0:
        print('Starting WIFIWeb')
        import wifiweb