Skip to content

Commit

Permalink
Merge branch 'trueagi-io:main' into br3
Browse files Browse the repository at this point in the history
  • Loading branch information
noskill authored Nov 5, 2024
2 parents 4aee507 + 29ae1f7 commit 25e04f2
Show file tree
Hide file tree
Showing 7 changed files with 261 additions and 12 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
strategy:
matrix:
# Use these Java versions
java: [ 17, ] # Current Java LTS & minimum supported by Minecraft
java: [ 21, ] # Current Java LTS & minimum supported by Minecraft
steps:
- name: lock file
run: lockfile /tmp/minecraft-test-lock
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ venv.bak/
.spyderproject
.spyproject

#VSCode project settings
.vscode

# Rope project settings
.ropeproject

Expand Down
22 changes: 22 additions & 0 deletions examples/8_draw.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from tagilmo.utils.vereya_wrapper import MCConnector
import tagilmo.utils.mission_builder as mb

block = mb.DrawBlock("-1", "-60", "4", "cobblestone")
it = mb.DrawItem(0, -60, 0, "diamond")
cuboid = mb.DrawCuboid("1", -60, "0", 3, -60, 3, "sandstone")
line = mb.DrawLine(5, -60, 3, 9, -55, 8, "diamond_ore")
draw = mb.DrawingDecorator([block, it, cuboid, line])

miss = mb.MissionXML(serverSection=mb.ServerSection(handlers=mb.ServerHandlers(drawingdecorator=draw)))
miss.setWorld(mb.flatworld("",
seed= '5',
forceReset = "true"))
miss.setObservations(mb.Observations())
# we typically don't need this for real Minecraft agents, but this example just checks the connection to Minecraft
miss.setTimeLimit(5000)

mc = MCConnector(miss)
# Note that we need two instances of Minecraft running
mc.safeStart()

mc.stop()
144 changes: 140 additions & 4 deletions tagilmo/utils/mission_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,16 +92,17 @@ def fileworld(uri2save, forceReset="false"):
class ServerHandlers:

def __init__(self, worldgenerator_xml=defaultworld(), alldecorators_xml=None,
bQuitAnyAgent=False, timeLimitsMs_string=None):
bQuitAnyAgent=False, timeLimitsMs_string=None, drawingdecorator = None):
self.worldgenerator = worldgenerator_xml
self.alldecorators = alldecorators_xml
self.bQuitAnyAgent = bQuitAnyAgent
self.timeLimitsMs = timeLimitsMs_string

self.drawingdecorator = drawingdecorator

def xml(self):
_xml = '<ServerHandlers>\n' + self.worldgenerator + '\n'
#if self.drawingdecorator:
# _xml += '<DrawingDecorator>\n' + self.drawingdecorator + '\n</DrawingDecorator>\n'
if self.drawingdecorator:
_xml += '<DrawingDecorator>\n' + self.drawingdecorator.xml() + '</DrawingDecorator>\n'
#<BuildBattleDecorator> --
#<MazeDecorator> --
if self.alldecorators:
Expand All @@ -125,6 +126,141 @@ def xml(self):
return '<ServerSection>\n'+self.initial_conditions.xml()+self.handlers.xml()+'</ServerSection>\n'


class DrawingDecorator:
def __init__(self, decorators = []):
"""
Draw all given Draw objects
Parameters:
decorators (List[Union[DrawBlock, DrawCuboid, DrawItem, DrawLine]]) : a list of objects to be drawn.\nEach object can be one of the following types:
- DrawBlock: represents a block.
- DrawCuboid: represents a cuboid.
- DrawItem: represents an item.
- DrawLine: represents a line between two points.
"""
self.decorators = decorators

def xml(self):
_xml = ""
for decorator in self.decorators:
_xml += decorator.xml()
return _xml


