gymcraft 1.2.0__tar.gz
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.
- gymcraft-1.2.0/PKG-INFO +167 -0
- gymcraft-1.2.0/README.md +154 -0
- gymcraft-1.2.0/pyproject.toml +67 -0
- gymcraft-1.2.0/setup.cfg +4 -0
- gymcraft-1.2.0/src/gymcraft/__init__.py +12 -0
- gymcraft-1.2.0/src/gymcraft/client.py +159 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/action_pb2.py +38 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/action_pb2.pyi +15 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/action_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/attack_once_pb2.py +37 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/attack_once_pb2.pyi +11 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/attack_once_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/break_block_pb2.py +37 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/break_block_pb2.pyi +15 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/break_block_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/click_menu_button_pb2.py +37 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/click_menu_button_pb2.pyi +13 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/click_menu_button_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/close_menu_pb2.py +37 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/close_menu_pb2.pyi +11 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/close_menu_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/drop_item_pb2.py +37 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/drop_item_pb2.pyi +13 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/drop_item_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/jump_pb2.py +37 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/jump_pb2.pyi +9 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/jump_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/look_at_pb2.py +43 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/look_at_pb2.pyi +38 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/look_at_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/move_menu_item_pb2.py +39 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/move_menu_item_pb2.pyi +27 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/move_menu_item_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/move_to_pb2.py +37 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/move_to_pb2.pyi +17 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/move_to_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/noop_pb2.py +37 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/noop_pb2.pyi +9 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/noop_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/open_menu_pb2.py +43 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/open_menu_pb2.pyi +36 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/open_menu_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/pick_up_item_pb2.py +37 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/pick_up_item_pb2.pyi +11 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/pick_up_item_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/send_chat_pb2.py +37 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/send_chat_pb2.pyi +11 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/send_chat_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/set_attack_target_pb2.py +37 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/set_attack_target_pb2.pyi +13 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/set_attack_target_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/set_block_pb2.py +37 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/set_block_pb2.pyi +17 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/set_block_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/step_move_pb2.py +37 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/step_move_pb2.pyi +17 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/step_move_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/update_interesting_blocks_pb2.py +37 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/update_interesting_blocks_pb2.pyi +15 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/update_interesting_blocks_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/use_item_pb2.py +41 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/use_item_pb2.pyi +32 -0
- gymcraft-1.2.0/src/gymcraft/gym/action/components/use_item_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/common/block_view_pb2.py +37 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/common/block_view_pb2.pyi +19 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/common/block_view_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/common/entity_view_pb2.py +37 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/common/entity_view_pb2.pyi +37 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/common/entity_view_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/common/item_entity_view_pb2.py +38 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/common/item_entity_view_pb2.pyi +25 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/common/item_entity_view_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/common/item_stack_view_pb2.py +37 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/common/item_stack_view_pb2.pyi +15 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/common/item_stack_view_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/common/slot_pb2.py +38 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/common/slot_pb2.pyi +21 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/common/slot_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/chat_pb2.py +39 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/chat_pb2.pyi +23 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/chat_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/interesting_blocks_pb2.py +38 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/interesting_blocks_pb2.pyi +14 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/interesting_blocks_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/menu_pb2.py +42 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/menu_pb2.pyi +46 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/menu_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/nearby_blocks_pb2.py +38 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/nearby_blocks_pb2.pyi +14 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/nearby_blocks_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/nearby_entities_pb2.py +38 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/nearby_entities_pb2.pyi +14 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/nearby_entities_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/nearby_items_pb2.py +38 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/nearby_items_pb2.pyi +14 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/nearby_items_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/self_pb2.py +37 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/self_pb2.pyi +49 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/self_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/world_pb2.py +39 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/world_pb2.pyi +39 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/components/world_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/observation_pb2.py +44 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/observation_pb2.pyi +37 -0
- gymcraft-1.2.0/src/gymcraft/gym/observation/observation_pb2_grpc.py +24 -0
- gymcraft-1.2.0/src/gymcraft/gym/rpc/env_service_pb2.py +55 -0
- gymcraft-1.2.0/src/gymcraft/gym/rpc/env_service_pb2.pyi +83 -0
- gymcraft-1.2.0/src/gymcraft/gym/rpc/env_service_pb2_grpc.py +226 -0
- gymcraft-1.2.0/src/gymcraft/llm/__init__.py +27 -0
- gymcraft-1.2.0/src/gymcraft/llm/actions.py +647 -0
- gymcraft-1.2.0/src/gymcraft/llm/context.py +92 -0
- gymcraft-1.2.0/src/gymcraft/llm/env.py +187 -0
- gymcraft-1.2.0/src/gymcraft/llm/observations.py +351 -0
- gymcraft-1.2.0/src/gymcraft/llm/types.py +68 -0
- gymcraft-1.2.0/src/gymcraft/type_info.py +109 -0
- gymcraft-1.2.0/src/gymcraft.egg-info/PKG-INFO +167 -0
- gymcraft-1.2.0/src/gymcraft.egg-info/SOURCES.txt +121 -0
- gymcraft-1.2.0/src/gymcraft.egg-info/dependency_links.txt +1 -0
- gymcraft-1.2.0/src/gymcraft.egg-info/requires.txt +6 -0
- gymcraft-1.2.0/src/gymcraft.egg-info/top_level.txt +1 -0
- gymcraft-1.2.0/tests/test_interesting_blocks.py +49 -0
- gymcraft-1.2.0/tests/test_llm_tools.py +566 -0
- gymcraft-1.2.0/tests/test_use_item.py +56 -0
gymcraft-1.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gymcraft
|
|
3
|
+
Version: 1.2.0
|
|
4
|
+
Summary: Python RPC client for GymCraft - Gymnasium-style RL environments in Minecraft
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: grpcio>=1.81.1
|
|
8
|
+
Requires-Dist: gymnasium>=1.3.0
|
|
9
|
+
Requires-Dist: mcrcon>=0.7.0
|
|
10
|
+
Requires-Dist: mypy>=2.1.0
|
|
11
|
+
Requires-Dist: openai>=3.3.1
|
|
12
|
+
Requires-Dist: protobuf>=6.33.6
|
|
13
|
+
|
|
14
|
+
# GymCraft Python RPC Client
|
|
15
|
+
|
|
16
|
+
Install dependencies:
|
|
17
|
+
|
|
18
|
+
```powershell
|
|
19
|
+
cd src\main\python
|
|
20
|
+
uv sync
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Generate Python gRPC stubs from the mod proto files, then build the wheel:
|
|
24
|
+
|
|
25
|
+
```powershell
|
|
26
|
+
# from repository root
|
|
27
|
+
.\gradlew generatePythonStubs
|
|
28
|
+
.\gradlew packagePython
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Or build directly with uv:
|
|
32
|
+
|
|
33
|
+
```powershell
|
|
34
|
+
cd src\main\python
|
|
35
|
+
uv build
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Create an environment in-game with the env tool, then connect by entity UUID:
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from gymcraft import GymCraftEnv
|
|
42
|
+
from gymcraft.gym.action.components import noop_pb2
|
|
43
|
+
|
|
44
|
+
env = GymCraftEnv("entity-uuid-here")
|
|
45
|
+
obs, reset_info = env.reset(options={
|
|
46
|
+
"disable_vanilla_ai": True,
|
|
47
|
+
"allow_multiple_actions": True,
|
|
48
|
+
}) # Disable vanilla AI only while waiting between actions; defaults to False.
|
|
49
|
+
self_state = obs["gymcraft:self"]
|
|
50
|
+
|
|
51
|
+
obs, reward, terminated, truncated, step_info = env.step({
|
|
52
|
+
"timeout_seconds": 0.0, # seconds; <= 0 means no limit
|
|
53
|
+
"actions": [
|
|
54
|
+
{"component_id": "gymcraft:noop", "payload": noop_pb2.ProtoNoop()},
|
|
55
|
+
],
|
|
56
|
+
})
|
|
57
|
+
env.close()
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
`reset()` returns `(observation, info)` and `step()` returns `(observation, reward, terminated, truncated, info)` (Gymnasium-style). The observation is the unpacked `Observation` dict: a `header` plus component keys that are full registration ids such as `gymcraft:self`, `gymcraft:nearby_blocks`, `gymcraft:menu`. A step receives an ordered `ActionBatch`; each action has exactly one `component_id` and protobuf `payload`, and the server executes the list serially under one shared `timeout_seconds`. `make_action()` packs one action into `ProtoMcAction`, while `unpack_observation()` converts a raw `ProtoMcObservation` back to an `Observation`.
|
|
61
|
+
|
|
62
|
+
`allow_multiple_actions` 默认为 `True`。在 reset options 中设为 `False` 后,每个 step 最多接受一个 action;多 action 批次会整体失败且不产生动作副作用,空批次 noop 仍可使用。
|
|
63
|
+
|
|
64
|
+
`gymcraft:update_interesting_blocks` 可通过 `add_block_ids` / `remove_block_ids` 批量维护当前 Agent 关注的方块类型;`gymcraft:interesting_blocks` 返回附近匹配类型的可见 `ProtoBlockView`。
|
|
65
|
+
|
|
66
|
+
Typecheck the Python client:
|
|
67
|
+
|
|
68
|
+
```powershell
|
|
69
|
+
cd src\main\python
|
|
70
|
+
uv run mypy src debug demos tests
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
GitHub Actions runs stub generation, mypy, packaging, and uploads the built distributions as the `gymcraft-python-dist` artifact.
|
|
74
|
+
|
|
75
|
+
## LLM Agent 工具包
|
|
76
|
+
|
|
77
|
+
`gymcraft.llm` 将 LLM 相关能力拆成可独立复用的组件:
|
|
78
|
+
|
|
79
|
+
- `ObservationTextFormatter`:将 protobuf 观测转换为紧凑、稳定的行式文本;
|
|
80
|
+
- `ActionDslParser` / `encode_action_batch`:解析模型回复中的命令 DSL,并编码为现有 `Action`;
|
|
81
|
+
- `ConversationHistory` / `ContextAssembler`:组装通用 Chat Completions 消息;
|
|
82
|
+
- `LLMGymCraftEnv`:只负责串联上述组件与底层 `GymCraftEnv`,所有组件都可替换或单独使用。
|
|
83
|
+
|
|
84
|
+
内置 system prompt、命令说明和动作纠错反馈均使用英文。观测只渲染决策所需的原生字段,不生成相对坐标等派生状态;附近实体、普通方块和感兴趣方块默认各最多 10 条。`action-result` 不包含服务端 `details`。
|
|
85
|
+
`ConversationHistory` 按 `history_turns` 分批保留完整历史;当前批次满载后,下一轮会折叠整批历史并作为新批次的第一轮重新积累,不再逐轮滚动淘汰最旧上下文。
|
|
86
|
+
|
|
87
|
+
最小 wrapper 示例:
|
|
88
|
+
|
|
89
|
+
````python
|
|
90
|
+
from gymcraft import GymCraftEnv
|
|
91
|
+
from gymcraft.llm import LLMGymCraftEnv
|
|
92
|
+
|
|
93
|
+
base_env = GymCraftEnv("entity-uuid-here")
|
|
94
|
+
env = LLMGymCraftEnv(base_env, task="走到最近的箱子旁并打开它。")
|
|
95
|
+
context, info = env.reset(options={"disable_vanilla_ai": True})
|
|
96
|
+
|
|
97
|
+
# context["messages"] 可直接交给任意 Chat Completions 兼容 API。
|
|
98
|
+
model_text = """我先靠近箱子。
|
|
99
|
+
|
|
100
|
+
```gymcraft-action
|
|
101
|
+
/timeout 10
|
|
102
|
+
/move_to 12 64 -3 1
|
|
103
|
+
```
|
|
104
|
+
"""
|
|
105
|
+
context, reward, terminated, truncated, info = env.step(model_text)
|
|
106
|
+
env.close()
|
|
107
|
+
````
|
|
108
|
+
|
|
109
|
+
动作块位于回复末尾,每个非空行是一条 Minecraft 风格命令。一个动作块可以包含多个动作,服务端严格按文本行顺序串行执行,并允许重复同一组件。多条 `move_menu_item` 会保留为一个组件原生批量负载。调用 `ActionDslParser.command_reference()` 可以取得当前环境支持的完整命令表。
|
|
110
|
+
|
|
111
|
+
LLM 可用一条原子命令同时增删兴趣类型,例如 `/update_interesting_blocks add minecraft:diamond_ore mod:target_block remove minecraft:stone`。匹配结果会在后续观测的 `interesting_blocks` 段中按距离排序;其文本裁剪上限由 `ObservationFormatConfig.max_interesting_blocks` 控制。
|
|
112
|
+
|
|
113
|
+
连接已创建的 `simple_mob` 环境进行真实 DSL/gRPC 调试:
|
|
114
|
+
|
|
115
|
+
```powershell
|
|
116
|
+
uv run python debug/interesting_blocks_debug.py <entity_uuid> --add minecraft:diamond_ore
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
格式错误不会推进游戏状态。wrapper 会把错误和模型原文加入上下文,默认允许两次原地纠正,连续第三次非法输出会截断当前 rollout。服务端返回的 reward、terminated 和 truncated 不会被 Python 任务逻辑改写。
|
|
120
|
+
|
|
121
|
+
## Chat Completions 闭环 Demo
|
|
122
|
+
|
|
123
|
+
Chat Completions 客户端是可选依赖:
|
|
124
|
+
|
|
125
|
+
```powershell
|
|
126
|
+
uv sync --extra openai
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
运行 demo;`base_url`、API key 和模型均可替换为任意兼容服务提供的值:
|
|
130
|
+
|
|
131
|
+
```powershell
|
|
132
|
+
$env:LLM_BASE_URL = "https://api.openai.com/v1"
|
|
133
|
+
$env:LLM_API_KEY = "your-api-key"
|
|
134
|
+
$env:LLM_MODEL = "your-model-id"
|
|
135
|
+
|
|
136
|
+
uv run --extra openai demos/llm_chat_completions_demo.py `
|
|
137
|
+
<entity_uuid> `
|
|
138
|
+
--task "找到最近的箱子并查看其中的物品"
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
demo 使用通用的 `client.chat.completions.create(model=..., messages=...)` 接口,不启用 Responses API、厂商工具调用或服务端会话存储。
|
|
142
|
+
|
|
143
|
+
连接 `gymcraft:iron_mining` 环境可运行完整生存工具链 demo:
|
|
144
|
+
|
|
145
|
+
```powershell
|
|
146
|
+
uv run --extra openai demos/iron_mining_llm_demo.py `
|
|
147
|
+
<entity_uuid> `
|
|
148
|
+
--max-steps 64 `
|
|
149
|
+
--trace traces/iron-mining.jsonl
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
该 demo 内置从空手采集原木、使用 self 菜单 $2\times2$ 合成、放置工作台、制作石镐并拾取粗铁的任务提示。`--task` 可覆盖提示,`--trace` 可保存完整 JSONL 轨迹。
|
|
153
|
+
|
|
154
|
+
## 人工终端交互
|
|
155
|
+
|
|
156
|
+
```powershell
|
|
157
|
+
uv run debug/llm_terminal.py <entity_uuid> --task "测试菜单和移动动作"
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
终端中可直接输入一条或多条 `/command`,空行提交;工具会自动补上 `gymcraft-action` 围栏。输入 `:obs` 查看最新观测、`:context` 查看实际消息历史、`:quit` 退出。
|
|
161
|
+
|
|
162
|
+
## 检查
|
|
163
|
+
|
|
164
|
+
```powershell
|
|
165
|
+
uv run python -m unittest discover -s tests -v
|
|
166
|
+
uv run mypy src debug demos tests
|
|
167
|
+
```
|
gymcraft-1.2.0/README.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# GymCraft Python RPC Client
|
|
2
|
+
|
|
3
|
+
Install dependencies:
|
|
4
|
+
|
|
5
|
+
```powershell
|
|
6
|
+
cd src\main\python
|
|
7
|
+
uv sync
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Generate Python gRPC stubs from the mod proto files, then build the wheel:
|
|
11
|
+
|
|
12
|
+
```powershell
|
|
13
|
+
# from repository root
|
|
14
|
+
.\gradlew generatePythonStubs
|
|
15
|
+
.\gradlew packagePython
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Or build directly with uv:
|
|
19
|
+
|
|
20
|
+
```powershell
|
|
21
|
+
cd src\main\python
|
|
22
|
+
uv build
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Create an environment in-game with the env tool, then connect by entity UUID:
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from gymcraft import GymCraftEnv
|
|
29
|
+
from gymcraft.gym.action.components import noop_pb2
|
|
30
|
+
|
|
31
|
+
env = GymCraftEnv("entity-uuid-here")
|
|
32
|
+
obs, reset_info = env.reset(options={
|
|
33
|
+
"disable_vanilla_ai": True,
|
|
34
|
+
"allow_multiple_actions": True,
|
|
35
|
+
}) # Disable vanilla AI only while waiting between actions; defaults to False.
|
|
36
|
+
self_state = obs["gymcraft:self"]
|
|
37
|
+
|
|
38
|
+
obs, reward, terminated, truncated, step_info = env.step({
|
|
39
|
+
"timeout_seconds": 0.0, # seconds; <= 0 means no limit
|
|
40
|
+
"actions": [
|
|
41
|
+
{"component_id": "gymcraft:noop", "payload": noop_pb2.ProtoNoop()},
|
|
42
|
+
],
|
|
43
|
+
})
|
|
44
|
+
env.close()
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`reset()` returns `(observation, info)` and `step()` returns `(observation, reward, terminated, truncated, info)` (Gymnasium-style). The observation is the unpacked `Observation` dict: a `header` plus component keys that are full registration ids such as `gymcraft:self`, `gymcraft:nearby_blocks`, `gymcraft:menu`. A step receives an ordered `ActionBatch`; each action has exactly one `component_id` and protobuf `payload`, and the server executes the list serially under one shared `timeout_seconds`. `make_action()` packs one action into `ProtoMcAction`, while `unpack_observation()` converts a raw `ProtoMcObservation` back to an `Observation`.
|
|
48
|
+
|
|
49
|
+
`allow_multiple_actions` 默认为 `True`。在 reset options 中设为 `False` 后,每个 step 最多接受一个 action;多 action 批次会整体失败且不产生动作副作用,空批次 noop 仍可使用。
|
|
50
|
+
|
|
51
|
+
`gymcraft:update_interesting_blocks` 可通过 `add_block_ids` / `remove_block_ids` 批量维护当前 Agent 关注的方块类型;`gymcraft:interesting_blocks` 返回附近匹配类型的可见 `ProtoBlockView`。
|
|
52
|
+
|
|
53
|
+
Typecheck the Python client:
|
|
54
|
+
|
|
55
|
+
```powershell
|
|
56
|
+
cd src\main\python
|
|
57
|
+
uv run mypy src debug demos tests
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
GitHub Actions runs stub generation, mypy, packaging, and uploads the built distributions as the `gymcraft-python-dist` artifact.
|
|
61
|
+
|
|
62
|
+
## LLM Agent 工具包
|
|
63
|
+
|
|
64
|
+
`gymcraft.llm` 将 LLM 相关能力拆成可独立复用的组件:
|
|
65
|
+
|
|
66
|
+
- `ObservationTextFormatter`:将 protobuf 观测转换为紧凑、稳定的行式文本;
|
|
67
|
+
- `ActionDslParser` / `encode_action_batch`:解析模型回复中的命令 DSL,并编码为现有 `Action`;
|
|
68
|
+
- `ConversationHistory` / `ContextAssembler`:组装通用 Chat Completions 消息;
|
|
69
|
+
- `LLMGymCraftEnv`:只负责串联上述组件与底层 `GymCraftEnv`,所有组件都可替换或单独使用。
|
|
70
|
+
|
|
71
|
+
内置 system prompt、命令说明和动作纠错反馈均使用英文。观测只渲染决策所需的原生字段,不生成相对坐标等派生状态;附近实体、普通方块和感兴趣方块默认各最多 10 条。`action-result` 不包含服务端 `details`。
|
|
72
|
+
`ConversationHistory` 按 `history_turns` 分批保留完整历史;当前批次满载后,下一轮会折叠整批历史并作为新批次的第一轮重新积累,不再逐轮滚动淘汰最旧上下文。
|
|
73
|
+
|
|
74
|
+
最小 wrapper 示例:
|
|
75
|
+
|
|
76
|
+
````python
|
|
77
|
+
from gymcraft import GymCraftEnv
|
|
78
|
+
from gymcraft.llm import LLMGymCraftEnv
|
|
79
|
+
|
|
80
|
+
base_env = GymCraftEnv("entity-uuid-here")
|
|
81
|
+
env = LLMGymCraftEnv(base_env, task="走到最近的箱子旁并打开它。")
|
|
82
|
+
context, info = env.reset(options={"disable_vanilla_ai": True})
|
|
83
|
+
|
|
84
|
+
# context["messages"] 可直接交给任意 Chat Completions 兼容 API。
|
|
85
|
+
model_text = """我先靠近箱子。
|
|
86
|
+
|
|
87
|
+
```gymcraft-action
|
|
88
|
+
/timeout 10
|
|
89
|
+
/move_to 12 64 -3 1
|
|
90
|
+
```
|
|
91
|
+
"""
|
|
92
|
+
context, reward, terminated, truncated, info = env.step(model_text)
|
|
93
|
+
env.close()
|
|
94
|
+
````
|
|
95
|
+
|
|
96
|
+
动作块位于回复末尾,每个非空行是一条 Minecraft 风格命令。一个动作块可以包含多个动作,服务端严格按文本行顺序串行执行,并允许重复同一组件。多条 `move_menu_item` 会保留为一个组件原生批量负载。调用 `ActionDslParser.command_reference()` 可以取得当前环境支持的完整命令表。
|
|
97
|
+
|
|
98
|
+
LLM 可用一条原子命令同时增删兴趣类型,例如 `/update_interesting_blocks add minecraft:diamond_ore mod:target_block remove minecraft:stone`。匹配结果会在后续观测的 `interesting_blocks` 段中按距离排序;其文本裁剪上限由 `ObservationFormatConfig.max_interesting_blocks` 控制。
|
|
99
|
+
|
|
100
|
+
连接已创建的 `simple_mob` 环境进行真实 DSL/gRPC 调试:
|
|
101
|
+
|
|
102
|
+
```powershell
|
|
103
|
+
uv run python debug/interesting_blocks_debug.py <entity_uuid> --add minecraft:diamond_ore
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
格式错误不会推进游戏状态。wrapper 会把错误和模型原文加入上下文,默认允许两次原地纠正,连续第三次非法输出会截断当前 rollout。服务端返回的 reward、terminated 和 truncated 不会被 Python 任务逻辑改写。
|
|
107
|
+
|
|
108
|
+
## Chat Completions 闭环 Demo
|
|
109
|
+
|
|
110
|
+
Chat Completions 客户端是可选依赖:
|
|
111
|
+
|
|
112
|
+
```powershell
|
|
113
|
+
uv sync --extra openai
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
运行 demo;`base_url`、API key 和模型均可替换为任意兼容服务提供的值:
|
|
117
|
+
|
|
118
|
+
```powershell
|
|
119
|
+
$env:LLM_BASE_URL = "https://api.openai.com/v1"
|
|
120
|
+
$env:LLM_API_KEY = "your-api-key"
|
|
121
|
+
$env:LLM_MODEL = "your-model-id"
|
|
122
|
+
|
|
123
|
+
uv run --extra openai demos/llm_chat_completions_demo.py `
|
|
124
|
+
<entity_uuid> `
|
|
125
|
+
--task "找到最近的箱子并查看其中的物品"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
demo 使用通用的 `client.chat.completions.create(model=..., messages=...)` 接口,不启用 Responses API、厂商工具调用或服务端会话存储。
|
|
129
|
+
|
|
130
|
+
连接 `gymcraft:iron_mining` 环境可运行完整生存工具链 demo:
|
|
131
|
+
|
|
132
|
+
```powershell
|
|
133
|
+
uv run --extra openai demos/iron_mining_llm_demo.py `
|
|
134
|
+
<entity_uuid> `
|
|
135
|
+
--max-steps 64 `
|
|
136
|
+
--trace traces/iron-mining.jsonl
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
该 demo 内置从空手采集原木、使用 self 菜单 $2\times2$ 合成、放置工作台、制作石镐并拾取粗铁的任务提示。`--task` 可覆盖提示,`--trace` 可保存完整 JSONL 轨迹。
|
|
140
|
+
|
|
141
|
+
## 人工终端交互
|
|
142
|
+
|
|
143
|
+
```powershell
|
|
144
|
+
uv run debug/llm_terminal.py <entity_uuid> --task "测试菜单和移动动作"
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
终端中可直接输入一条或多条 `/command`,空行提交;工具会自动补上 `gymcraft-action` 围栏。输入 `:obs` 查看最新观测、`:context` 查看实际消息历史、`:quit` 退出。
|
|
148
|
+
|
|
149
|
+
## 检查
|
|
150
|
+
|
|
151
|
+
```powershell
|
|
152
|
+
uv run python -m unittest discover -s tests -v
|
|
153
|
+
uv run mypy src debug demos tests
|
|
154
|
+
```
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=75", "grpcio-tools>=1.81.1"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "gymcraft"
|
|
7
|
+
version = "1.2.0" # 这里和模组版本号保持一致
|
|
8
|
+
description = "Python RPC client for GymCraft - Gymnasium-style RL environments in Minecraft"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"grpcio>=1.81.1",
|
|
13
|
+
"gymnasium>=1.3.0",
|
|
14
|
+
"mcrcon>=0.7.0",
|
|
15
|
+
"mypy>=2.1.0",
|
|
16
|
+
"openai>=3.3.1",
|
|
17
|
+
"protobuf>=6.33.6",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[dependency-groups]
|
|
21
|
+
dev = [
|
|
22
|
+
"grpcio-tools>=1.81.1",
|
|
23
|
+
"mcp>=2.1.1",
|
|
24
|
+
"openai>=2.0.0",
|
|
25
|
+
"python-dotenv>=1.2.3",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[tool.setuptools.packages.find]
|
|
29
|
+
where = ["src"]
|
|
30
|
+
include = ["gymcraft", "gymcraft.*"]
|
|
31
|
+
|
|
32
|
+
[tool.mypy]
|
|
33
|
+
python_version = "3.11"
|
|
34
|
+
files = ["src/gymcraft", "debug"]
|
|
35
|
+
exclude = ["src/gymcraft/gym/"]
|
|
36
|
+
mypy_path = "src"
|
|
37
|
+
|
|
38
|
+
warn_return_any = true
|
|
39
|
+
warn_unused_configs = true
|
|
40
|
+
warn_unused_ignores = true
|
|
41
|
+
warn_redundant_casts = true
|
|
42
|
+
warn_unreachable = true
|
|
43
|
+
|
|
44
|
+
disallow_untyped_defs = true
|
|
45
|
+
disallow_incomplete_defs = true
|
|
46
|
+
check_untyped_defs = true
|
|
47
|
+
disallow_untyped_decorators = true
|
|
48
|
+
|
|
49
|
+
no_implicit_optional = true
|
|
50
|
+
strict_equality = true
|
|
51
|
+
show_error_codes = true
|
|
52
|
+
pretty = true
|
|
53
|
+
|
|
54
|
+
[[tool.mypy.overrides]]
|
|
55
|
+
module = [
|
|
56
|
+
"gymcraft.gym.*",
|
|
57
|
+
]
|
|
58
|
+
follow_imports = "skip"
|
|
59
|
+
ignore_errors = true
|
|
60
|
+
|
|
61
|
+
[[tool.mypy.overrides]]
|
|
62
|
+
module = [
|
|
63
|
+
"grpc.*",
|
|
64
|
+
"gymnasium.*",
|
|
65
|
+
"google.*",
|
|
66
|
+
]
|
|
67
|
+
ignore_missing_imports = true
|
gymcraft-1.2.0/setup.cfg
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from gymcraft.client import GymCraftEnv, make_action, make_step_request, single_action, unpack_observation
|
|
2
|
+
from gymcraft.llm import LLMEnvConfig, LLMGymCraftEnv
|
|
3
|
+
|
|
4
|
+
__all__ = [
|
|
5
|
+
"GymCraftEnv",
|
|
6
|
+
"LLMEnvConfig",
|
|
7
|
+
"LLMGymCraftEnv",
|
|
8
|
+
"make_action",
|
|
9
|
+
"make_step_request",
|
|
10
|
+
"single_action",
|
|
11
|
+
"unpack_observation",
|
|
12
|
+
]
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from collections.abc import Mapping
|
|
5
|
+
from typing import Any, Tuple, TypeVar, cast
|
|
6
|
+
|
|
7
|
+
import grpc
|
|
8
|
+
import gymnasium as gym
|
|
9
|
+
from google.protobuf import message
|
|
10
|
+
|
|
11
|
+
from gymcraft.gym.action.action_pb2 import ProtoMcAction
|
|
12
|
+
from gymcraft.gym.observation.components.chat_pb2 import ProtoRecentChat
|
|
13
|
+
from gymcraft.gym.observation.components.menu_pb2 import ProtoMenuObservation
|
|
14
|
+
from gymcraft.gym.observation.components.interesting_blocks_pb2 import ProtoInterestingBlocks
|
|
15
|
+
from gymcraft.gym.observation.components.nearby_blocks_pb2 import ProtoNearbyBlocks
|
|
16
|
+
from gymcraft.gym.observation.components.nearby_entities_pb2 import ProtoNearbyEntities
|
|
17
|
+
from gymcraft.gym.observation.components.nearby_items_pb2 import ProtoNearbyItems
|
|
18
|
+
from gymcraft.gym.observation.components.self_pb2 import ProtoSelfState
|
|
19
|
+
from gymcraft.gym.observation.components.world_pb2 import ProtoWorldState
|
|
20
|
+
from gymcraft.gym.observation.observation_pb2 import ProtoMcObservation
|
|
21
|
+
from gymcraft.gym.rpc.env_service_pb2 import (
|
|
22
|
+
CloseSessionRequest,
|
|
23
|
+
ConnectRequest,
|
|
24
|
+
ResetRequest,
|
|
25
|
+
ResetResponse,
|
|
26
|
+
StepRequest,
|
|
27
|
+
StepResponse,
|
|
28
|
+
)
|
|
29
|
+
from gymcraft.gym.rpc.env_service_pb2_grpc import GymEnvServiceStub
|
|
30
|
+
from gymcraft.type_info import (
|
|
31
|
+
Action,
|
|
32
|
+
ActionBatch,
|
|
33
|
+
Observation,
|
|
34
|
+
OBS_INTERESTING_BLOCKS,
|
|
35
|
+
OBS_MENU,
|
|
36
|
+
OBS_NEARBY_BLOCKS,
|
|
37
|
+
OBS_NEARBY_ENTITIES,
|
|
38
|
+
OBS_NEARBY_ITEMS,
|
|
39
|
+
OBS_CHAT,
|
|
40
|
+
OBS_SELF,
|
|
41
|
+
OBS_WORLD,
|
|
42
|
+
TIMEOUT_SECONDS,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
_TMessage = TypeVar("_TMessage", bound=message.Message)
|
|
46
|
+
|
|
47
|
+
# 观测组件注册 id(完整 wire 键,含 `gymcraft:` 命名空间)→ 解包目标 protobuf 消息类型。
|
|
48
|
+
# 新增观测组件时需在此登记,否则 `unpack_observation` 会将其视为未知组件。
|
|
49
|
+
_OBSERVATION_COMPONENT_TYPES: dict[str, type[message.Message]] = {
|
|
50
|
+
OBS_SELF: ProtoSelfState,
|
|
51
|
+
OBS_WORLD: ProtoWorldState,
|
|
52
|
+
OBS_NEARBY_ENTITIES: ProtoNearbyEntities,
|
|
53
|
+
OBS_NEARBY_BLOCKS: ProtoNearbyBlocks,
|
|
54
|
+
OBS_MENU: ProtoMenuObservation,
|
|
55
|
+
OBS_NEARBY_ITEMS: ProtoNearbyItems,
|
|
56
|
+
OBS_INTERESTING_BLOCKS: ProtoInterestingBlocks,
|
|
57
|
+
OBS_CHAT: ProtoRecentChat,
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class GymCraftEnv(gym.Env[Any, Any]):
|
|
62
|
+
metadata = {"render_modes": []}
|
|
63
|
+
|
|
64
|
+
def __init__(self, entity_uuid: str, address: str = "localhost:50051") -> None:
|
|
65
|
+
self.entity_uuid = entity_uuid
|
|
66
|
+
self.address = address
|
|
67
|
+
self.channel = grpc.insecure_channel(address)
|
|
68
|
+
self.stub = GymEnvServiceStub(self.channel)
|
|
69
|
+
|
|
70
|
+
response = self.stub.Connect(ConnectRequest(entity_uuid=entity_uuid))
|
|
71
|
+
self.session_id = response.session_id
|
|
72
|
+
self.entity_uuid = response.entity_uuid
|
|
73
|
+
self.remote_metadata = json.loads(response.metadata)
|
|
74
|
+
self.action_space_spec = json.loads(response.action_space_json)
|
|
75
|
+
self.observation_space_spec = json.loads(response.observation_space_json)
|
|
76
|
+
|
|
77
|
+
# gymnasium 约定 info 为 dict,本环境按 proto 直接透传 info 的 JSON 字符串。
|
|
78
|
+
def reset(self, *, seed: int | None = None, options: Mapping[str, Any] | None = None) -> Tuple[Observation, str]: # type: ignore[override] # noqa: E501
|
|
79
|
+
super().reset(seed=seed)
|
|
80
|
+
request = ResetRequest(session_id=self.session_id)
|
|
81
|
+
if seed is not None:
|
|
82
|
+
request.seed = seed
|
|
83
|
+
request.options = json.dumps(options or {})
|
|
84
|
+
|
|
85
|
+
response = self.stub.Reset(request)
|
|
86
|
+
assert isinstance(response, ResetResponse)
|
|
87
|
+
return unpack_observation(response.observation), response.info
|
|
88
|
+
|
|
89
|
+
# gymnasium 约定 info 为 dict,本环境按 proto 直接透传 info 的 JSON 字符串。
|
|
90
|
+
def step(self, action: ActionBatch) -> Tuple[Observation, float, bool, bool, str]: # type: ignore[override] # noqa: E501
|
|
91
|
+
request = make_step_request(self.session_id, action)
|
|
92
|
+
response = self.stub.Step(request)
|
|
93
|
+
assert isinstance(response, StepResponse)
|
|
94
|
+
return (
|
|
95
|
+
unpack_observation(response.observation),
|
|
96
|
+
response.reward,
|
|
97
|
+
response.terminated,
|
|
98
|
+
response.truncated,
|
|
99
|
+
response.info,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
def close(self) -> None:
|
|
103
|
+
session_id = getattr(self, "session_id", None)
|
|
104
|
+
if session_id:
|
|
105
|
+
self.stub.CloseSession(CloseSessionRequest(session_id=session_id))
|
|
106
|
+
self.session_id = ""
|
|
107
|
+
self.channel.close()
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def make_action(action: Action) -> ProtoMcAction:
|
|
111
|
+
"""把单个 ``component_id`` / ``payload`` 动作打包为 wire 消息。"""
|
|
112
|
+
proto_action = ProtoMcAction(component_id=action["component_id"])
|
|
113
|
+
proto_action.payload.Pack(cast(message.Message, action["payload"]))
|
|
114
|
+
return proto_action
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def single_action(component_id: str, payload: message.Message, timeout_seconds: float = 0.0) -> ActionBatch:
|
|
118
|
+
"""构造只包含一项的 step 动作批次。"""
|
|
119
|
+
return {
|
|
120
|
+
"timeout_seconds": timeout_seconds,
|
|
121
|
+
"actions": [{"component_id": component_id, "payload": payload}],
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def make_step_request(session_id: str, batch: ActionBatch) -> StepRequest:
|
|
126
|
+
"""把用户视角的动作批次打包为 gRPC StepRequest。"""
|
|
127
|
+
return StepRequest(
|
|
128
|
+
session_id=session_id,
|
|
129
|
+
actions=[make_action(item) for item in batch["actions"]],
|
|
130
|
+
timeout_seconds=batch.get(TIMEOUT_SECONDS, 0.0),
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _unpack_component(
|
|
135
|
+
raw_observation: ProtoMcObservation,
|
|
136
|
+
key: str,
|
|
137
|
+
message_type: type[_TMessage],
|
|
138
|
+
) -> _TMessage:
|
|
139
|
+
packed = raw_observation.components[key]
|
|
140
|
+
payload = cast(_TMessage, message_type())
|
|
141
|
+
if not packed.Unpack(payload):
|
|
142
|
+
raise ValueError(f"观测组件 {key!r} 无法解包为 {message_type.DESCRIPTOR.full_name}")
|
|
143
|
+
return payload
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def unpack_observation(raw_observation: ProtoMcObservation) -> Observation:
|
|
147
|
+
"""把 wire 上的 ``ProtoMcObservation`` 解包为用户视角的 ``Observation``。
|
|
148
|
+
|
|
149
|
+
``header`` 原样保留;``components`` 中已登记的组件按注册 id 解包为对应的
|
|
150
|
+
protobuf 消息,未登记的键抛 ``ValueError``,避免静默丢失新组件。
|
|
151
|
+
"""
|
|
152
|
+
unknown = set(raw_observation.components) - set(_OBSERVATION_COMPONENT_TYPES)
|
|
153
|
+
if unknown:
|
|
154
|
+
raise ValueError(f"观测包含未识别的组件: {sorted(unknown)}")
|
|
155
|
+
result: dict[str, Any] = {"header": raw_observation.header}
|
|
156
|
+
for key, message_type in _OBSERVATION_COMPONENT_TYPES.items():
|
|
157
|
+
if key in raw_observation.components:
|
|
158
|
+
result[key] = _unpack_component(raw_observation, key, message_type)
|
|
159
|
+
return cast(Observation, result)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# NO CHECKED-IN PROTOBUF GENCODE
|
|
4
|
+
# source: gymcraft/gym/action/action.proto
|
|
5
|
+
# Protobuf Python Version: 6.33.5
|
|
6
|
+
"""Generated protocol buffer code."""
|
|
7
|
+
from google.protobuf import descriptor as _descriptor
|
|
8
|
+
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
9
|
+
from google.protobuf import runtime_version as _runtime_version
|
|
10
|
+
from google.protobuf import symbol_database as _symbol_database
|
|
11
|
+
from google.protobuf.internal import builder as _builder
|
|
12
|
+
_runtime_version.ValidateProtobufRuntimeVersion(
|
|
13
|
+
_runtime_version.Domain.PUBLIC,
|
|
14
|
+
6,
|
|
15
|
+
33,
|
|
16
|
+
5,
|
|
17
|
+
'',
|
|
18
|
+
'gymcraft/gym/action/action.proto'
|
|
19
|
+
)
|
|
20
|
+
# @@protoc_insertion_point(imports)
|
|
21
|
+
|
|
22
|
+
_sym_db = _symbol_database.Default()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n gymcraft/gym/action/action.proto\x12\x13gymcraft.gym.action\x1a\x19google/protobuf/any.proto\"u\n\rProtoMcAction\x12\x14\n\x0c\x63omponent_id\x18\x03 \x01(\t\x12%\n\x07payload\x18\x04 \x01(\x0b\x32\x14.google.protobuf.AnyJ\x04\x08\x01\x10\x02J\x04\x08\x02\x10\x03R\ncomponentsR\x0ftimeout_secondsB>\n-io.github.mousemeya.gymcraft.gym.action.protoB\x0b\x41\x63tionProtoP\x01\x62\x06proto3')
|
|
29
|
+
|
|
30
|
+
_globals = globals()
|
|
31
|
+
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
32
|
+
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'gymcraft.gym.action.action_pb2', _globals)
|
|
33
|
+
if not _descriptor._USE_C_DESCRIPTORS:
|
|
34
|
+
_globals['DESCRIPTOR']._loaded_options = None
|
|
35
|
+
_globals['DESCRIPTOR']._serialized_options = b'\n-io.github.mousemeya.gymcraft.gym.action.protoB\013ActionProtoP\001'
|
|
36
|
+
_globals['_PROTOMCACTION']._serialized_start=84
|
|
37
|
+
_globals['_PROTOMCACTION']._serialized_end=201
|
|
38
|
+
# @@protoc_insertion_point(module_scope)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from google.protobuf import any_pb2 as _any_pb2
|
|
2
|
+
from google.protobuf import descriptor as _descriptor
|
|
3
|
+
from google.protobuf import message as _message
|
|
4
|
+
from collections.abc import Mapping as _Mapping
|
|
5
|
+
from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union
|
|
6
|
+
|
|
7
|
+
DESCRIPTOR: _descriptor.FileDescriptor
|
|
8
|
+
|
|
9
|
+
class ProtoMcAction(_message.Message):
|
|
10
|
+
__slots__ = ("component_id", "payload")
|
|
11
|
+
COMPONENT_ID_FIELD_NUMBER: _ClassVar[int]
|
|
12
|
+
PAYLOAD_FIELD_NUMBER: _ClassVar[int]
|
|
13
|
+
component_id: str
|
|
14
|
+
payload: _any_pb2.Any
|
|
15
|
+
def __init__(self, component_id: _Optional[str] = ..., payload: _Optional[_Union[_any_pb2.Any, _Mapping]] = ...) -> None: ...
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
|
2
|
+
"""Client and server classes corresponding to protobuf-defined services."""
|
|
3
|
+
import grpc
|
|
4
|
+
import warnings
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
GRPC_GENERATED_VERSION = '1.81.1'
|
|
8
|
+
GRPC_VERSION = grpc.__version__
|
|
9
|
+
_version_not_supported = False
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
from grpc._utilities import first_version_is_lower
|
|
13
|
+
_version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
|
|
14
|
+
except ImportError:
|
|
15
|
+
_version_not_supported = True
|
|
16
|
+
|
|
17
|
+
if _version_not_supported:
|
|
18
|
+
raise RuntimeError(
|
|
19
|
+
f'The grpc package installed is at version {GRPC_VERSION},'
|
|
20
|
+
+ ' but the generated code in gymcraft/gym/action/action_pb2_grpc.py depends on'
|
|
21
|
+
+ f' grpcio>={GRPC_GENERATED_VERSION}.'
|
|
22
|
+
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
|
|
23
|
+
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
|
|
24
|
+
)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# NO CHECKED-IN PROTOBUF GENCODE
|
|
4
|
+
# source: gymcraft/gym/action/components/attack_once.proto
|
|
5
|
+
# Protobuf Python Version: 6.33.5
|
|
6
|
+
"""Generated protocol buffer code."""
|
|
7
|
+
from google.protobuf import descriptor as _descriptor
|
|
8
|
+
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
9
|
+
from google.protobuf import runtime_version as _runtime_version
|
|
10
|
+
from google.protobuf import symbol_database as _symbol_database
|
|
11
|
+
from google.protobuf.internal import builder as _builder
|
|
12
|
+
_runtime_version.ValidateProtobufRuntimeVersion(
|
|
13
|
+
_runtime_version.Domain.PUBLIC,
|
|
14
|
+
6,
|
|
15
|
+
33,
|
|
16
|
+
5,
|
|
17
|
+
'',
|
|
18
|
+
'gymcraft/gym/action/components/attack_once.proto'
|
|
19
|
+
)
|
|
20
|
+
# @@protoc_insertion_point(imports)
|
|
21
|
+
|
|
22
|
+
_sym_db = _symbol_database.Default()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n0gymcraft/gym/action/components/attack_once.proto\x12\x13gymcraft.gym.action\"+\n\x0fProtoAttackOnce\x12\x18\n\x10target_entity_id\x18\x01 \x01(\x05\x42\x42\n-io.github.mousemeya.gymcraft.gym.action.protoB\x0f\x41ttackOnceProtoP\x01\x62\x06proto3')
|
|
28
|
+
|
|
29
|
+
_globals = globals()
|
|
30
|
+
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
31
|
+
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'gymcraft.gym.action.components.attack_once_pb2', _globals)
|
|
32
|
+
if not _descriptor._USE_C_DESCRIPTORS:
|
|
33
|
+
_globals['DESCRIPTOR']._loaded_options = None
|
|
34
|
+
_globals['DESCRIPTOR']._serialized_options = b'\n-io.github.mousemeya.gymcraft.gym.action.protoB\017AttackOnceProtoP\001'
|
|
35
|
+
_globals['_PROTOATTACKONCE']._serialized_start=73
|
|
36
|
+
_globals['_PROTOATTACKONCE']._serialized_end=116
|
|
37
|
+
# @@protoc_insertion_point(module_scope)
|