Skip to content

Commit 359bf7c

Browse files
committed
implement most functions in python wrapper
1 parent e80527c commit 359bf7c

File tree

11 files changed

+617
-67
lines changed

11 files changed

+617
-67
lines changed

python/bot/bot.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import random
12
from uwapi import *
23

34
class Bot:
@@ -8,10 +9,25 @@ def __init__(self):
89
uw_events.on_update(self.on_update)
910

1011
def attack_nearest_enemies(self):
11-
pass # todo
12+
own_units = [x for x in uw_world.entities().values() if x.own() and x.Unit is not None and x.proto().data.get("dps", 0) > 0]
13+
if not own_units:
14+
return
15+
enemy_units = [x for x in uw_world.entities().values() if x.enemy() and x.Unit is not None]
16+
if not enemy_units:
17+
return
18+
for own in own_units:
19+
if len(uw_commands.orders(own.id)) == 0:
20+
enemy = min(enemy_units, key=lambda x: uw_map.distance_estimate(own.pos(), x.pos()))
21+
uw_commands.order(own.id, uw_commands.fight_to_entity(enemy.id))
1222

1323
def assign_random_recipes(self):
14-
pass # todo
24+
for own in uw_world.entities().values():
25+
if not own.own() or own.Unit is None or own.Recipe is not None:
26+
continue
27+
recipes = own.proto().data.get("recipes", [])
28+
if recipes:
29+
recipe = random.choice(recipes)
30+
uw_commands.set_recipe(own.id, recipe)
1531

1632
def configure(self):
1733
if self.is_configured:

python/uwapi/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
from .interop import *
66
from .admin import uw_admin
77
from .commands import uw_commands
8-
from .entity import Entity
8+
from .entity import Entity, INVALID
99
from .events import uw_events
1010
from .game import uw_game
1111
from .library import UwapiLibrary
1212
from .map import uw_map
1313
from .prototypes import uw_prototypes
1414
from .world import uw_world
1515

16-
__all__ = ["uw_admin","uw_commands","Entity","uw_events","uw_game","UwapiLibrary","uw_map","uw_prototypes","uw_world","Severity","LogCallback","ConnectionState","MyPlayer","AssistConfig","PerformanceStatistics","OrderType","OrderPriority","Order","Orders","Ids","Priority","Ping","PathState","ForeignPolicy","ChatTarget","ProtoComponent","OwnerComponent","ControllerComponent","PositionComponent","UnitState","UnitComponent","LifeComponent","ManaComponent","MoveComponent","AimComponent","RecipeComponent","RecipeStatisticsComponent","LogisticsTimestampComponent","PriorityComponent","AmountComponent","AttachmentComponent","PingComponent","PlayerState","PlayerConnectionClass","PlayerComponent","PlayerAiConfigComponent","ForceState","ForceComponent","ForceDetailsComponent","ForeignPolicyComponent","DiplomacyProposalComponent","GameState","ShootingUnit","ShootingData","ShootingArray","ExplosionData","ExplosionsArray","TaskType","MapState","MapInfo","MapStartingPosition","MapStartingPositionsArray","Tile","Cluster","ClustersDistancesQuery","ClustersDistancesResult","PrototypeType","MyForceStatistics","UnitUpgrades","Overview","OverviewExtract","UnitPathfindingQuery","UnitPathfindingResult"]
16+
__all__ = ["uw_admin","uw_commands","Entity","INVALID","uw_events","uw_game","UwapiLibrary","uw_map","uw_prototypes","uw_world","Severity","LogCallback","ConnectionState","MyPlayer","AssistConfig","PerformanceStatistics","OrderType","OrderPriority","Order","Orders","Ids","Priority","Ping","PathState","ForeignPolicy","ChatTarget","ProtoComponent","OwnerComponent","ControllerComponent","PositionComponent","UnitState","UnitComponent","LifeComponent","ManaComponent","MoveComponent","AimComponent","RecipeComponent","RecipeStatisticsComponent","LogisticsTimestampComponent","PriorityComponent","AmountComponent","AttachmentComponent","PingComponent","PlayerState","PlayerConnectionClass","PlayerComponent","PlayerAiConfigComponent","ForceState","ForceComponent","ForceDetailsComponent","ForeignPolicyComponent","DiplomacyProposalComponent","GameState","ShootingUnit","ShootingData","ShootingArray","ExplosionData","ExplosionsArray","TaskType","MapState","MapInfo","MapStartingPosition","MapStartingPositionsArray","Tile","Cluster","ClustersDistancesQuery","ClustersDistancesResult","PrototypeType","MyForceStatistics","UnitUpgrades","Overview","OverviewExtract","UnitPathfindingQuery","UnitPathfindingResult"]