class DrawBlock:
def __init__(self, x, y, z, blockType):
"""
Draw a block in world.
Parameters:
x (int | str): x coordinate.
y (int | str): y coordinate.
z (int | str): z coordinate.
blockType (str): block that will be used.
"""
self.x = x
self.y = y
self.z = z
self.blockType = blockType

def xml(self):
return f'<DrawBlock x="{self.x}" y="{self.y}" z="{self.z}" type="{self.blockType}"/>\n'


class DrawCuboid:
def __init__(self, x1, y1, z1, x2, y2, z2, blockType):
"""
Draw a cuboid in world.
Parameters:
x1 (int | str): x coordinate of the first corner.
y1 (int | str): y coordinate of the first corner.
z1 (int | str): z coordinate of the first corner.
x2 (int | str): x coordinate of the second corner.
y2 (int | str): y coordinate of the second corner.
z2 (int | str): z coordinate of the second corner.
blockType (str): block that will be used.
"""
self.x1 = x1
self.y1 = y1
self.z1 = z1
self.x2 = x2
self.y2 = y2
self.z2 = z2
self.blockType = blockType

def xml(self):
return f'<DrawCuboid x1="{self.x1}" y1="{self.y1}" z1="{self.z1}" x2="{self.x2}" y2="{self.y2}" z2="{self.z2}" type="{self.blockType}"/>\n'


class DrawLine:
def __init__(self, x1, y1, z1, x2, y2, z2, blockType):
"""
Draw a line of blocks in world.
Parameters:
x1 (int | str): x coordinate of the first point.
y1 (int | str): y coordinate of the first point.
z1 (int | str): z coordinate of the first point.
x2 (int | str): x coordinate of the second point.
y2 (int | str): y coordinate of the second point.
z2 (int | str): z coordinate of the second point.
blockType (str): block that will be used.
"""
self.x1 = x1
self.y1 = y1
self.z1 = z1
self.x2 = x2
self.y2 = y2
self.z2 = z2
self.blockType = blockType

def xml(self):
return f'<DrawLine x1="{self.x1}" y1="{self.y1}" z1="{self.z1}" x2="{self.x2}" y2="{self.y2}" z2="{self.z2}" type="{self.blockType}"/>\n'


class DrawItem:
def __init__(self, x, y, z, itemType):
"""
Draw an item in world.
Parameters:
x (int | str): x coordinate.
y (int | str): y coordinate.
z (int | str): z coordinate.
itemType (str): item that will be used.
"""
self.x = x
self.y = y
self.z = z
self.itemType = itemType

def xml(self):
return f'<DrawItem x="{self.x}" y="{self.y}" z="{self.z}" type="{self.itemType}"/>\n'


class DrawSphere:
def __init__(self, x, y, z, radius, blockType):
"""
Draw a block in world.
Parameters:
x (int | str): x coordinate.
y (int | str): y coordinate.
z (int | str): z coordinate.
radius (int | str): radius.
blockType (str): block that will be used.
"""
self.x = x
self.y = y
self.z = z
self.radius = radius
self.blockType = blockType

def xml(self):
return f'<DrawBlock x="{self.x}" y="{self.y}" z="{self.z}" radius="{self.radius}" type="{self.blockType}"/>\n'


class Commands:

