Skip to content

Commit

Permalink
a lot of 'updates'
Browse files Browse the repository at this point in the history
  • Loading branch information
Ovizro committed Nov 12, 2021
1 parent 661ac23 commit 152e320
Show file tree
Hide file tree
Showing 13 changed files with 219 additions and 141 deletions.
20 changes: 14 additions & 6 deletions doc/zh_cn/getting_start.md → doc/zh_cn/GettingStart.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,29 @@ Minecraft自然不用多说,只要是>=1.14的JE版就没有问题。
## 开始使用

那么,按照惯例,我们先来一个"Hello world"。
新建一个test_mcdp.py,然后输入以下内容。
那么,按照惯例,我们先来一个"Hello world"。
在你常用的IDE中新建一个test_mcdp.py,然后输入以下内容。

```py
from mcdp import *

Config("MyFirstDatapack", "1.16.5", "Hello world!")
Config("mydatapack", "1.16.5", "Hello world!")

@mcfunc_main
def main():
add_tag("minecraft:load")
cout << "Hello world!" << endl
```

如果你已经成功的完成了安装步骤,在运行过后,test_mcdp.py所在的文件夹中就会多出一个名为MyFirstDatapack的文件夹,这个就是一个完整的数据包啦。
如果你已经成功的完成了安装步骤,在运行过后,test_mcdp.py所在的文件夹中就会多出一个名为mydatapack的文件夹,这个就是一个完整的数据包啦。
然后,把这个文件夹复制到世界存档的datapacks文件夹中,进入游戏。输入`/reload`命令进行一下重载。如果你能看到聊天框中的"Hello world!",就说明你成功了。

##
## 解释与说明

让我们来看一下这几句代码的作用。

首先,我们从mcdp中导入了我们需要的类及函数。为了方便起见,这里的导入内容使用了`*`,也就是里面的所有函数和类。
然后,我们使用`Config`来设置了整个数据包的配置文件。`Config`中的三个参数依次为数据包的名称、受支持的Minecraft版本,以及数据包的描述内容。
接下来,我们定义了main函数。`@mcfunc_main`是Mcdp提供的一个装饰器,用来将main函数标记为整个数据包的主函数。
里面的`cout`是标准输出流,用来向聊天框中输出文字。(学过C++的小伙伴应该会很熟悉) 这里使用了左移运算符(`<<`)来写入文字"Hello world!"。但只有一个`cout`并不行,还需要一个`endl`来进行配合。`endl`意为"end of line",用来告诉输出流当前输出结束,可以开始打印了。如果删去`<< endl`,那么程序将不会打出任何东西。

怎么样,是不是非常简单?
38 changes: 15 additions & 23 deletions doc/zh_cn/README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,26 @@
# Mcdp #
# Mcdp

一个用来帮助制作数据包的Python库,
名称"Mcdp"是"Minecraft datapack"的简称。