python/uwapi/admin.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from .interop import *
22

3+
INVALID: int = 0xFFFFFFFF
4+
35
class Admin:
46
_instance = None
57

@@ -8,4 +10,64 @@ def __new__(cls):
810
cls._instance = super().__new__(cls)
911
return cls._instance
1012

13+
def get_lobby_id(self) -> int:
14+
return uw_interop.uwGetLobbyId()
15+
16+
def get_user_id(self) -> int:
17+
return uw_interop.uwGetUserId()
18+
19+
def get_server_port(self) -> int:
20+
return uw_interop.uwGetServerPort()
21+
22+
def set_map_selection(self, path: str) -> None:
23+
uw_interop.uwAdminSetMapSelection(path)
24+
25+
def start_game(self) -> None:
26+
uw_interop.uwAdminStartGame()
27+
28+
def terminate_game(self) -> None:
29+
uw_interop.uwAdminTerminateGame()
30+
31+
def set_game_speed(self, speed: float) -> None:
32+
uw_interop.uwAdminSetGameSpeed(speed)
33+
34+
def set_weather_speed(self, speed: float, offset: float) -> None:
35+
uw_interop.uwAdminSetWeatherSpeed(speed, offset)
36+
37+
def add_ai(self) -> None:
38+
uw_interop.uwAdminAddAi()
39+
40+
def kick_player(self, player_id: int) -> None:
41+
uw_interop.uwAdminKickPlayer(player_id)
42+
43+
def player_set_admin(self, player_id: int, admin: bool) -> None:
44+
uw_interop.uwAdminPlayerSetAdmin(player_id, admin)
45+
46+
def player_set_name(self, player_id: int, name: str) -> None:
47+
uw_interop.uwAdminPlayerSetName(player_id, name)
48+
49+
def player_join_force(self, player_id: int, force_id: int) -> None:
50+
uw_interop.uwAdminPlayerJoinForce(player_id, force_id)
51+
52+
def force_join_team(self, force_id: int, team: int) -> None:
53+
uw_interop.uwAdminForceJoinTeam(force_id, team)
54+
55+
def force_set_color(self, force_id: int, r: float, g: float, b: float) -> None:
56+
uw_interop.uwAdminForceSetColor(force_id, r, g, b)
57+
58+
def force_set_race(self, force_id: int, race_proto: int) -> None:
59+
uw_interop.uwAdminForceSetRace(force_id, race_proto)
60+
61+
def send_suggested_camera_focus(self, position: int) -> None:
62+
uw_interop.uwAdminSendSuggestedCameraFocus(position)
63+
64+
def set_automatic_suggested_camera_focus(self, enabled: bool) -> None:
65+
uw_interop.uwAdminSetAutomaticSuggestedCameraFocus(enabled)
66+
67+
def send_chat(self, msg: str, flags, id: int = INVALID) -> None:
68+
uw_interop.uwAdminSendChat(msg, flags, id)
69+
70+
def send_ping(self, position: int, ping, id: int) -> None:
71+
uw_interop.uwAdminSendPing(position, ping, id)
72+
1173
uw_admin = Admin()

python/uwapi/commands.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from .interop import *
22

