Open jonathanfine opened 9 years ago
I'm not convinced about the indexing syntax yet. This just covers a small part of the API.
What happens if you call world[3, 4, 5]
without an assignment? Does it return the block type?
How do you get the height of a specific place? world[3, 4].get_height()
? That won't be possible if the indexing syntax returns a block type (currently an int or enum).
Furthermore, world[3, 4]
is probably wrong, correct would be world[3, _, 4]
because the coordinates are xyz and z is "up" while y is "forward/back".
Last but not least, this will lead to a lot of hacks in the codebase. I'm more for a function or method based approach.
I'd really like to avoid an explicit connection to the world. I believe this should be handled by the instantiation of a Minecraft
class.
I'd really like to avoid an explicit connection to the world. I believe this should be handled by the instantiation of a Minecraft class.
I disagree about that. That's global connection state. It makes testing harder, creates side effects and makes it hard or impossible to control multiple minecraft instances at once.
A lot of projects (e.g. Django or Celery) moved from implicit initialization to explicit initialization (with a very simple default) in the last 1-2 years.
I'd really like to avoid an explicit connection to the world. I believe this should be handled by the instantiation of a Minecraft class.
I disagree about that. That's global connection state. It makes testing harder, creates side effects and makes it hard or impossible to control multiple minecraft instances at once.
Surely that's nothing global, that's a connection per Minecraft
instance, no?
Aaah, sorry, I didn't get that :)
In that case it would be:
from minecraft import Minecraft
world = Minecraft()
# you're connected!
Right?
@dbrgn – Yes that's the API I was going for, sorry I should have added an example to be specific.
@dbrgn
You wrote
What happens if you call world[3, 4, 5] without an assignment? Does it return the block type?
Did you follow the link I gave to
whole user sample user file at smoke.py
The answer is YES.
whole user sample user file at smoke.py
Sorry, I overlooked that :)
In that case: How would you get the height of a specific x-z coordinate in the world? You can't attach any methods to the indexed world call, as it returns an enum type (which is an integer).
from minecraft import Minecraft
world = Minecraft()
# you're connected!
:+1:
@dbrgn asked
How would you get the height of a specific x-z coordinate in the world?
A really good API is one where the answer to this question is obvious, from the basic examples given in my sample file smoke.py.
A good API is one where the answer is obviously the only correct one, once you have seen it. I'm leaving your question as an exercise. I'll tell you what my answer is this evening.
You'll appreciate my answer better if you try to answer the question yourself. (There, I sound like a teacher.)
It is definitely not obvious.
You could go with world[1, 4]
. But then it's not necessarily obvious whether these are xy or xz coordinates.
You could go with something like world[1, ..., 4]
, similar to the way numpy does it.
The return value is also non-obvious. It could return either the height as an integer, or - if you consider the syntax a slice - a sequence of blocks that matches the coordinates (in the case of world[1, ..., 4]
all blocks that are in the vertical column from the lowest to the highest block, at the xz coordinates (x=1, z=4).
@dbrgn
Hint. An object can have attributes (besides __getitem__
and __setitem__
).
You do sound like a teacher. And it makes it hard to provide good feedback.
@dbrgn
We have world[1, 2, 3]
. So how about height[1, 2]
. And to make it easier to use a position in space rather than the horizontal plane, also allow height[1, 2, 3]
.
You were trying to use the [...]
interface directly on world
, which made the problem impossible. But introduce height
and it's easy.
One last thing - height
is an attribute of world
.
h = world.height[pos]
While I like the concept that the world is indexable (treating it as a 3D array), i'm not too fond of having height
as an attribute of world
. There is no hierarchical relation between world and its height. A height is also nothing with a spacial location, it's rather something like a function call. And function calls traditionally use parentheses, not square brackets.
A few thoughts (not all of them well thought-out):
Minecraft
instance called mc
) is not a bad thing, because it allows to attach different "namespaces" like the world, the player, the camera etc. A camera perspective is not really part of the world, so attaching it to the world wouldn't make much sense.from minecraft import Minecraft
mc = Minecraft()
some_position = mc.world[1, 2, 3]
print(some_position.height)
print(some_position.type)
print(some_position.hits)
That would be the OOP style approach. I'm not completely sure yet whether it's better than a functional approach though.
BlockGroup
collection type that allows you to apply changes to multiple blocks at once:from minecraft import BlockGroup, BlockType
# Positions could be indicated by tuples
group = BlockGroup((1, 2, 3), (4, 5, 6), (7, 8, 9))
group.type = BlockType.WOOD
# Or maybe by a separate type? We had a discussion about this in a separate issue.
group = BlockGroup(Position(1, 2, 3), Position(4, 5, 6), Position(7, 8, 9))
# A group could act like a set. That would allow things like intersections or differences.
group.add((1, 3, 5))
# We could define different operations
group.destroy() # Remove blocks (replace with air)
group.translate(0, 3, 0) # Move up by three blocks
We could treat BlockGroups as iterators:
group = BlockGroup((1, 2, 3), (4, 5, 6), (7, 8, 9))
for block in group:
block.type = BlockType.WOOD
Does the low-level API allow us to issue commands affecting more than one
block, or would we have to implement eg group.type = BlockType.WOOD
as a
for-loop internally?
Does the low-level API allow us to issue commands affecting more than one block, or would we have to implement eg
group.type = BlockType.WOOD
as a for-loop internally?
There is a setBlocks
command: https://github.com/py3minepi/py3minepi/wiki/Minecraft-Pi-Protocol-Specification#commands
OK, then it definitely makes sense to allow some whole-group operations in the high-level API (though I think we could usefully make them iterable, too).
That would be trivial by implementing __iter__
.
Absolutely! I'm just saying that we should do so :-)
On Thu, Oct 2, 2014 at 9:25 PM, Danilo Bargen notifications@github.com wrote:
That would be trivial by implementing iter.
— Reply to this email directly or view it on GitHub https://github.com/py3minepi/py3minepi/issues/30#issuecomment-57699447.
I've started exploring the design of the high-level API. My basic idea it to write user code that feels right, and then to provide a stub implementation.
For example, here's how to get going
You can see the whole user sample user file at smoke.py
To reduce distractions while I work I'm doing this in a fork of the main repository, but in my own github account.
I welcome comments, and if it helps to do this you can create a pull request.