语言: [English](https://github.com/Ovizro/Mcdp/blob/master/doc/en_us/README.md) / 中文

## 为什么使用它? ##
## 为什么要使用它

1. 直接与世界关联:
与mod不同,数据包是与世界绑定的。你可以为一个世界创造专有的玩法,
而不会对其他世界造成影响。
Mcdp极大的方便了数据包的编写。诚然,现在已经有很多大佬编写出了快速创建模版,语法高亮及语法补全等非常方便的功能,但是,由于数据包本身的特性,数据包的编写依然非常复杂。

1. 便捷:
相比常规的命令使用来说,Mcdp简化了调用命令的方式。
使用Mcdp,你可以仅仅写一个简短的Python或Mcdl文件,然后编译出完整的数据包。
而Mcdp则从另一个角度出发,是将Minecraft命令看作汇编语言,在此基础上进一步开发出的高级语言,提供了更多的语法抽象,为数据包的编写者带来更多的便利。同时由于Python和Minecraft命令的特点,其相对简单,易于学习,对于初学者更加友好。

2. 简单:
Mcdp可以被认为是以Minecraft命令作为汇编,以Python作为解释器的高级语言。
由于Python本身的特点及Minecraft命令的普及性,Mcdp需要的编程基础相对较少。
而且,你可以方便的在函数中直接插入原版命令。

3. 无需Forge、Fabric等支持:
你可以直接在原版中将数据包放入世界存档来使用。发送存档时,数据包会和世界存档一起打包,省去了mod安装的麻烦。

4. 兼容性较强:
Minecraft命令随版本变化较少,而且一般都是增加新的命令而已有命令保持不变。 因此只要不使用一些高版本特性,数据包很容易跨游戏版本使用而不必做出更改。
或许也有人会问,如果想要更加方便的功能,为什么不去编写mod呢?
很简单,数据包与mod的定位并不是完全相同的。<br>
与mod不同,数据包是与世界绑定的。你可以为一个世界创造专有的玩法,
而不会对其他世界造成影响。<br>
同时,数据包无需Forge、Fabric等支持,你可以直接在原版中将数据包放入世界存档来使用。发送存档时,数据包会和世界存档一起打包,省去了mod安装的麻烦。<br>
数据包的兼容性也较强。Minecraft命令随版本变化较少,而且一般都是增加新的命令而已有命令保持不变。 因此只要不使用一些高版本特性,数据包很容易跨游戏版本使用而不必做出更改。

## 不适用情况 ##

以下情况不适合使用Mcdp
以下情况不适合使用Mcdp,或许你需要去学习一下如何制作一个mod。

1. 复杂的计算:
Mcdp生成的数据包的计算主要由记分板来完成。 原版命令提供的运算符较少,且计算效率低下。 虽然能够在Mcdp中通过计算实现各种数学函数,但从效率来看有些得不偿失。
Expand All @@ -38,9 +30,9 @@

## 工作方式 ##

Mcdp主要有三种工作方式: Python内部编写、由mcfzip快速创建和编译Mcdl文件。
Mcdp计划拥有三种工作方式: Python内部编写、由mcfzip快速创建和编译Mcdl文件。

> 这一段目前仅实现了Pydp[\\doge]
> 这一阶段目前仅实现了Pydp[\\doge]
1. Python内部编写(Pydp)

Expand All @@ -56,7 +48,7 @@ Mcdp主要有三种工作方式: Python内部编写、由mcfzip快速创建和

缺点
1. 操作复杂:
所有Mcdp函数均需要使用mcfunc装饰器。 需要的变量大多需要自行创建。 由于if/for等关键字无法捕获,需要使用相应的 上下文管理器来代替(解决方案见'mcfunc&ast解析')
所有Mcdp函数均需要使用mcfunc装饰器。 需要的变量大多需要自行创建。 由于if/for等关键字无法捕获,需要使用相应的 上下文管理器来代替。
2. 难以检查错误:
Pydp很多错误难以在编译时检查,容易导致让人困惑的行为。
(见'Pydp常见问题')
Expand All @@ -74,4 +66,4 @@ Mcdp主要有三种工作方式: Python内部编写、由mcfzip快速创建和
1. 功能简单:
简单,当然要简单到底。mcfzip只能生成含函数的数据包。 编译器只分隔命令到不同文件,不检查命令格式是否正确, 也不会对命令进行其他修改。
2. 无扩展包:
mcfzip的编译不支持自定义,也没有任何可用的包。
mcfzip的编译不支持自定义,也没有任何可用的包。
2 changes: 1 addition & 1 deletion mcdp/aio_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def __init__(
path: T_Path,
*,
root: Optional[T_Path] = None
) -> None:
) -> None:
p = Path(path)
if not p.is_absolute():
if not root:
Expand Down
76 changes: 40 additions & 36 deletions mcdp/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from .typings import McdpBaseModel, McdpVar, McdpError
from .mcstring import MCString
from .context import insert
from .exceptions import *