3+
INVALID: int = 0xFFFFFFFF
4+
35
class Commands:
46
_instance = None
57

@@ -8,4 +10,81 @@ def __new__(cls):
810
cls._instance = super().__new__(cls)
911
return cls._instance
1012

13+
def orders(self, unit_id: int) -> list[UwOrder]:
14+
return uw_interop.uwOrders(unit_id).orders
15+
16+
def order(self, unit_id: int, order: UwOrder) -> None:
17+
uw_interop.uwOrder(unit_id, order)
18+
19+
def stop(self) -> UwOrder:
20+
o = self._default_order()
21+
o.order = UwOrderTypeEnum.Stop
22+
return o
23+
24+
def guard(self) -> UwOrder:
25+
o = self._default_order()
26+
o.order = UwOrderTypeEnum.Guard
27+
return o
28+
29+
def run_to_position(self, position: int) -> UwOrder:
30+
o = self._default_order()
31+
o.position = position
32+
o.order = UwOrderTypeEnum.Run
33+
return o
34+
35+
def run_to_entity(self, entity_id: int) -> UwOrder:
36+
o = self._default_order()
37+
o.entity = entity_id
38+
o.order = UwOrderTypeEnum.Run
39+
return o
40+
41+
def fight_to_position(self, position: int) -> UwOrder:
42+
o = self._default_order()
43+
o.position = position
44+
o.order = UwOrderTypeEnum.Fight
45+
return o
46+
47+
def fight_to_entity(self, entity_id: int) -> UwOrder:
48+
o = self._default_order()
49+
o.entity = entity_id
50+
o.order = UwOrderTypeEnum.Fight
51+
return o
52+
53+
def place_construction(
54+
self,
55+
construction_proto: int,
56+
position: int,
57+
yaw: float = 0,
58+
recipe_proto: int = 0,
59+
priority: UwPriorityEnum = UwPriorityEnum.Normal
60+
) -> None:
61+
uw_interop.uwCommandPlaceConstruction(construction_proto, position, yaw, recipe_proto, priority)
62+
63+
def set_recipe(self, unit_id: int, recipe_proto: int) -> None:
64+
uw_interop.uwCommandSetRecipe(unit_id, recipe_proto)
65+
66+
def set_priority(self, unit_id: int, priority : UwPriorityEnum) -> None:
67+
uw_interop.uwCommandSetPriority(unit_id, priority)
68+
69+
def load(self, unit_id: int, resource_proto: int) -> None:
70+
uw_interop.uwCommandLoad(unit_id, resource_proto)
71+
72+
def unload(self, unit_id: int) -> None:
73+
uw_interop.uwCommandUnload(unit_id)
74+
75+
def move(self, unit_id: int, position: int, yaw: float = 0) -> None:
76+
uw_interop.uwCommandMove(unit_id, position, yaw)
77+
78+
def aim(self, unit_id: int, target_id: int) -> None:
79+
uw_interop.uwCommandAim(unit_id, target_id)
80+
81+
def renounce_control(self, entity_id: int) -> None:
82+
uw_interop.uwCommandRenounceControl(entity_id)
83+
84+
def self_destruct(self, entity_id: int) -> None:
85+
uw_interop.uwCommandSelfDestruct(entity_id)
86+
87+
def _default_order(self) -> UwOrder:
88+
return UwOrder(INVALID, INVALID, UwOrderTypeEnum.Nothing, UwOrderPriorityFlags.User)
89+
1190
uw_commands = Commands()

python/uwapi/entity.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
from dataclasses import dataclass
22
from typing import Optional
33
from .interop import *
4+
from .prototypes import uw_prototypes, Prototype
5+
6+
INVALID: int = 0xFFFFFFFF
7+
8+
def _make_empty_UwUnitUpgrades() -> UwUnitUpgrades:
9+
return UwUnitUpgrades(0, 0, 0, 0, 0, 0, 0)
410

