st-minecraft 1.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- st_minecraft/__about__.py +3 -0
- st_minecraft/__init__.py +1 -0
- st_minecraft/core/__init__.py +3 -0
- st_minecraft/core/core.py +126 -0
- st_minecraft/de/__init__.py +14 -0
- st_minecraft/de/boss_leiste.py +134 -0
- st_minecraft/de/daten_modelle.py +309 -0
- st_minecraft/de/entity.py +148 -0
- st_minecraft/de/main.py +398 -0
- st_minecraft/de/material.py +1344 -0
- st_minecraft/en/__init__.py +14 -0
- st_minecraft/en/boss_bar.py +130 -0
- st_minecraft/en/data_models.py +278 -0
- st_minecraft/en/entity.py +131 -0
- st_minecraft/en/main.py +531 -0
- st_minecraft/en/material.py +1346 -0
- st_minecraft-1.1.0.dist-info/METADATA +160 -0
- st_minecraft-1.1.0.dist-info/RECORD +21 -0
- st_minecraft-1.1.0.dist-info/WHEEL +5 -0
- st_minecraft-1.1.0.dist-info/licenses/LICENSE.txt +661 -0
- st_minecraft-1.1.0.dist-info/top_level.txt +1 -0
st_minecraft/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
""" st_minecraft package """
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Core of the library, here communication with the server happens
|
|
3
|
+
this file also provides some helper functions
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import socket
|
|
8
|
+
from enum import Enum
|
|
9
|
+
from typing import Any
|
|
10
|
+
from typing import Optional
|
|
11
|
+
from typing import Type
|
|
12
|
+
from typing import TypeVar
|
|
13
|
+
|
|
14
|
+
# Global variable for the connection
|
|
15
|
+
connection: Optional[socket.socket] = None
|
|
16
|
+
|
|
17
|
+
ARG_SEPARATOR = "𝇉"
|
|
18
|
+
|
|
19
|
+
DEFAULT_PORT = 25595
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def connect(ip: str = "0.0.0.0", port: int = DEFAULT_PORT) -> None:
|
|
23
|
+
"""
|
|
24
|
+
Establishes a connection to the Minecraft server.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
ip (str): The IP address of the server (default is "0.0.0.0" - equivalent to "localhost")
|
|
28
|
+
port (int): The port of the server.
|
|
29
|
+
"""
|
|
30
|
+
# needed internally
|
|
31
|
+
global connection
|
|
32
|
+
if connection is not None:
|
|
33
|
+
connection.close()
|
|
34
|
+
|
|
35
|
+
# this allows us to develop more easily without having to adjust everything temporarily each time
|
|
36
|
+
_ip = os.getenv("SK_SERVER_OVERWRITE")
|
|
37
|
+
if _ip is not None:
|
|
38
|
+
spacer = "#" * 100
|
|
39
|
+
print(
|
|
40
|
+
f"{spacer}\n"
|
|
41
|
+
f"IP was overwritten by environment variable from '{ip}' to '{_ip}', "
|
|
42
|
+
f"(env var name: 'SK_SERVER_OVERWRITE')\n"
|
|
43
|
+
f"{spacer}"
|
|
44
|
+
)
|
|
45
|
+
ip = _ip
|
|
46
|
+
|
|
47
|
+
connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
48
|
+
connection.connect((ip, port))
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _receive(timeout: float = 2.0) -> bytes | None:
|
|
52
|
+
# needed internally
|
|
53
|
+
|
|
54
|
+
# this allows us to develop more easily without having to adjust everything temporarily each time
|
|
55
|
+
_timeout = os.getenv("SK_TIMEOUT_OVERWRITE")
|
|
56
|
+
if _timeout is not None:
|
|
57
|
+
if _timeout == "None":
|
|
58
|
+
_timeout = None
|
|
59
|
+
else:
|
|
60
|
+
_timeout = float(_timeout)
|
|
61
|
+
|
|
62
|
+
spacer = "#" * 100
|
|
63
|
+
print(
|
|
64
|
+
f"{spacer}\n"
|
|
65
|
+
f"Timeout was overwritten by environment variable from '{timeout}' to '{_timeout}', "
|
|
66
|
+
f"(env var name: 'SK_TIMEOUT_OVERWRITE')\n"
|
|
67
|
+
f"{spacer}"
|
|
68
|
+
)
|
|
69
|
+
timeout = _timeout
|
|
70
|
+
|
|
71
|
+
if timeout:
|
|
72
|
+
connection.settimeout(timeout) # Timeout in seconds
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
data = connection.recv(1024)
|
|
76
|
+
except socket.timeout:
|
|
77
|
+
raise NoDataError(f"Timeout: After {timeout} seconds no response was received from the server.")
|
|
78
|
+
|
|
79
|
+
return data
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _build_command(*args: Any) -> str:
|
|
83
|
+
"""
|
|
84
|
+
Takes all arguments, converts them to strings and builds the finished command from them
|
|
85
|
+
"""
|
|
86
|
+
return ARG_SEPARATOR.join(map(str, args))
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _bytes_to_text(b: bytes) -> str:
|
|
90
|
+
# needed internally
|
|
91
|
+
# bytes to text :)
|
|
92
|
+
return b.decode("utf-8").strip()
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _send_command(command: str) -> None:
|
|
96
|
+
"""
|
|
97
|
+
Sends a command over the global connection.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
command (str): The command to send.
|
|
101
|
+
"""
|
|
102
|
+
# needed internally
|
|
103
|
+
if connection is None:
|
|
104
|
+
raise RuntimeError("No connection to server. Please connect first.")
|
|
105
|
+
|
|
106
|
+
command = f"{command}\n"
|
|
107
|
+
connection.sendall(command.encode("utf-8"))
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
E = TypeVar("E", bound=Enum)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def _to_enum(enum: Type[E], value: Any) -> Optional[E]:
|
|
114
|
+
return enum._value2member_map_.get(value)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class NoDataError(ValueError):
|
|
118
|
+
"""Raised when we receive nothing from the API"""
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class WertFehler(ValueError):
|
|
122
|
+
"""ValueError aber deutsch :clown face:"""
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class InventoryFieldEmptyError(KeyError):
|
|
126
|
+
"""Raised when trying to access an inventory field that is empty."""
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from st_minecraft.core import connect as verbinden # noqa: unused-import
|
|
2
|
+
from st_minecraft.de.boss_leiste import * # noqa: unused-import
|
|
3
|
+
from st_minecraft.de.daten_modelle import * # noqa: unused-import
|
|
4
|
+
from st_minecraft.de.main import * # noqa: unused-import
|
|
5
|
+
|
|
6
|
+
try:
|
|
7
|
+
from st_minecraft.de.entity import * # noqa: unused-import
|
|
8
|
+
from st_minecraft.de.material import * # noqa: unused-import
|
|
9
|
+
|
|
10
|
+
except ModuleNotFoundError as e:
|
|
11
|
+
raise RuntimeError(
|
|
12
|
+
f"Es ist nicht möglich die auto-generierten Enums für Material und/oder Entity zu importieren."
|
|
13
|
+
f"Bitte überprüfe, ob diese vorliegen, falls nicht siehe bitte ressourcen/generate_enums.py im git repo."
|
|
14
|
+
) from e
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"""Ermöglicht das erstellen und konfigurieren von Bossleisten"""
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel
|
|
6
|
+
|
|
7
|
+
import st_minecraft.en as __st_minecraft_en
|
|
8
|
+
import st_minecraft.en.boss_bar as _st_minecraft_en_boss_bar
|
|
9
|
+
from st_minecraft.core.core import WertFehler
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BossLeisteStil(Enum):
|
|
13
|
+
"""Möglichkeiten in denen der Stil einer Bossleiste angezeigt werden kann"""
|
|
14
|
+
|
|
15
|
+
DURCHGEZOGEN = "solid"
|
|
16
|
+
SEGMENTE_6 = "segmented_6"
|
|
17
|
+
SEGMENTE_10 = "segmented_10"
|
|
18
|
+
SEGMENTE_12 = "segmented_12"
|
|
19
|
+
SEGMENTE_20 = "segmented_20"
|
|
20
|
+
|
|
21
|
+
@staticmethod
|
|
22
|
+
def von_englisch(boss_bar_stil: _st_minecraft_en_boss_bar.BossBarStyle) -> "BossLeisteStil":
|
|
23
|
+
return BossLeisteStil._value2member_map_[boss_bar_stil.value]
|
|
24
|
+
|
|
25
|
+
def zu_englisch(self) -> _st_minecraft_en_boss_bar.BossBarStyle:
|
|
26
|
+
return _st_minecraft_en_boss_bar.BossBarStyle._value2member_map_[self.value]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class BossLeisteFarben(Enum):
|
|
30
|
+
"""Farben in denen eine Bossleiste angezeigt werden kann"""
|
|
31
|
+
|
|
32
|
+
BLAU = "blue"
|
|
33
|
+
GRÜN = "green"
|
|
34
|
+
PINK = "pink"
|
|
35
|
+
LILA = "purple"
|
|
36
|
+
ROT = "red"
|
|
37
|
+
WEIß = "white"
|
|
38
|
+
GELB = "yellow"
|
|
39
|
+
|
|
40
|
+
@staticmethod
|
|
41
|
+
def von_englisch(boss_bar_farbe: _st_minecraft_en_boss_bar.BossBarColor) -> "BossLeisteFarben":
|
|
42
|
+
return BossLeisteFarben._value2member_map_[boss_bar_farbe.value]
|
|
43
|
+
|
|
44
|
+
def zu_englisch(self) -> _st_minecraft_en_boss_bar.BossBarColor:
|
|
45
|
+
return _st_minecraft_en_boss_bar.BossBarColor._value2member_map_[self.value]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class BossLeiste(BaseModel):
|
|
49
|
+
"""Modell einer Bossleiste"""
|
|
50
|
+
|
|
51
|
+
name: str
|
|
52
|
+
""" Der von dir für die Leiste gesetze Name """
|
|
53
|
+
anzeige_text: str
|
|
54
|
+
""" Der Text der auf der Leiste angezeigt wird """
|
|
55
|
+
wert: float # zwischen 0 und 1
|
|
56
|
+
""" Wie viel von der Leiste gefüllt sein soll (zwischen 0 und 1) """
|
|
57
|
+
stil: BossLeisteStil
|
|
58
|
+
""" Anzeige Stil der Leiste (siehe BossLeisteStil) """
|
|
59
|
+
farbe: BossLeisteFarben
|
|
60
|
+
""" Anzeige Farbe der Leiste (siehe BossLeisteFarbe) """
|
|
61
|
+
|
|
62
|
+
def __repr__(self):
|
|
63
|
+
return (
|
|
64
|
+
f"BossLeiste(name={self.name}, "
|
|
65
|
+
f"anzeige_text={self.anzeige_text}, "
|
|
66
|
+
f"wert={self.wert:.2f}, "
|
|
67
|
+
f"stil={self.stil}, "
|
|
68
|
+
f"farbe={self.farbe})"
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
@staticmethod
|
|
72
|
+
def von_englisch(boss_bar: _st_minecraft_en_boss_bar.BossBar) -> "BossLeiste":
|
|
73
|
+
return BossLeiste(
|
|
74
|
+
name=boss_bar.name,
|
|
75
|
+
anzeige_text=boss_bar.display_text,
|
|
76
|
+
wert=boss_bar.value,
|
|
77
|
+
stil=BossLeisteStil.von_englisch(boss_bar.style),
|
|
78
|
+
farbe=BossLeisteFarben.von_englisch(boss_bar.color),
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
def zu_englisch(self) -> _st_minecraft_en_boss_bar.BossBar:
|
|
82
|
+
return _st_minecraft_en_boss_bar.BossBar(
|
|
83
|
+
name=self.name,
|
|
84
|
+
display_text=self.anzeige_text,
|
|
85
|
+
value=self.wert,
|
|
86
|
+
style=self.stil.zu_englisch(),
|
|
87
|
+
color=self.farbe.zu_englisch(),
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def erzeuge_leiste(name: str, anzeige_text: str) -> BossLeiste:
|
|
92
|
+
"""
|
|
93
|
+
Erstelle eine Bossleiste
|
|
94
|
+
Args:
|
|
95
|
+
name: Ein von dir gewählter Name, wie die Bossleiste für dich heißen soll
|
|
96
|
+
anzeige_text: Text der an der Leiste angezeigt werden soll
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
Ein BossLeisten Objekt mit dessen Hilfe du die Leiste weiter konfigurieren kannst
|
|
100
|
+
"""
|
|
101
|
+
b = __st_minecraft_en.create_bar(name, anzeige_text)
|
|
102
|
+
return BossLeiste.von_englisch(b)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def setze_text(boss_leiste: BossLeiste, anzeige_text: str) -> BossLeiste:
|
|
106
|
+
"""Setze den Text der Leiste"""
|
|
107
|
+
b = __st_minecraft_en.set_text(boss_leiste.zu_englisch(), anzeige_text)
|
|
108
|
+
return BossLeiste.von_englisch(b)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def setze_farbe(boss_leiste: BossLeiste, farbe: BossLeisteFarben) -> BossLeiste:
|
|
112
|
+
"""Setze die Farbe der Leiste"""
|
|
113
|
+
b = __st_minecraft_en.set_color(boss_leiste.zu_englisch(), farbe.zu_englisch())
|
|
114
|
+
return BossLeiste.von_englisch(b)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def setze_wert(boss_leiste: BossLeiste, wert: float) -> BossLeiste:
|
|
118
|
+
"""Setze zu welchem Anteil die leiste gefüllt sein soll (zwischen 0 und 1)"""
|
|
119
|
+
if not 0 <= wert <= 1:
|
|
120
|
+
raise WertFehler(f"Der Wert der Bossleiste muss zwischen 0 und 1 liegen. Du hast '{wert}' angegeben.")
|
|
121
|
+
|
|
122
|
+
b = __st_minecraft_en.set_value(boss_leiste.zu_englisch(), wert)
|
|
123
|
+
return BossLeiste.von_englisch(b)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def setze_stil(boss_leiste: BossLeiste, stil: BossLeisteStil) -> BossLeiste:
|
|
127
|
+
"""Setze den Stil der Leiste"""
|
|
128
|
+
b = __st_minecraft_en.set_style(boss_leiste.zu_englisch(), stil.zu_englisch())
|
|
129
|
+
return BossLeiste.von_englisch(b)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def loesche_leiste(boss_leiste: BossLeiste):
|
|
133
|
+
"""Lösche eine Leiste"""
|
|
134
|
+
__st_minecraft_en.delete_bar(boss_leiste.zu_englisch())
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel
|
|
5
|
+
|
|
6
|
+
from st_minecraft.core.core import InventoryFieldEmptyError
|
|
7
|
+
from st_minecraft.core.core import _to_enum
|
|
8
|
+
from st_minecraft.de.entity import EntitySammlung
|
|
9
|
+
from st_minecraft.de.material import MaterialSammlung
|
|
10
|
+
from st_minecraft.en import Dimension
|
|
11
|
+
from st_minecraft.en import DirectionCollection as _DirectionCollection
|
|
12
|
+
from st_minecraft.en import Entity as _EntityEN
|
|
13
|
+
from st_minecraft.en import Inventory as _InventoryEN
|
|
14
|
+
from st_minecraft.en import InventoryField as _InventoryFieldEN
|
|
15
|
+
from st_minecraft.en import Item as _ItemEN
|
|
16
|
+
from st_minecraft.en import Material as _MaterialEN
|
|
17
|
+
from st_minecraft.en import Message as _MessageEN
|
|
18
|
+
from st_minecraft.en import Player as _PlayerEN
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class RichtungSammlung(Enum):
|
|
22
|
+
"""
|
|
23
|
+
Arten, wie Geschwindigkeiten verändert werden können
|
|
24
|
+
Wird u.A. in spieler_geschwindigkeit_setzen() verwendet.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
Hoch = "UP"
|
|
28
|
+
Runter = "DOWN"
|
|
29
|
+
Zurück = "BACK"
|
|
30
|
+
Vorwärts = "LOOKING"
|
|
31
|
+
|
|
32
|
+
@staticmethod
|
|
33
|
+
def von_englisch(e: _DirectionCollection) -> "RichtungSammlung":
|
|
34
|
+
return RichtungSammlung._value2member_map_[e.value]
|
|
35
|
+
|
|
36
|
+
def zu_englisch(self) -> _DirectionCollection:
|
|
37
|
+
return _DirectionCollection._value2member_map_[self.value]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class Material(BaseModel):
|
|
41
|
+
"""
|
|
42
|
+
Modelliert einen Block in Minecraft, der sich zum Zeitpunkt der Abfrage an einer bestimmten Koordinate befindet.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
typ: MaterialSammlung | None
|
|
46
|
+
""" Block Typ """
|
|
47
|
+
x: int | None = None
|
|
48
|
+
y: int | None = None
|
|
49
|
+
z: int | None = None
|
|
50
|
+
dimension: Dimension | None = None
|
|
51
|
+
|
|
52
|
+
def __repr__(self):
|
|
53
|
+
return f"Block(typ={self.typ}, x={self.x}, y={self.y}, z={self.z}, dimension={self.dimension})"
|
|
54
|
+
|
|
55
|
+
@staticmethod
|
|
56
|
+
def von_englisch(m: _MaterialEN | None) -> Optional["Material"]:
|
|
57
|
+
if m is None:
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
return Material(
|
|
61
|
+
typ=MaterialSammlung.von_englisch(m.type),
|
|
62
|
+
x=m.x,
|
|
63
|
+
y=m.y,
|
|
64
|
+
z=m.z,
|
|
65
|
+
dimension=m.dimension,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
def zu_englisch(self) -> _MaterialEN:
|
|
69
|
+
if self.typ is None:
|
|
70
|
+
return None
|
|
71
|
+
|
|
72
|
+
return _MaterialEN(
|
|
73
|
+
type=self.typ.zu_englisch(),
|
|
74
|
+
x=self.x,
|
|
75
|
+
y=self.y,
|
|
76
|
+
z=self.z,
|
|
77
|
+
dimension=self.dimension,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class Spieler(BaseModel):
|
|
82
|
+
"""Momentaufnahme zum Zeitpunkt der Abfrage, die Daten werden NICHT dauerhaft aktualisiert!"""
|
|
83
|
+
|
|
84
|
+
id: int
|
|
85
|
+
""" Eindeutige ID des Spielers """
|
|
86
|
+
name: str
|
|
87
|
+
""" Name des Spielers """
|
|
88
|
+
x: int
|
|
89
|
+
y: int
|
|
90
|
+
z: int
|
|
91
|
+
dimension: Dimension
|
|
92
|
+
rotation: int
|
|
93
|
+
""" Rotation des Spielers von -180 bis 180 """
|
|
94
|
+
schaut_auf: Material | None
|
|
95
|
+
""" Der nächste Block auf den Spieler schaut (maximal 100 Blöcke weit entfernt) """
|
|
96
|
+
sneaked: bool
|
|
97
|
+
""" True wenn Player sneaked """
|
|
98
|
+
max_leben: float
|
|
99
|
+
leben: float
|
|
100
|
+
hunger: float
|
|
101
|
+
sättigung: float
|
|
102
|
+
xp_level: float
|
|
103
|
+
xp_fortschritt: float
|
|
104
|
+
|
|
105
|
+
@staticmethod
|
|
106
|
+
def von_englisch(p: _PlayerEN):
|
|
107
|
+
return Spieler(
|
|
108
|
+
id=p.id,
|
|
109
|
+
name=p.name,
|
|
110
|
+
x=p.x,
|
|
111
|
+
y=p.y,
|
|
112
|
+
z=p.z,
|
|
113
|
+
dimension=p.dimension,
|
|
114
|
+
rotation=p.rotation,
|
|
115
|
+
schaut_auf=Material.von_englisch(p.looking_at),
|
|
116
|
+
sneaked=p.sneaked,
|
|
117
|
+
max_leben=p.max_health,
|
|
118
|
+
leben=p.health,
|
|
119
|
+
hunger=p.hunger,
|
|
120
|
+
sättigung=p.saturation,
|
|
121
|
+
xp_level=p.xp_level,
|
|
122
|
+
xp_fortschritt=p.xp_progress,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
def zu_englisch(self) -> _PlayerEN:
|
|
126
|
+
return _PlayerEN(
|
|
127
|
+
id=self.id,
|
|
128
|
+
name=self.name,
|
|
129
|
+
x=self.x,
|
|
130
|
+
y=self.y,
|
|
131
|
+
z=self.z,
|
|
132
|
+
dimension=self.dimension,
|
|
133
|
+
rotation=self.rotation,
|
|
134
|
+
looking_at=self.schaut_auf.zu_englisch(),
|
|
135
|
+
sneaked=self.sneaked,
|
|
136
|
+
max_health=self.max_leben,
|
|
137
|
+
health=self.leben,
|
|
138
|
+
hunger=self.hunger,
|
|
139
|
+
saturation=self.sättigung,
|
|
140
|
+
xp_level=self.xp_level,
|
|
141
|
+
xp_progress=self.xp_fortschritt,
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
def __repr__(self):
|
|
145
|
+
return (
|
|
146
|
+
f"Spieler("
|
|
147
|
+
f"id={self.id}, "
|
|
148
|
+
f"name={self.name}, "
|
|
149
|
+
f"x={self.x}, "
|
|
150
|
+
f"y={self.y}, "
|
|
151
|
+
f"z={self.z}, "
|
|
152
|
+
f"dimension={self.dimension}, "
|
|
153
|
+
f"rotation={self.rotation}, "
|
|
154
|
+
f"leben={self.leben}, "
|
|
155
|
+
f"max_leben={self.max_leben}, "
|
|
156
|
+
f"hunger={self.hunger}, "
|
|
157
|
+
f"sättigung={self.sättigung}, "
|
|
158
|
+
f"xp_level={self.xp_level}, "
|
|
159
|
+
f"xp_fortschritt={self.xp_fortschritt}, "
|
|
160
|
+
f"sneaked={self.sneaked}, "
|
|
161
|
+
f"schaut_auf={self.schaut_auf}, "
|
|
162
|
+
")"
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class Entity(BaseModel):
|
|
167
|
+
"""Modelliert ein Entity. Viele der Informationen können leer (None) sein"""
|
|
168
|
+
|
|
169
|
+
typ: EntitySammlung
|
|
170
|
+
""" Typ des Entity's """
|
|
171
|
+
id: str | None = None
|
|
172
|
+
""" Einzigartige ID für dieses Entity """
|
|
173
|
+
name: str | None = None
|
|
174
|
+
x: float | None = None
|
|
175
|
+
y: float | None = None
|
|
176
|
+
z: float | None = None
|
|
177
|
+
dimension: Dimension | None = None
|
|
178
|
+
leben: float | None = None
|
|
179
|
+
ai: bool | None = None
|
|
180
|
+
|
|
181
|
+
def __repr__(self):
|
|
182
|
+
return (
|
|
183
|
+
f"Entity("
|
|
184
|
+
f"typ={self.typ}, "
|
|
185
|
+
f"name={self.name}, "
|
|
186
|
+
f"x={self.x}, "
|
|
187
|
+
f"y={self.y}, "
|
|
188
|
+
f"z={self.z}, "
|
|
189
|
+
f"dimension={self.dimension}, "
|
|
190
|
+
f"leben={self.leben}, "
|
|
191
|
+
f"ai={self.ai}, "
|
|
192
|
+
f"id={self.id}, "
|
|
193
|
+
")"
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
@staticmethod
|
|
197
|
+
def von_string(typ: str):
|
|
198
|
+
# TODO: brauchen wir das? falls nein können wir die default-Nones entfernen
|
|
199
|
+
return Entity(typ=_to_enum(EntitySammlung, typ))
|
|
200
|
+
|
|
201
|
+
@staticmethod
|
|
202
|
+
def von_englisch(e: _EntityEN):
|
|
203
|
+
return Entity(
|
|
204
|
+
typ=EntitySammlung.von_englisch(e.type),
|
|
205
|
+
id=e.id,
|
|
206
|
+
name=e.name,
|
|
207
|
+
x=e.x,
|
|
208
|
+
y=e.y,
|
|
209
|
+
z=e.z,
|
|
210
|
+
dimension=e.dimension,
|
|
211
|
+
leben=e.health,
|
|
212
|
+
ai=e.ai,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
def zu_englisch(self) -> _EntityEN:
|
|
216
|
+
return _EntityEN(
|
|
217
|
+
type=self.typ.zu_englisch(),
|
|
218
|
+
id=self.id,
|
|
219
|
+
name=self.name,
|
|
220
|
+
x=self.x,
|
|
221
|
+
y=self.y,
|
|
222
|
+
z=self.z,
|
|
223
|
+
dimension=self.dimension,
|
|
224
|
+
health=self.leben,
|
|
225
|
+
ai=self.ai,
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
class Item(BaseModel):
|
|
230
|
+
"""Modelliert ein Item"""
|
|
231
|
+
|
|
232
|
+
typ: MaterialSammlung
|
|
233
|
+
anzeige_name: str | None
|
|
234
|
+
|
|
235
|
+
def __repr__(self):
|
|
236
|
+
return f"Item(typ={self.typ}, anzeige_name={self.anzeige_name})"
|
|
237
|
+
|
|
238
|
+
@staticmethod
|
|
239
|
+
def von_englisch(i: _ItemEN):
|
|
240
|
+
return Item(typ=MaterialSammlung.von_englisch(i.type), anzeige_name=i.display_name)
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
class InventarFeld(BaseModel):
|
|
244
|
+
"""Ein Feld im Inventar eine:r Spieler:in"""
|
|
245
|
+
|
|
246
|
+
index: int
|
|
247
|
+
""" Index wo das Feld im Inventar liegt """
|
|
248
|
+
item: Item
|
|
249
|
+
""" Item Objekt, welches Item in dem Feld liegt """
|
|
250
|
+
anzahl: int
|
|
251
|
+
""" Wie viele von dem Item in diesem Feld liegen """
|
|
252
|
+
|
|
253
|
+
def __repr__(self):
|
|
254
|
+
return f"InventarFeld(index={self.index}, item={self.item!r}, anzahl={self.anzahl})"
|
|
255
|
+
|
|
256
|
+
@staticmethod
|
|
257
|
+
def von_englisch(i: _InventoryFieldEN):
|
|
258
|
+
return InventarFeld(index=i.index, item=Item.von_englisch(i.item), anzahl=i.amount)
|
|
259
|
+
|
|
260
|
+
def zu_englisch(self) -> _InventoryFieldEN:
|
|
261
|
+
return _InventoryFieldEN(index=self.index, item=self.item.zu_englisch(), amount=self.anzahl)
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
class Inventar(dict[int, InventarFeld]):
|
|
265
|
+
"""
|
|
266
|
+
Enthält das gesamte Inventar eines Spielers.
|
|
267
|
+
Die Struktur ist ein dict.
|
|
268
|
+
Das dict zeigt von Index des Inventars auf ein Objekt vom Typ InventarFeld, welcher die Infos über das Element in dem Feld enthält.
|
|
269
|
+
Hinweis: Felder, die Leer sind, sind nicht in dem dict enthalten!
|
|
270
|
+
"""
|
|
271
|
+
|
|
272
|
+
def __contains__(self, item: Item):
|
|
273
|
+
"""Überprüfe, ob ein Item im Inventar ist"""
|
|
274
|
+
for _, v in self.items():
|
|
275
|
+
if v.item == item:
|
|
276
|
+
return True
|
|
277
|
+
return False
|
|
278
|
+
|
|
279
|
+
def __getitem__(self, item: int):
|
|
280
|
+
try:
|
|
281
|
+
super().__getitem__(item)
|
|
282
|
+
# ich glaube, hier ist der peak der library. ein nicht-generischer wrapper um den KeyError.
|
|
283
|
+
except KeyError:
|
|
284
|
+
raise InventoryFieldEmptyError(f"Das Feld {item} ist leer. Daher kannst du hier nicht drauf zugreifen.")
|
|
285
|
+
|
|
286
|
+
@staticmethod
|
|
287
|
+
def von_englisch(i: _InventoryEN):
|
|
288
|
+
return Inventar({index: InventarFeld.von_englisch(field) for index, field in i.items()})
|
|
289
|
+
|
|
290
|
+
def zu_englisch(self) -> _InventoryEN:
|
|
291
|
+
return _InventoryEN({index: field.zu_englisch() for index, field in self.items()})
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
class Nachricht(BaseModel):
|
|
295
|
+
"""
|
|
296
|
+
Repräsentiert eine Nachricht, die vom Nutzer an den Chat gesendet wurde
|
|
297
|
+
"""
|
|
298
|
+
|
|
299
|
+
text: str
|
|
300
|
+
"""Der in den Chat gesendete Text"""
|
|
301
|
+
sender_name: str
|
|
302
|
+
"""Name des Spielers, der diese Nachricht gesendet hat"""
|
|
303
|
+
|
|
304
|
+
@staticmethod
|
|
305
|
+
def von_englisch(m: _MessageEN):
|
|
306
|
+
return Nachricht(text=m.text, absender_name=m.sender_name)
|
|
307
|
+
|
|
308
|
+
def zu_englisch(self) -> _MessageEN:
|
|
309
|
+
return _MessageEN(text=self.text, sender_name=self.absender_name)
|