def __init__(self, bAll=True, bContinuous=None, bDiscrete=None, bInventory=None,
Expand Down
24 changes: 18 additions & 6 deletions tests/vereya/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
import json
import time
import os
import warnings
import tagilmo.utils.mission_builder as mb
from tagilmo.utils.vereya_wrapper import MCConnector, RobustObserver
from base_test import BaseTest


def init_mission(mc, start_x, start_z, seed, forceReset="false", forceReuse="false", start_y=78):
def init_mission(mc, start_x, start_z, seed, forceReset="false", forceReuse="false", start_y=78, worldType = "default"):
want_depth = False
video_producer = mb.VideoProducer(width=320 * 4,
height=240 * 4, want_depth=want_depth)
Expand All @@ -34,10 +34,22 @@ def init_mission(mc, start_x, start_z, seed, forceReset="false", forceReuse="fal

flat_param = "3;7,25*1,3*3,2;1;stronghold,biome_1,village,decoration,dungeon,lake,mineshaft,lava_lake"
flat_json = json.dumps(flat_json).replace('"', "%ESC")
world = mb.defaultworld(
seed=seed,
forceReset=forceReset,
forceReuse=forceReuse)
match worldType:
case "default":
world = mb.defaultworld(
seed=seed,
forceReset=forceReset,
forceReuse=forceReuse)
case "flat":
world = mb.flatworld("",
seed=seed,
forceReset=forceReset)
case _:
warnings.warn("World type " + worldType + " is not supported, setting up default world")
world = mb.defaultworld(
seed=seed,
forceReset=forceReset,
forceReuse=forceReuse)
miss.setWorld(world)
miss.serverSection.initial_conditions.allowedmobs = "Pig Sheep Cow Chicken Ozelot Rabbit Villager"
# uncomment to disable passage of time:
Expand Down
2 changes: 1 addition & 1 deletion tests/vereya/run_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def main():
test_files = ['test_motion_vereya', 'test_craft',
'test_inventory', 'test_quit',
'test_observation', 'test_placement', 'test_image',
'test_consistency', 'test_motion_mob', 'test_mob', 'test_agent']
'test_consistency', 'test_motion_mob', 'test_mob', 'test_agent', 'test_flat_world']
res = run_tests(test_files)
if not res.wasSuccessful():
sys.exit(1)
Expand Down
76 changes: 76 additions & 0 deletions tests/vereya/test_flat_world.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import unittest
import logging
from tagilmo import VereyaPython
import json
import time
import tagilmo.utils.mission_builder as mb
from tagilmo.utils.vereya_wrapper import MCConnector, RobustObserver
from base_test import BaseTest


def init_mission(mc, start_x=None, start_z=None):
want_depth = False

video_producer = mb.VideoProducer(width=320 * 4,
height=240 * 4, want_depth=want_depth)

obs = mb.Observations()

agent_handlers = mb.AgentHandlers(observations=obs,
video_producer=video_producer)

print('starting at ({0}, {1})'.format(start_x, start_z))

#miss = mb.MissionXML(namespace="ProjectMalmo.microsoft.com",
miss = mb.MissionXML(
agentSections=[mb.AgentSection(name='Cristina',
agenthandlers=agent_handlers,
# depth
agentstart=mb.AgentStart([start_x, -60.0, start_z, 1]))])
world = mb.flatworld("",
seed='5',
forceReset="false")
miss.setWorld(world)
miss.serverSection.initial_conditions.allowedmobs = "Pig Sheep Cow Chicken Ozelot Rabbit Villager"
# uncomment to disable passage of time:
miss.serverSection.initial_conditions.time_pass = 'false'
miss.serverSection.initial_conditions.time_start = "1000"

if mc is None:
mc = MCConnector(miss)
obs = RobustObserver(mc)
else:
mc.setMissionXML(miss)
return mc, obs


class TestFlat(BaseTest):
mc = None

@classmethod
def setUpClass(cls, *args, **kwargs):
start = (-108.0, -187.0)
mc, obs = init_mission(None, start_x=start[0], start_z=start[1])
cls.mc = mc
assert mc.safeStart()
time.sleep(3)

@classmethod
def tearDownClass(cls, *args, **kwargs):
cls.mc.stop()

def setUp(self):
super().setUp()
self.mc.sendCommand("chat /clear")
time.sleep(3)

def test_flat_world(self):
self.assertTrue(self.mc.is_mission_running())


def main():
VereyaPython.setupLogger()
unittest.main()

if __name__ == '__main__':
main()

0 comments on commit 25e04f2

Please sign in to comment.