511
@dataclass
612
class Entity:
713
id: int
14+
fresh: bool = True
15+
destroyed: bool = False
816

917
Proto: Optional[UwProtoComponent] = None
1018
Owner: Optional[UwOwnerComponent] = None
@@ -28,3 +36,33 @@ class Entity:
2836
ForceDetails: Optional[UwForceDetailsComponent] = None
2937
ForeignPolicy: Optional[UwForeignPolicyComponent] = None
3038
DiplomacyProposal: Optional[UwDiplomacyProposalComponent] = None
39+
40+
def pos(self) -> int:
41+
return self.Position.position if self.Position is not None else INVALID
42+
43+
def policy(self) -> UwForeignPolicyEnum:
44+
from .world import uw_world
45+
return uw_world.policy(self.Owner.force) if self.Owner is not None else UwForeignPolicyEnum.Nothing
46+
47+
def own(self) -> bool:
48+
from .world import uw_world
49+
return self.Owner is not None and self.Owner.force == uw_world.my_force_id()
50+
51+
def ally(self) -> bool:
52+
return self.policy() == UwForeignPolicyEnum.Ally
53+
54+
def enemy(self) -> bool:
55+
return self.policy() == UwForeignPolicyEnum.Enemy
56+
57+
def type(self) -> UwPrototypeTypeEnum:
58+
return uw_prototypes.type(self.Proto.proto) if self.Proto is not None else UwPrototypeTypeEnum.Nothing
59+
60+
def proto(self) -> Prototype:
61+
if self.Proto is not None:
62+
return uw_prototypes.get(self.Proto.proto)
63+
else:
64+
raise Exception("entity does not have a Proto")
65+
66+
def unit_upgrades(self) -> UwUnitUpgrades:
67+
from .world import uw_world
68+
return uw_world.unit_upgrades(self.id) if self.type() == UwPrototypeTypeEnum.Unit else _make_empty_UwUnitUpgrades()

python/uwapi/events.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,23 @@
1+
from dataclasses import field
12
from typing import Callable, List
23
from .interop import *
34

45
class Events:
56
_instance = None
7+
_connection_state_listeners: List[Callable[[UwConnectionStateEnum], None]] = []
8+
_game_state_listeners: List[Callable[[UwGameStateEnum], None]] = []
9+
_update_listeners: List[Callable[[int, bool], None]] = []
10+
_shooting_listeners: List[Callable[[UwShootingArray], None]] = []
11+
_explosions_listeners: List[Callable[[UwExplosionsArray], None]] = []
12+
_force_eliminated_listeners: List[Callable[[int], None]] = []
13+
_chat_listeners: List[Callable[[str, int, UwChatTargetFlags], None]] = []
14+
_map_state_listeners: List[Callable[[UwMapStateEnum], None]] = []
615

716
def __new__(cls):
817
if cls._instance is None:
918
cls._instance = super().__new__(cls)
1019
return cls._instance
1120

12-
def __init__(self):
13-
self._connection_state_listeners: List[Callable[[UwConnectionStateEnum], None]] = []
14-
self._game_state_listeners: List[Callable[[UwGameStateEnum], None]] = []
15-
self._update_listeners: List[Callable[[int, bool], None]] = []
16-
self._shooting_listeners: List[Callable[[UwShootingArray], None]] = []
17-
self._explosions_listeners: List[Callable[[UwExplosionsArray], None]] = []
18-
self._force_eliminated_listeners: List[Callable[[int], None]] = []
19-
self._chat_listeners: List[Callable[[str, int, UwChatTargetFlags], None]] = []
20-
self._map_state_listeners: List[Callable[[UwMapStateEnum], None]] = []
21-
2221
def initialize(self) -> None:
2322
uw_interop.uwSetExceptionCallback(self._exception_callback)
2423
# uw_interop.uwSetLogCallback(self._log_callback)

python/uwapi/game.py

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,14 @@ def __new__(cls):
88
cls._instance = super().__new__(cls)
99
return cls._instance
1010

