Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example for DrawingDecorator #176

Merged
merged 8 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -89,16 +89,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 @@ -122,6 +123,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
Loading