cleanup!
This commit is contained in:
parent
60997eccad
commit
3b9ce53b4e
|
@ -0,0 +1,6 @@
|
||||||
|
[*.{py,json,hy,yaml}]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = spaces
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_size = 4
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
|
||||||
|
kate: indent-pasted-text false; indent-width 4; space-indent true;
|
|
@ -1,32 +0,0 @@
|
||||||
|
|
||||||
import curses
|
|
||||||
|
|
||||||
class Colours:
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
|
|
||||||
self.colours = min(curses.COLORS, 16)
|
|
||||||
self.pairs = self.colours*self.colours
|
|
||||||
|
|
||||||
curses.use_default_colors()
|
|
||||||
for i in range(0, self.pairs):
|
|
||||||
curses.init_pair(i, i%self.colours, i//self.colours)
|
|
||||||
|
|
||||||
def get(self, fg=0, bg=0):
|
|
||||||
if self.colours == 16:
|
|
||||||
return curses.color_pair(fg + bg*self.colours)
|
|
||||||
elif self.colours == 8:
|
|
||||||
dfg = fg % 8
|
|
||||||
dbg = bg % 8
|
|
||||||
if bg == 8:
|
|
||||||
dbg = 7
|
|
||||||
if fg == 8:
|
|
||||||
dfg = 7
|
|
||||||
colour = curses.color_pair(dfg + dbg*self.colours)
|
|
||||||
if fg >= 8 and bg < 8:
|
|
||||||
colour |= curses.A_BOLD
|
|
||||||
elif fg < 8 and bg >= 8:
|
|
||||||
colour |= curses.A_DIM
|
|
||||||
return colour
|
|
||||||
else:
|
|
||||||
return curses.color_pair(0)
|
|
|
@ -1,154 +0,0 @@
|
||||||
|
|
||||||
import curses
|
|
||||||
|
|
||||||
from .field import Field
|
|
||||||
from .info import Info
|
|
||||||
from .health import Health
|
|
||||||
from .inventory import Inventory
|
|
||||||
from .screen import Screen
|
|
||||||
from .colours import Colours
|
|
||||||
from .messages import Messages
|
|
||||||
from .switcher import Switcher
|
|
||||||
from .textinput import TextInput
|
|
||||||
from .widget import Widget
|
|
||||||
|
|
||||||
from asciifarm.common.utils import get
|
|
||||||
|
|
||||||
|
|
||||||
SIDEWIDTH = 20
|
|
||||||
|
|
||||||
ALPHABET = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
|
|
||||||
|
|
||||||
class Display:
|
|
||||||
|
|
||||||
def __init__(self, stdscr, charMap, colours=False):
|
|
||||||
|
|
||||||
if colours and curses.has_colors and curses.COLORS > 1:
|
|
||||||
self.colours = Colours()
|
|
||||||
else:
|
|
||||||
self.colours = None
|
|
||||||
self.characters = {}
|
|
||||||
|
|
||||||
def parseSprite(sprite):
|
|
||||||
if isinstance(sprite, str):
|
|
||||||
return (sprite, None, None)
|
|
||||||
char = get(sprite, 0, " ")
|
|
||||||
fg = get(sprite, 1)
|
|
||||||
bg = get(sprite, 2)
|
|
||||||
return (char, fg, bg)
|
|
||||||
for name, sprite in charMap["mapping"].items():
|
|
||||||
vals = parseSprite(sprite)
|
|
||||||
if vals:
|
|
||||||
self.characters[name] = vals
|
|
||||||
|
|
||||||
for name, colours in charMap.get("writable", {}).items():
|
|
||||||
fg = get(colours, 0)
|
|
||||||
bg = get(colours, 1)
|
|
||||||
for i in range(min(len(ALPHABET), len(charMap.get("alphabet", [])))):
|
|
||||||
self.characters[name + '-' + ALPHABET[i]] = (charMap["alphabet"][i], fg, bg)
|
|
||||||
|
|
||||||
self.defaultChar = parseSprite(charMap.get("default", "?"))
|
|
||||||
screen = Screen(self, stdscr, self.colours)
|
|
||||||
self.screen = screen
|
|
||||||
|
|
||||||
self.widgets = {}
|
|
||||||
|
|
||||||
self.addWidget(Field((1, 1), charMap.get("charwidth", 1), self.colours), "field")
|
|
||||||
self.addWidget(Info(), "info")
|
|
||||||
self.addWidget(Health(
|
|
||||||
charMap.get("healthfull", ("@",7, 2)),
|
|
||||||
charMap.get("healthempty", ("-",7, 1))
|
|
||||||
),
|
|
||||||
"health")
|
|
||||||
self.addWidget(Inventory("Inventory"), "inventory")
|
|
||||||
self.addWidget(Inventory("Ground"), "ground")
|
|
||||||
self.addWidget(Inventory("Equipment"), "equipment")
|
|
||||||
|
|
||||||
|
|
||||||
#switcher = Switcher([self.widgets["ground"], self.widgets["inventory"], self.widgets["equipment"]], 1)
|
|
||||||
self.addWidget(Inventory(""), "switch")
|
|
||||||
self.addWidget(Messages(charMap.get("msgcolours", {})), "msg")
|
|
||||||
self.addWidget(TextInput(), "textinput")
|
|
||||||
|
|
||||||
self.forced = False
|
|
||||||
|
|
||||||
def addWidget(self, w, name, winname=None):
|
|
||||||
if not winname:
|
|
||||||
winname = name
|
|
||||||
widget = Widget(w, name)
|
|
||||||
self.widgets[name] = widget
|
|
||||||
widget.setWin(winname, self.screen)
|
|
||||||
|
|
||||||
def getWidget(self, name):
|
|
||||||
if name in self.widgets:
|
|
||||||
return self.widgets[name].getImpl()
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def resizeField(self, size):
|
|
||||||
self.getWidget("field").resize(*size)
|
|
||||||
self.forced = True
|
|
||||||
|
|
||||||
def drawFieldCells(self, cells):
|
|
||||||
field = self.getWidget("field")
|
|
||||||
for cell in cells:
|
|
||||||
(x, y), spriteNames = cell
|
|
||||||
sprites = [self.getChar(spriteName) for spriteName in spriteNames]
|
|
||||||
if not len(sprites):
|
|
||||||
sprites = [self.getChar(" ")]
|
|
||||||
field.changeCell(x, y, sprites)
|
|
||||||
|
|
||||||
|
|
||||||
def setFieldCenter(self, pos):
|
|
||||||
self.getWidget("field").setCenter(pos)
|
|
||||||
|
|
||||||
def setHealth(self, health, maxHealth):
|
|
||||||
self.getWidget("health").setHealth(health, maxHealth)
|
|
||||||
|
|
||||||
|
|
||||||
def showInfo(self, infostring):
|
|
||||||
self.getWidget("info").showString(infostring)
|
|
||||||
|
|
||||||
|
|
||||||
#def setInventory(self, items):
|
|
||||||
#self.getWidget("inventory").setInventory(items)
|
|
||||||
|
|
||||||
|
|
||||||
#def setEquipment(self, slots):
|
|
||||||
#self.getWidget("equipment").setInventory(
|
|
||||||
#sorted([
|
|
||||||
#slot + ": " + (item if item else "")
|
|
||||||
#for slot, item in slots.items()
|
|
||||||
#])
|
|
||||||
#)
|
|
||||||
|
|
||||||
#def setGround(self, items):
|
|
||||||
#self.getWidget("ground").setInventory(items)
|
|
||||||
|
|
||||||
|
|
||||||
def addMessage(self, message, type):
|
|
||||||
self.getWidget("msg").addMessage(message, type)
|
|
||||||
|
|
||||||
def scrollBack(self, amount, relative=True):
|
|
||||||
self.getWidget("msg").scroll(amount, relative)
|
|
||||||
|
|
||||||
def getChar(self, sprite):
|
|
||||||
"""This returns the character belonging to some spritename. This does not read a character"""
|
|
||||||
return self.characters.get(sprite, self.defaultChar)
|
|
||||||
|
|
||||||
def setInputString(self, string, cursor):
|
|
||||||
self.getWidget("textinput").setText(string, cursor)
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
changed = False
|
|
||||||
for widget in self.widgets.values():
|
|
||||||
if self.forced or widget.isChanged():
|
|
||||||
widget.update()
|
|
||||||
changed = True
|
|
||||||
if changed:
|
|
||||||
self.screen.update()
|
|
||||||
self.forced = False
|
|
||||||
|
|
||||||
def forceUpdate(self):
|
|
||||||
self.forced = True
|
|
||||||
|
|
|
@ -1,70 +0,0 @@
|
||||||
|
|
||||||
import curses
|
|
||||||
from .widimp import WidImp
|
|
||||||
|
|
||||||
class Field(WidImp):
|
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, size=(1,1), charSize=1, colours=False):
|
|
||||||
self.pad = curses.newpad(size[1]+1, (size[0]+1)*charSize)
|
|
||||||
self.size = size
|
|
||||||
self.charSize = charSize
|
|
||||||
self.center = (0, 0)
|
|
||||||
self.colours = colours
|
|
||||||
self.changed = False
|
|
||||||
self.redraw = False
|
|
||||||
|
|
||||||
def resize(self, width, height):
|
|
||||||
self.size = (width, height)
|
|
||||||
self.pad.resize(height+1, width*self.charSize)
|
|
||||||
self.redraw = True
|
|
||||||
self.change()
|
|
||||||
|
|
||||||
def changeCell(self, x, y, sprites):
|
|
||||||
""" sprites must always have at least one element """
|
|
||||||
char, colour, bgcolour = sprites[0]
|
|
||||||
if bgcolour is None:
|
|
||||||
for (ch, co, bg) in sprites:
|
|
||||||
if bg is not None:
|
|
||||||
bgcolour = bg
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
bgcolour = 0
|
|
||||||
if colour is not None and self.colours:
|
|
||||||
self.pad.addstr(y, x*self.charSize, " "*self.charSize, self.colours.get(7, 0))
|
|
||||||
self.pad.addstr(y, x*self.charSize, char, self.colours.get(colour, bgcolour))
|
|
||||||
else:
|
|
||||||
self.pad.addstr(y, x*self.charSize, char)
|
|
||||||
self.change()
|
|
||||||
|
|
||||||
def setCenter(self, pos):
|
|
||||||
self.center = pos
|
|
||||||
self.change()
|
|
||||||
|
|
||||||
def getWidth(self):
|
|
||||||
return self.size[0]*self.charSize
|
|
||||||
|
|
||||||
def getHeight(self):
|
|
||||||
return self.size[1]
|
|
||||||
|
|
||||||
def _roundWidth(self, x):
|
|
||||||
return x // self.charSize * self.charSize
|
|
||||||
|
|
||||||
def update(self, win):
|
|
||||||
if self.redraw:
|
|
||||||
win.erase()
|
|
||||||
win.noutrefresh()
|
|
||||||
self.redraw = False
|
|
||||||
width, height = win.getSize()
|
|
||||||
x, y = win.getPos()
|
|
||||||
xmax = x + width
|
|
||||||
ymax = y + height
|
|
||||||
self.pad.noutrefresh(
|
|
||||||
max(0, min(self.getHeight()-height, self.center[1] - int(height/2))),
|
|
||||||
max(0, min(
|
|
||||||
self._roundWidth(self.getWidth()-width),
|
|
||||||
self._roundWidth(self.center[0]*self.charSize - int(width/2)))),
|
|
||||||
y,
|
|
||||||
x + max(0, (width - self.getWidth()) // 2),
|
|
||||||
ymax,
|
|
||||||
xmax)
|
|
|
@ -1,27 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
from .widimp import WidImp
|
|
||||||
|
|
||||||
class Health(WidImp):
|
|
||||||
|
|
||||||
def __init__(self, char=None, emptyChar=None):
|
|
||||||
self.char = char or ('@',7,0)
|
|
||||||
self.emptyChar = emptyChar or ('-',7,0)
|
|
||||||
self.changed = False
|
|
||||||
self.health = 0
|
|
||||||
self.maxHealth = 0
|
|
||||||
|
|
||||||
def setHealth(self, health, maxHealth):
|
|
||||||
self.health = health or 0
|
|
||||||
self.maxHealth = maxHealth or 0
|
|
||||||
self.change()
|
|
||||||
|
|
||||||
def update(self, win):
|
|
||||||
width, height = win.getSize()
|
|
||||||
width -= 1
|
|
||||||
barEnd = round(self.health/self.maxHealth * width) if self.maxHealth > 0 else 0
|
|
||||||
win.erase()
|
|
||||||
win.addLine((0,0),"Health: {}/{}".format(self.health, self.maxHealth)[:width])
|
|
||||||
win.addLine((0, 1), self.char[0]*barEnd, self.char[1:])
|
|
||||||
win.addLine((barEnd, 1), self.emptyChar[0]*(width-barEnd), self.emptyChar[1:])
|
|
||||||
win.noutrefresh()
|
|
|
@ -1,24 +0,0 @@
|
||||||
|
|
||||||
from .widimp import WidImp
|
|
||||||
|
|
||||||
class Info(WidImp):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.changed = False
|
|
||||||
self.lines = []
|
|
||||||
self.lastString = None
|
|
||||||
|
|
||||||
def showString(self, string):
|
|
||||||
if string == self.lastString:
|
|
||||||
return
|
|
||||||
self.lines = string.split('\n')
|
|
||||||
self.change()
|
|
||||||
self.lastString = string
|
|
||||||
|
|
||||||
def update(self, win):
|
|
||||||
width, height = win.getSize()
|
|
||||||
lines = [line[:width-1] for line in self.lines][:height]
|
|
||||||
win.erase()
|
|
||||||
for i, line in enumerate(lines):
|
|
||||||
win.addLine((0, i), line)
|
|
||||||
win.noutrefresh()
|
|
|
@ -1,73 +0,0 @@
|
||||||
|
|
||||||
from asciifarm.common import utils
|
|
||||||
|
|
||||||
from .widimp import WidImp
|
|
||||||
|
|
||||||
class Inventory(WidImp):
|
|
||||||
|
|
||||||
def __init__(self, title, titlebar="{}:", selectorChar="*"):
|
|
||||||
self.title = title
|
|
||||||
self.titlebar = titlebar
|
|
||||||
self.selectorChar = selectorChar
|
|
||||||
self.items = []
|
|
||||||
self.selector = 0
|
|
||||||
|
|
||||||
def getSelected(self):
|
|
||||||
return self.selector
|
|
||||||
|
|
||||||
def select(self, value, relative=False, modular=False):
|
|
||||||
invLen = len(self.items)
|
|
||||||
if relative:
|
|
||||||
value += self.selector
|
|
||||||
if modular and invLen:
|
|
||||||
value %= invLen
|
|
||||||
if value < 0:
|
|
||||||
value = 0
|
|
||||||
if value >= invLen:
|
|
||||||
value = invLen-1
|
|
||||||
if value in range(invLen):
|
|
||||||
self.doSelect(value)
|
|
||||||
|
|
||||||
def doSelect(self, value):
|
|
||||||
self.selector = value
|
|
||||||
self.change()
|
|
||||||
|
|
||||||
def setInventory(self, items):
|
|
||||||
self.items = items
|
|
||||||
self.selector = utils.clamp(self.selector, 0, len(items)-1)
|
|
||||||
self.change()
|
|
||||||
|
|
||||||
def getItem(self, num):
|
|
||||||
return self.items[num]
|
|
||||||
|
|
||||||
def getSelectedItem(self):
|
|
||||||
return self.getItem(self.getSelected())
|
|
||||||
|
|
||||||
def setTitle(self, title):
|
|
||||||
self.title = title
|
|
||||||
|
|
||||||
def getNumItems(self):
|
|
||||||
return len(self.items)
|
|
||||||
|
|
||||||
def itemName(self, item):
|
|
||||||
return item
|
|
||||||
|
|
||||||
def update(self, win):
|
|
||||||
|
|
||||||
width, height = win.getSize()
|
|
||||||
height -= 1
|
|
||||||
selected = self.selector
|
|
||||||
start = min(selected - height//2, len(self.items)-height)
|
|
||||||
start = max(start, 0)
|
|
||||||
end = start + height
|
|
||||||
win.erase()
|
|
||||||
win.addLine((0,0), (self.titlebar.format(self.title))[:width])
|
|
||||||
for i, item in enumerate(self.items[start:end]):
|
|
||||||
if i + start == selected:
|
|
||||||
win.addLine((0, i+1), self.selectorChar)
|
|
||||||
win.addLine((1, i+1), self.itemName(item))
|
|
||||||
if end < len(self.items):
|
|
||||||
win.addLine((width-1, height), "+")
|
|
||||||
if start > 0:
|
|
||||||
win.addLine((width-1, 1), "-")
|
|
||||||
win.noutrefresh()
|
|
|
@ -1,56 +0,0 @@
|
||||||
|
|
||||||
import textwrap
|
|
||||||
|
|
||||||
from .widimp import WidImp
|
|
||||||
|
|
||||||
class Messages(WidImp):
|
|
||||||
|
|
||||||
def __init__(self, colours):
|
|
||||||
self.changed = False
|
|
||||||
self.messages = []
|
|
||||||
self.scrolledBack = 0
|
|
||||||
self.colours = colours
|
|
||||||
|
|
||||||
def addMessage(self, message, type=None):
|
|
||||||
self.messages.append([message, type])
|
|
||||||
if self.scrolledBack:
|
|
||||||
self.scrolledBack += 1
|
|
||||||
self.change()
|
|
||||||
|
|
||||||
def scroll(self, amount, relative=True):
|
|
||||||
if relative:
|
|
||||||
self.scrolledBack += amount
|
|
||||||
else:
|
|
||||||
self.scrolledBack = amount
|
|
||||||
self.scrolledBack = max(self.scrolledBack, 0)
|
|
||||||
self.change()
|
|
||||||
|
|
||||||
def update(self, win):
|
|
||||||
width, height = win.getSize()
|
|
||||||
if height < 1:
|
|
||||||
return
|
|
||||||
lines = []
|
|
||||||
messages = self.messages
|
|
||||||
for message, type in messages:
|
|
||||||
colour = self.colours.get(type, (7,0))
|
|
||||||
for line in textwrap.wrap(message, width):
|
|
||||||
lines.append((line, colour))
|
|
||||||
self.scrolledBack = max(min(self.scrolledBack, len(lines)-height), 0)
|
|
||||||
moreDown = False
|
|
||||||
if self.scrolledBack > 0:
|
|
||||||
lines = lines[:-self.scrolledBack]
|
|
||||||
moreDown = True
|
|
||||||
moreUp = False
|
|
||||||
if len(lines) > height:
|
|
||||||
moreUp = True
|
|
||||||
lines = lines[len(lines)-height:]
|
|
||||||
elif len(lines) < height:
|
|
||||||
lines = (height-len(lines)) * [("",)] + lines
|
|
||||||
win.erase()
|
|
||||||
for i, line in enumerate(lines):
|
|
||||||
win.addLine((0,i), *line)
|
|
||||||
if moreUp:
|
|
||||||
win.addLine((width-1, 0), '-')
|
|
||||||
if moreDown:
|
|
||||||
win.addLine((width-1, height-1), '+')
|
|
||||||
win.noutrefresh()
|
|
|
@ -1,95 +0,0 @@
|
||||||
|
|
||||||
import curses
|
|
||||||
from asciifarm.common.utils import clamp
|
|
||||||
from .window import Window
|
|
||||||
|
|
||||||
import signal
|
|
||||||
|
|
||||||
class Screen:
|
|
||||||
|
|
||||||
def __init__(self, display, stdscr, colours):
|
|
||||||
self.display = display
|
|
||||||
try:
|
|
||||||
curses.curs_set(0)
|
|
||||||
self.cursorSet = False
|
|
||||||
except curses.error:
|
|
||||||
# Not all terminals support this functionality.
|
|
||||||
# When the error is ignored the screen will look a little uglier,
|
|
||||||
# A cursor will move around, but that's not terrible
|
|
||||||
# So in order to keep the game as accesible as possible to everyone, it should be safe to ignore the error.
|
|
||||||
self.cursorSet = True
|
|
||||||
# It is probably possible to make sure the cursor is only in a corner of the screen
|
|
||||||
# but I can't figure out how.
|
|
||||||
# it seems to ignore all my move commands unless I press a key
|
|
||||||
# I give up
|
|
||||||
self.stdscr = stdscr
|
|
||||||
self.colours = colours
|
|
||||||
self.setWins()
|
|
||||||
signal.signal(signal.SIGWINCH, self.updateSize)
|
|
||||||
|
|
||||||
def _limitHeight(self, h, y):
|
|
||||||
return min(h + y, self.height) - y
|
|
||||||
|
|
||||||
def setWins(self):
|
|
||||||
height, width = self.height, self.width = self.stdscr.getmaxyx()
|
|
||||||
|
|
||||||
sideW = 20
|
|
||||||
sideX = width-sideW
|
|
||||||
|
|
||||||
msgH = clamp(height // 5, 3, 5)
|
|
||||||
msgY = height - msgH-1
|
|
||||||
inputH = 1
|
|
||||||
inputY = msgY + msgH
|
|
||||||
|
|
||||||
healthY = 0
|
|
||||||
healthH = self._limitHeight(2, healthY)
|
|
||||||
indexY = healthY + healthH
|
|
||||||
indexH = self._limitHeight(4, indexY)
|
|
||||||
listY = indexY + indexH + 1
|
|
||||||
listH = self._limitHeight(12, listY)
|
|
||||||
infoY = listY + listH
|
|
||||||
infoH = self._limitHeight(20, infoY)
|
|
||||||
|
|
||||||
lists = self.makeWin(sideX, listY, sideW, listH)
|
|
||||||
|
|
||||||
self.windows = {
|
|
||||||
"field": self.makeWin(0, 0, sideX - 1, msgY),
|
|
||||||
"msg": self.makeWin(0, msgY, sideX - 1, msgH),
|
|
||||||
"textinput": self.makeWin(0, inputY, sideX - 1, inputH),
|
|
||||||
|
|
||||||
"health": self.makeWin(sideX, healthY, sideW, healthH),
|
|
||||||
"switch": self.makeWin(sideX, indexY, sideW, indexH),
|
|
||||||
"ground": lists,
|
|
||||||
"inventory": lists,
|
|
||||||
"equipment": lists,
|
|
||||||
"info": self.makeWin(sideX, infoY, sideW, infoH)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def makeWin(self, x, y, width, height):
|
|
||||||
if width < 1 or height < 1:
|
|
||||||
win = None
|
|
||||||
else:
|
|
||||||
win = curses.newwin(height, width, y, x)
|
|
||||||
return Window(win, self.colours)
|
|
||||||
|
|
||||||
def getWin(self, name):
|
|
||||||
return self.windows.get(name, None)
|
|
||||||
|
|
||||||
def updateSize(self, *args):
|
|
||||||
curses.endwin()
|
|
||||||
curses.initscr()
|
|
||||||
self.setWins()
|
|
||||||
self.stdscr.clear()
|
|
||||||
self.display.forceUpdate()
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
curses.doupdate()
|
|
||||||
|
|
||||||
def getWidth(self):
|
|
||||||
return self.width
|
|
||||||
|
|
||||||
def getHeight(self):
|
|
||||||
return self.height
|
|
||||||
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
from .inventory import Inventory
|
|
||||||
|
|
||||||
class Switcher(Inventory):
|
|
||||||
"""An area that can contain multiple widgets but only shows one at a time.
|
|
||||||
There is a function to switch between the displayed widgets.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#def __init__(self, widgets, initial=0):
|
|
||||||
#Inventory.__init__(self, "", "", "=")
|
|
||||||
#self.setInventory(widgets)
|
|
||||||
|
|
||||||
#for wid in widgets:
|
|
||||||
#wid.hidden = True
|
|
||||||
|
|
||||||
#self.select(initial)
|
|
||||||
|
|
||||||
#def doSelect(self, value):
|
|
||||||
#self.getSelectedItem().hidden = True
|
|
||||||
#self.selector = value
|
|
||||||
#self.change()
|
|
||||||
#newWid = self.getSelectedItem()
|
|
||||||
#newWid.hidden = False
|
|
||||||
#newWid.change()
|
|
||||||
|
|
||||||
def itemName(self, item):
|
|
||||||
return item.getImpl().title
|
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
|
|
||||||
import curses
|
|
||||||
from .widimp import WidImp
|
|
||||||
|
|
||||||
class TextInput(WidImp):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.text = ""
|
|
||||||
self.cursor = -1
|
|
||||||
|
|
||||||
def setText(self, text, cursor):
|
|
||||||
self.text = text
|
|
||||||
self.cursor = cursor
|
|
||||||
self.change()
|
|
||||||
|
|
||||||
def update(self, win):
|
|
||||||
width, height = win.getSize()
|
|
||||||
win.erase()
|
|
||||||
win.addLine((0, 0), self.text[:width])
|
|
||||||
if self.cursor >= 0 and self.cursor <= len(self.text):
|
|
||||||
win.setAttr((min(self.cursor, width-1), 0), curses.A_REVERSE)
|
|
||||||
win.noutrefresh()
|
|
|
@ -1,35 +0,0 @@
|
||||||
|
|
||||||
class Widget:
|
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, impl, name=None):
|
|
||||||
self.impl = impl
|
|
||||||
|
|
||||||
self.win = None
|
|
||||||
self.screen = None
|
|
||||||
self.changed = False
|
|
||||||
self.hidden = False
|
|
||||||
self.name = name
|
|
||||||
self.impl.setWidget(self)
|
|
||||||
|
|
||||||
def setWin(self, win, screen):
|
|
||||||
self.win = win
|
|
||||||
self.screen = screen
|
|
||||||
|
|
||||||
def getWin(self):
|
|
||||||
return self.win and self.screen and self.screen.getWin(self.win)
|
|
||||||
|
|
||||||
def getImpl(self):
|
|
||||||
return self.impl
|
|
||||||
|
|
||||||
def change(self):
|
|
||||||
self.changed = True
|
|
||||||
|
|
||||||
def isChanged(self):
|
|
||||||
return self.changed
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
if not self.getWin() or self.hidden:
|
|
||||||
return
|
|
||||||
self.impl.update(self.getWin())
|
|
||||||
self.changed = False
|
|
|
@ -1,18 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
class WidImp:
|
|
||||||
|
|
||||||
"""widget implementation"""
|
|
||||||
|
|
||||||
_widget = None
|
|
||||||
|
|
||||||
def setWidget(self, widget):
|
|
||||||
self._widget = widget
|
|
||||||
self.change()
|
|
||||||
|
|
||||||
def change(self):
|
|
||||||
if self._widget is not None:
|
|
||||||
self._widget.change()
|
|
||||||
|
|
||||||
def update(self, win):
|
|
||||||
pass
|
|
|
@ -1,74 +0,0 @@
|
||||||
|
|
||||||
import curses
|
|
||||||
|
|
||||||
class Window:
|
|
||||||
""" Small wrapper around curses windows """
|
|
||||||
|
|
||||||
def __init__(self, win, colours=None):
|
|
||||||
|
|
||||||
self.win = win
|
|
||||||
self.colours = colours
|
|
||||||
|
|
||||||
def getSize(self):
|
|
||||||
if not self.win:
|
|
||||||
return (0, 0)
|
|
||||||
height, width = self.win.getmaxyx()
|
|
||||||
return (width, height)
|
|
||||||
|
|
||||||
def getPos(self):
|
|
||||||
if not self.win:
|
|
||||||
return (0, 0)
|
|
||||||
y, x = self.win.getparyx()
|
|
||||||
return (x, y)
|
|
||||||
|
|
||||||
def addLine(self, pos, string, colour=(0,0)):
|
|
||||||
"""Draw a string that does not contain newlines or characters with larger width
|
|
||||||
|
|
||||||
long lines are cropped to fit in the window"""
|
|
||||||
|
|
||||||
if not self.win:
|
|
||||||
return
|
|
||||||
x, y = pos
|
|
||||||
width, height = self.getSize()
|
|
||||||
string = string[:width-x]
|
|
||||||
drawLast = None
|
|
||||||
if self.colours:
|
|
||||||
self._addstr(y, x, string, self.colours.get(*colour))
|
|
||||||
else:
|
|
||||||
self._addstr(y, x, string)
|
|
||||||
|
|
||||||
|
|
||||||
def _addstr(self, y, x, string, *args):
|
|
||||||
if not self.win:
|
|
||||||
return
|
|
||||||
width, height = self.getSize()
|
|
||||||
if y == height-1 and x+len(string) == width:
|
|
||||||
if len(string) > 1:
|
|
||||||
self.win.addstr(y, x, string[:-1], *args)
|
|
||||||
try:
|
|
||||||
self.win.addstr(height-1, width-1, string[-1], *args)
|
|
||||||
except curses.error:
|
|
||||||
# ncurses has a weird problem:
|
|
||||||
# it always raises an error when drawing to the last character in the window
|
|
||||||
# it draws first and then raises the error
|
|
||||||
# therefore to draw in the last place of the window the last character needs to be ingored
|
|
||||||
# other solutions might be possible, but are more hacky
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
self.win.addstr(y, x, string, *args)
|
|
||||||
|
|
||||||
def erase(self):
|
|
||||||
if self.win:
|
|
||||||
self.win.erase()
|
|
||||||
|
|
||||||
def noutrefresh(self):
|
|
||||||
if self.win:
|
|
||||||
self.win.noutrefresh()
|
|
||||||
|
|
||||||
def setAttr(self, pos, attr, num=1):
|
|
||||||
if self.win:
|
|
||||||
x, y = pos
|
|
||||||
self.win.chgat(y, x, num, attr)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ from .inputhandler import InputHandler
|
||||||
class Client:
|
class Client:
|
||||||
|
|
||||||
def __init__(self, display, name, connection, keybindings, logFile=None):
|
def __init__(self, display, name, connection, keybindings, logFile=None):
|
||||||
#self.stdscr = stdscr
|
|
||||||
self.display = display
|
self.display = display
|
||||||
self.name = name
|
self.name = name
|
||||||
self.keepalive = True
|
self.keepalive = True
|
||||||
|
@ -54,13 +54,9 @@ class Client:
|
||||||
self.queue.put(("error", error))
|
self.queue.put(("error", error))
|
||||||
|
|
||||||
def getInput(self):
|
def getInput(self):
|
||||||
#try:
|
|
||||||
while True:
|
while True:
|
||||||
key = ratuil.inputs.get_key()
|
key = ratuil.inputs.get_key()
|
||||||
#key = self.stdscr.getch()
|
|
||||||
self.queue.put(("input", key))
|
self.queue.put(("input", key))
|
||||||
#except Exception as e:
|
|
||||||
#self.queue.put(("error", e))
|
|
||||||
|
|
||||||
def close(self, msg=None):
|
def close(self, msg=None):
|
||||||
self.keepalive = False
|
self.keepalive = False
|
||||||
|
@ -112,23 +108,14 @@ class Client:
|
||||||
if maxHealth is None:
|
if maxHealth is None:
|
||||||
self.log("You have died. Restart the client to respawn")
|
self.log("You have died. Restart the client to respawn")
|
||||||
if msgType == "inventory":
|
if msgType == "inventory":
|
||||||
self.display.inventory.setItems(msg[1])
|
|
||||||
#invbox = self.display.getWidget("inventory")
|
|
||||||
#invbox.setInventory(self.inventory.items)
|
|
||||||
#invbox.select(self.inventory.selector)
|
|
||||||
#self.display.setInventory(msg[1])
|
#self.display.setInventory(msg[1])
|
||||||
|
self.display.inventory.setItems(msg[1])
|
||||||
if msgType == "equipment":
|
if msgType == "equipment":
|
||||||
#self.display.setEquipment(msg[1])
|
#self.display.setEquipment(msg[1])
|
||||||
self.display.equipment.setItems(msg[1])
|
self.display.equipment.setItems(msg[1])
|
||||||
#eqbox = self.display.getWidget("equipment")
|
|
||||||
#eqbox.setInventory(self.inventory.items)
|
|
||||||
#eqbox.select(self.equipment.selector)
|
|
||||||
if msgType == "ground":
|
if msgType == "ground":
|
||||||
#self.display.setGround(msg[1])
|
#self.display.setGround(msg[1])
|
||||||
self.display.ground.setItems(msg[1])
|
self.display.ground.setItems(msg[1])
|
||||||
#grbox = self.display.getWidget("ground")
|
|
||||||
#grbox.setInventory(self.ground.items)
|
|
||||||
#grbox.select(self.ground.selector)
|
|
||||||
if msgType == "message":
|
if msgType == "message":
|
||||||
self.log(*msg[1:])
|
self.log(*msg[1:])
|
||||||
if msgType == "options":
|
if msgType == "options":
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
|
=
|
||||||
#import curses
|
|
||||||
#import curses.ascii
|
|
||||||
import string
|
import string
|
||||||
|
|
||||||
from .commandhandler import CommandHandler, InvalidCommandException
|
from .commandhandler import CommandHandler, InvalidCommandException
|
||||||
#from .keynames import nameFromKey
|
|
||||||
|
|
||||||
import ratuil.inputs as inp
|
import ratuil.inputs as inp
|
||||||
|
|
||||||
|
@ -23,7 +20,7 @@ class InputHandler:
|
||||||
|
|
||||||
def onInput(self, key):
|
def onInput(self, key):
|
||||||
if not self.typing:
|
if not self.typing:
|
||||||
keyName = key#nameFromKey(key)
|
keyName = key
|
||||||
if keyName in self.keybindings:
|
if keyName in self.keybindings:
|
||||||
self.commandHandler.execute(self.keybindings[keyName])
|
self.commandHandler.execute(self.keybindings[keyName])
|
||||||
else:
|
else:
|
||||||
|
@ -61,36 +58,36 @@ class InputHandler:
|
||||||
self.client.display.setInputString(self.string, self.cursor if self.typing else -1)
|
self.client.display.setInputString(self.string, self.cursor if self.typing else -1)
|
||||||
|
|
||||||
def addKey(self, key):
|
def addKey(self, key):
|
||||||
if key in string.printable:#curses.ascii.isprint(key):
|
if key in string.printable:
|
||||||
self.string = self.string[:self.cursor] + key + self.string[self.cursor:]
|
self.string = self.string[:self.cursor] + key + self.string[self.cursor:]
|
||||||
self.cursor += 1
|
self.cursor += 1
|
||||||
elif key == inp.BACKSPACE: #== curses.KEY_BACKSPACE or key == curses.ascii.BS or key == curses.ascii.DEL:
|
elif key == inp.BACKSPACE:
|
||||||
self.string = self.string[:self.cursor-1] + self.string[self.cursor:]
|
self.string = self.string[:self.cursor-1] + self.string[self.cursor:]
|
||||||
self.cursor = max(self.cursor - 1, 0)
|
self.cursor = max(self.cursor - 1, 0)
|
||||||
elif key == inp.RIGHT:#curses.KEY_RIGHT:
|
elif key == inp.RIGHT:
|
||||||
self.cursor = min(self.cursor + 1, len(self.string))
|
self.cursor = min(self.cursor + 1, len(self.string))
|
||||||
elif key == inp.LEFT:#curses.KEY_LEFT:
|
elif key == inp.LEFT:
|
||||||
self.cursor = max(self.cursor - 1, 0)
|
self.cursor = max(self.cursor - 1, 0)
|
||||||
elif key == inp.DELETE:#curses.KEY_DC:
|
elif key == inp.DELETE:
|
||||||
self.string = self.string[:self.cursor] + self.string[self.cursor+1:]
|
self.string = self.string[:self.cursor] + self.string[self.cursor+1:]
|
||||||
elif key == inp.HOME:#curses.KEY_HOME:
|
elif key == inp.HOME:
|
||||||
self.cursor = 0
|
self.cursor = 0
|
||||||
elif key == inp.END:#curses.KEY_END:
|
elif key == inp.END:
|
||||||
self.cursor = len(self.string)
|
self.cursor = len(self.string)
|
||||||
|
|
||||||
elif key == inp.ESCAPE:#curses.ascii.ESC or key == curses.KEY_DL:
|
elif key == inp.ESCAPE:
|
||||||
# throw away entered string and go back to game
|
# throw away entered string and go back to game
|
||||||
self.typing = False
|
self.typing = False
|
||||||
self.string = ""
|
self.string = ""
|
||||||
self.cursor = 0
|
self.cursor = 0
|
||||||
elif key == inp.ENTER:#curses.ascii.LF or key == curses.ascii.CR:
|
elif key == inp.ENTER:
|
||||||
# process entered string and reset it
|
# process entered string and reset it
|
||||||
message = self.string
|
message = self.string
|
||||||
self.string = ""
|
self.string = ""
|
||||||
self.cursor = 0
|
self.cursor = 0
|
||||||
self.typing = False
|
self.typing = False
|
||||||
self.processString(message)
|
self.processString(message)
|
||||||
elif key == "^I":#curses.ascii.TAB:
|
elif key == "^I": # tab
|
||||||
# return to game but keep entered string
|
# return to game but keep entered string
|
||||||
self.typing = False
|
self.typing = False
|
||||||
|
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
|
|
||||||
import curses
|
|
||||||
|
|
||||||
prenamed = {
|
|
||||||
10: "NEWLINE"
|
|
||||||
}
|
|
||||||
|
|
||||||
def nameFromKey(key):
|
|
||||||
if key in prenamed:
|
|
||||||
return prenamed[key]
|
|
||||||
try:
|
|
||||||
keyname = curses.keyname(key)
|
|
||||||
except ValueError:
|
|
||||||
return None
|
|
||||||
return str(keyname, "utf-8")
|
|
|
@ -6,6 +6,7 @@ import sys
|
||||||
import termios
|
import termios
|
||||||
import tty
|
import tty
|
||||||
import signal
|
import signal
|
||||||
|
#import os
|
||||||
|
|
||||||
from .connection import Connection
|
from .connection import Connection
|
||||||
from .gameclient import Client
|
from .gameclient import Client
|
||||||
|
@ -34,27 +35,6 @@ def main(argv=None):
|
||||||
oldterm = termios.tcgetattr(fd)
|
oldterm = termios.tcgetattr(fd)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Initialize curses
|
|
||||||
#stdscr = curses.initscr()
|
|
||||||
|
|
||||||
# Turn off echoing of keys, and enter cbreak mode,
|
|
||||||
# where no buffering is performed on keyboard input
|
|
||||||
#curses.noecho()
|
|
||||||
#curses.cbreak()
|
|
||||||
|
|
||||||
## In keypad mode, escape sequences for special keys
|
|
||||||
## (like the cursor keys) will be interpreted and
|
|
||||||
## a special value like curses.KEY_LEFT will be returned
|
|
||||||
#stdscr.keypad(1)
|
|
||||||
|
|
||||||
# Start color, too. Harmless if the terminal doesn't have
|
|
||||||
# color; user can test with has_color() later on. The try/catch
|
|
||||||
# works around a minor bit of over-conscientiousness in the curses
|
|
||||||
# module -- the error return from C start_color() is ignorable.
|
|
||||||
#try:
|
|
||||||
#curses.start_color()
|
|
||||||
#except:
|
|
||||||
#pass
|
|
||||||
|
|
||||||
tty.setraw(sys.stdin)
|
tty.setraw(sys.stdin)
|
||||||
Screen.default.hide_cursor()
|
Screen.default.hide_cursor()
|
||||||
|
@ -73,11 +53,6 @@ def main(argv=None):
|
||||||
closeMessage = client.closeMessage
|
closeMessage = client.closeMessage
|
||||||
finally:
|
finally:
|
||||||
## Set everything back to normal
|
## Set everything back to normal
|
||||||
#if 'stdscr' in locals():
|
|
||||||
#stdscr.keypad(0)
|
|
||||||
#curses.echo()
|
|
||||||
#curses.nocbreak()
|
|
||||||
#curses.endwin()
|
|
||||||
termios.tcsetattr(fd, termios.TCSADRAIN, oldterm)
|
termios.tcsetattr(fd, termios.TCSADRAIN, oldterm)
|
||||||
Screen.default.finalize()
|
Screen.default.finalize()
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,6 @@ class Display:
|
||||||
self.ground = ListSelector(self.getWidget("ground"))
|
self.ground = ListSelector(self.getWidget("ground"))
|
||||||
self.switch = ListSelector(self.getWidget("switchtitles"))
|
self.switch = ListSelector(self.getWidget("switchtitles"))
|
||||||
|
|
||||||
# it is important that these lists have the same order!
|
|
||||||
self.switch.setItems(["inventory", "equipment", "ground"])
|
self.switch.setItems(["inventory", "equipment", "ground"])
|
||||||
self.menus = {
|
self.menus = {
|
||||||
"inventory": self.inventory,
|
"inventory": self.inventory,
|
||||||
|
@ -76,14 +75,9 @@ class Display:
|
||||||
|
|
||||||
def getWidget(self, name):
|
def getWidget(self, name):
|
||||||
return self.layout.get(name)
|
return self.layout.get(name)
|
||||||
#if name in self.widgets:
|
|
||||||
#return self.widgets[name].getImpl()
|
|
||||||
#else:
|
|
||||||
#return None
|
|
||||||
|
|
||||||
def resizeField(self, size):
|
def resizeField(self, size):
|
||||||
self.getWidget("field").set_size(*size)
|
self.getWidget("field").set_size(*size)
|
||||||
#self.forced = True
|
|
||||||
|
|
||||||
def drawFieldCells(self, cells):
|
def drawFieldCells(self, cells):
|
||||||
field = self.getWidget("field")
|
field = self.getWidget("field")
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
from .listselector import ListSelector
|
|
||||||
|
|
||||||
class SwitchSelector(ListSelector):
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#def setItems(self, items):
|
|
||||||
#super().setItems(items)
|
|
||||||
#self.updateVisibility()
|
|
||||||
|
|
||||||
#def updateVisibility(self):
|
|
||||||
#pass
|
|
||||||
##for i, (_menu, widget, _title) in enumerate(self.items):
|
|
||||||
##if i == self.selector:
|
|
||||||
##widget.hidden = False
|
|
||||||
##widget.change()
|
|
||||||
##else:
|
|
||||||
##widget.hidden = True
|
|
||||||
|
|
||||||
def doSelect(self, value):
|
|
||||||
|
|
||||||
#self.getSelectedItem().widget.hidden = True
|
|
||||||
super().doSelect(value)
|
|
||||||
#self.updateVisibility()
|
|
||||||
#self.getSelectedItem().widimp.change()
|
|
||||||
#newWid.hidden = False
|
|
||||||
#newWid.change()
|
|
||||||
|
|
||||||
def itemName(self, item):
|
|
||||||
_menu, _widget, title = item
|
|
||||||
return title
|
|
Loading…
Reference in New Issue