11-
def log_info(self, message: str) -> None:
12-
uw_interop.uwLog(UwSeverityEnum.Info, message)
11+
def log_info(self, msg: str):
12+
uw_interop.uwLog(UwSeverityEnum.Info, msg)
1313

14-
def try_reconnect(self) -> bool:
15-
return uw_interop.uwTryReconnect()
16-
17-
def set_connect_start_gui(self, enabled: bool, extra_cmd_params: str = "") -> None:
18-
return uw_interop.uwSetConnectStartGui(enabled, extra_cmd_params)
19-
20-
def connect_environment(self) -> bool:
21-
return uw_interop.uwConnectEnvironment()
14+
def log_warning(self, msg: str):
15+
uw_interop.uwLog(UwSeverityEnum.Warning, msg)
2216

23-
def connect_new_server(self, visibility: int = 0, name: str = "", extra_cmd_params: str = "") -> None:
24-
uw_interop.uwConnectNewServer(visibility, name, extra_cmd_params)
25-
26-
def game_state(self) -> GameState:
27-
return uw_interop.uwGameState()
17+
def log_error(self, msg: str):
18+
uw_interop.uwLog(UwSeverityEnum.Error, msg)
2819

2920
def set_player_name(self, name: str) -> None:
3021
uw_interop.uwSetPlayerName(name)
@@ -35,4 +26,55 @@ def player_join_force(self, force_id: int) -> None:
3526
def set_force_color(self, r: float, g: float, b: float) -> None:
3627
uw_interop.uwSetForceColor(r, g, b)
3728

29+
def set_force_race(self, race_proto: int) -> None:
30+
uw_interop.uwSetForceRace(race_proto)
31+
32+
def force_join_team(self, team: int) -> None:
33+
uw_interop.uwForceJoinTeam(team)
34+
35+
def set_connect_start_gui(self, start_gui: bool, extra_params: str = "--observer 1") -> None:
36+
uw_interop.uwSetConnectStartGui(start_gui, extra_params)
37+
38+
def connect_find_lan(self, timeout_microseconds: int = 1000000) -> bool:
39+
return uw_interop.uwConnectFindLan(timeout_microseconds)
40+
41+
def connect_direct(self, address: str, port: int) -> None:
42+
uw_interop.uwConnectDirect(address, port)
43+
44+
def connect_lobby_id(self, lobby_id: int) -> None:
45+
uw_interop.uwConnectLobbyId(lobby_id)
46+
47+
def connect_environment(self) -> bool:
48+
return uw_interop.uwConnectEnvironment()
49+
50+
def connect_new_server(self, visibility: int = 0, name: str = "", extra_params: str = "") -> None:
51+
uw_interop.uwConnectNewServer(visibility, name, extra_params)
52+
53+
def try_reconnect(self) -> bool:
54+
return uw_interop.uwTryReconnect()
55+
56+
def disconnect(self) -> None:
57+
uw_interop.uwDisconnect()
58+
59+
def connection_state(self) -> UwConnectionStateEnum:
60+
return uw_interop.uwConnectionState()
61+
62+
def game_state(self) -> UwGameStateEnum:
63+
return uw_interop.uwGameState()
64+
65+
def map_state(self) -> UwMapStateEnum:
66+
return uw_interop.uwMapState()
67+
68+
def performance_statistics(self) -> UwPerformanceStatistics:
69+
return uw_interop.uwPerformanceStatistics()
70+
71+
def performance_profiling(self, enable: bool) -> None:
72+
uw_interop.uwPerformanceProfiling(enable)
73+
74+
def profiling_event_begin(self) -> int:
75+
return uw_interop.uwProfilingEventBegin()
76+
77+
def profiling_event_end(self, name: str, event_start_time: int) -> None:
78+
uw_interop.uwProfilingEventEnd(name, event_start_time)
79+
3880
uw_game = Game()

0 commit comments

Comments
 (0)