class PosComponent(McdpVar):
Expand All @@ -30,7 +31,7 @@ def __init__(
int(value)
self.type = "absolute"
if type and (type != self.type):
raise ValueError("unsuit position value.")
raise McdpValueError("unsuit position value.")

def __str__(self) -> str:
return self.value
Expand All @@ -45,21 +46,21 @@ class Position(McdpVar):
def __init__(self, pos: str) -> None:
l = [PosComponent(i) for i in pos.split()]
if len(l) != 3:
raise ValueError("incorrect position length.")
raise McdpValueError("Incorrect position length.")

tid = 0
for i in l:
if i.type == "absolute":
if tid == 3:
raise TypeError
raise McdpTypeError("Invalid position.")
tid = 1
elif i.type == "relative":
if tid == 3:
raise TypeError
raise McdpTypeError("Invalid position.")
tid = 2
else:
if tid < 3 and tid != 0:
raise TypeError
raise McdpTypeError("Invalid position.")
tid = 3

self._posXYZ = tuple(l)
Expand Down Expand Up @@ -207,7 +208,7 @@ def __init__(self, axes: str) -> None:
y = axes.count('y')
z = axes.count('z')
if x > 1 or y > 1 or z > 1 or x + y + z != len(axes):
raise ValueError(
raise McdpValueError(
"Axes should be any non-repeating combination of the characters 'x', 'y', and 'z'.")
McdpBaseModel.__init__(self, axes=axes)

Expand Down Expand Up @@ -260,12 +261,12 @@ def __init__(
) -> None:
if entity:
if not anchor:
raise ValueError("Miss a argument 'anchor'.'")
raise McdpValueError("Miss a argument 'anchor'.'")
McdpBaseModel.__init__(
self, targets=pos_or_targets, anchor=anchor, entity=True)
else:
if anchor:
raise ValueError("Invalid argument 'anchor'.")
raise McdpValueError("Invalid argument 'anchor'.")
McdpBaseModel.__init__(self, pos=pos_or_targets, entity=entity)

def __str__(self) -> str:
Expand Down Expand Up @@ -428,7 +429,7 @@ def __init__(
) -> None:
if ops == "matches":
if source_obj:
raise ValueError("Invalid source objective.")
raise McdpValueError("Invalid source objective.")
super().__init__(
target=target,
target_obj=target_obj,
Expand Down Expand Up @@ -644,41 +645,44 @@ def __init__(self, data: Optional[List[str]] = None, *, base: bool = False):

def __lshift__(self, other: Any) -> "Printer":
if isinstance(other, PrinterEOF):
if len(self.input) < 1:
raise McdpCommandError(
"tellraw", ValueError(
"No string griven."
))
elif len(self.input) == 1:
input = self.input[0]
else:
input = "[{0}]".format(','.join((str(i) for i in self.input)))

if not self.data:
other.__apply_printer__("tellraw {targets} {input}", input=input)
elif len(self.data) == 1:
other.__apply_printer__("title {targets} {subcmd} {input}", input=input, subcmd=self.data[0])
else:
raise McdpCommandError(
"tellraw/title", ValueError(
"Invalid printer data."
))

self.input.clear()
self.data.clear()
return self

if not isinstance(other, MCString):
other = MCString.validate(other)
other(self)
else:
if not isinstance(other, MCString):
other = MCString.validate(other)

self.input.append(other)
self.input.append(other)
return self


class PrinterEOF(IOStreamObject):

__slots__ = []

def __call__(self, stream: Printer) -> None:
if len(stream.input) < 1:
raise McdpCommandError(
"tellraw", ValueError(
"No string griven."
))
elif len(stream.input) == 1:
input = stream.input[0]
else:
input = "[{0}]".format(','.join((str(i) for i in stream.input)))

if not stream.data:
self.__apply_printer__("tellraw {targets} {input}", input=input)
elif len(stream.data) == 1:
self.__apply_printer__("title {targets} {subcmd} {input}", input=input, subcmd=stream.data[0])
else:
raise McdpCommandError(
"tellraw/title", ValueError(
"Invalid printer data."
))

stream.input.clear()
stream.data.clear()


def __apply_printer__(self, cmd: str, **kw) -> None:
if len(self.data) == 0:
targets = "@a"
Expand Down
13 changes: 7 additions & 6 deletions mcdp/config.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
from os import PathLike
from typing import Literal, Union, Optional, List

from .typings import McdpBaseModel, McdpError, McdpVersionError
from .version import (Version, T_version, __version__, version_check, AioCompatVersionChecker)
from typing import Literal, Union, Optional, List, Set

from .typings import McdpBaseModel
from .version import Version, T_version, __version__, AioCompatVersionChecker
from .exceptions import *

class PydpConfig(McdpBaseModel):
use_ast: bool = False
add_function_comments: bool = True


class VmclConfig(McdpBaseModel):
enabled: bool = True
enable_pywheel: bool = True
add_function_comments: bool = True


class MCFuncConfig(McdpBaseModel):
type: Literal["sfunction", "normal"] = "normal"
tag: List[str] = []
allow_overload: bool = True
tag: Set[str] = set()


def get_version(mc_version: T_version) -> int:
Expand Down
24 changes: 16 additions & 8 deletions mcdp/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
import warnings
from pathlib import Path
from collections import ChainMap, UserList, defaultdict
from typing import Any, Dict, List, Literal, Optional, Callable, Union, Type
from typing import Any, ClassVar, Dict, List, Literal, Optional, Callable, Union, Type

from .typings import McdpVar, Variable, McdpError
from .typings import McdpVar, Variable
from .config import get_config
from .aio_stream import Stream, T_Path, wraps
from .counter import get_counter
from .exceptions import McdpError


class StackCache(UserList):
Expand Down Expand Up @@ -136,8 +137,8 @@ class Context(McdpVar, metaclass=ContextMeta):

path: Path
top: "Context"
enter: EnvMethod
leave: EnvMethod
enter: ClassVar[EnvMethod]
leave: ClassVar[EnvMethod]

def __init__(self, name: str, *, root_path: Optional[T_Path] = None):
self.name = name
Expand Down Expand Up @@ -189,7 +190,11 @@ def comment(self, *content: str) -> None:
else:
com.append(c)

self.write("#" + "\n#".join(com) + "\n")
self.write("# " + "\n# ".join(com) + "\n")

@EnvMethod
def newline(self, line: int = 1) -> None:
self.write("\n" * line)

@EnvMethod
def get_stack_id(self) -> int:
Expand Down Expand Up @@ -259,7 +264,7 @@ def get_tag_data(self, tag: str, replace: bool = False) -> dict:

async def apply_tag(self, tag: str, *, replace: bool = False) -> None:
if not tag in self.cache:
raise McdpContextError
raise McdpContextError(f"Tag {tag} did not defined.")

async with Stream(tag + ".json", root=self.root_path) as stream:
await stream.adump(self.get_tag_data(tag, replace))
Expand Down Expand Up @@ -289,11 +294,14 @@ def __del__(self) -> None:


def insert(*content: str) -> None:
return Context.insert(*content)
Context.insert(*content)


def comment(*content: str) -> None:
return Context.comment(*content)
Context.comment(*content)

def newline(line: int = 1) -> None:
Context.newline(line)


def get_stack_id() -> int:
Expand Down
6 changes: 3 additions & 3 deletions mcdp/entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from itertools import count
from functools import lru_cache
from itertools import count
from typing import Any, Generator, Literal, Optional, Union, Dict
from typing import Any, List, Union, Dict

from .config import get_config
from .context import Context, insert, enter_stack_ops, leave_stack_ops
Expand Down Expand Up @@ -55,10 +55,10 @@ def __init__(

if not nbt.get("Tags", None):
self.tags = [get_tag()]
elif not get_tag() in nbt["Tags"]:
nbt["Tags"] = self.tags
elif isinstance(nbt["Tags"], list) and not get_tag() in nbt["Tags"]:
nbt["Tags"].append(get_tag())
self.tags = nbt["Tags"]
nbt["Tags"] = self.tags

nbt_string = ujson.dumps(nbt)
cmd.write(' ')
Expand Down
Loading

0 comments on commit 152e320

Please sign in to comment.