Skip to content

Commit

Permalink
update getting_start.md
Browse files Browse the repository at this point in the history
  • Loading branch information
Ovizro committed Nov 10, 2021
1 parent 6ab9657 commit 1a6ee7f
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 60 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ dmypy.json
cython_debug/

/testdatapack
/test
/testdatapack.py
/mcdp/command
.vscode
Expand Down
Binary file added doc/pictures/hello_world_reload.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
38 changes: 34 additions & 4 deletions doc/zh_cn/getting_start.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,40 @@

> 由于该项目目前正在开发,该文档可能会随时更改。里面的内容也可能因为文档更新的延误而暂时无法使用,还请见谅。
首先,我们需要在电脑上安装一个Python。推荐使用3.8或以上的版本,否则可能会出现兼容问题。然后到[Github](https://github.com/Ovizro/Mcdp/releases)中下载最新的包。
![在这里下载](https://github.com/Ovizro/Mcdp/blob/master/doc/pictures/Mcdp_releases.png)
最后在控制台中输入以下命令来进行安装,以0.1.0版本为例。
## 前期准备

想要玩转Mcdp这个Python库,我们需要准备两个东西——Minecraft和Python。

Minecraft自然不用多说,只要是>=1.14的JE版就没有问题。
同时,我们需要在电脑上安装一个Python。推荐使用3.8或以上的版本,否则可能会出现兼容问题。

> 嗯,什么是Python?Python是一种计算机程序设计语言。基础的Python安装教程可以参考[这里](https://www.liaoxuefeng.com/wiki/1016959663602400/1016959856222624)
光有一个Python本体还不行,我们还需要到[Github](https://github.com/Ovizro/Mcdp/releases)中下载最新的Mcdp包。
[![在这里下载](https://github.com/Ovizro/Mcdp/blob/master/doc/pictures/Mcdp_releases.png)](https://github.com/Ovizro/Mcdp/releases)

最后在你下载下来的包所在的文件夹中打开控制台,输入以下命令来进行安装,以0.1.0版本为例。

pip install Mcdp-0.1.0.tar.gz

> 嗯,什么是Python?Python是一种计算机程序设计语言。基础的Python安装教程可以参考[这里](https://www.liaoxuefeng.com/wiki/1016959663602400/1016959856222624)
> 一个方便的打开控制台的办法是在文件夹中按住shift点右键->在此处打开powershell
## 开始使用

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

```py
from mcdp import *

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

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

如果你已经成功的完成了安装步骤,在运行过后,test_mcdp.py所在的文件夹中就会多出一个名为MyFirstDatapack的文件夹,这个就是一个完整的数据包啦。
然后,把这个文件夹复制到世界存档的datapacks文件夹中,进入游戏。输入`/reload`命令进行一下重载。如果你能看到聊天框中的"Hello world!",就说明你成功了。
![HelloWorld](https://github.com/Ovizro/Mcdp/blob/master/doc/pictures/hello_world_reload.png)
9 changes: 5 additions & 4 deletions mcdp/aio_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@
from pathlib import Path
from functools import partial, wraps
from aiofiles import open as aio_open
from typing import List, Optional, TypeVar
from typing import List, Optional, Union

from .counter import get_counter

counter = get_counter()

T_Path = TypeVar("T_Path", str, os.PathLike, Path)
T_Path = Union[str, os.PathLike, Path]


def aio_future(func):
@wraps(func)
async def run(*args, loop=None, executor=None, **kwargs):
async def run(*args, loop=None, executor=None, **kwargs) -> asyncio.Future:
if loop is None:
loop = asyncio.get_event_loop()
pfunc = partial(func, *args, **kwargs)
Expand Down Expand Up @@ -55,13 +55,14 @@ class Stream:
__slots__ = ["opened", "closed", "write_tasks", "__file", "path"]

pathtools = os.path
tasks: List[List[asyncio.Task]] = []

def __init__(
self,
path: T_Path,
*,
root: Optional[T_Path] = None
) -> None:
) -> None:
p = Path(path)
if not p.is_absolute():
if not root:
Expand Down
26 changes: 16 additions & 10 deletions mcdp/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from io import StringIO
from typing import Any, Dict, List, Literal, Optional, Set, Tuple, Type, Union


from .typings import McdpBaseModel, McdpVar, McdpError
from .mcstring import MCString
from .context import insert
Expand All @@ -15,7 +16,7 @@ def __init__(
self,
value: str,
type: Optional[Literal["absolute", "relative", "local"]] = None
) -> None:
) -> None:
self.value = value
if '^' in value:
if len(value) > 1:
Expand Down Expand Up @@ -620,13 +621,13 @@ def __init__(self, data: Optional[List[str]] = None, *, base: bool = False):
self.data = data
self.base = base

def __getitem__(self, value: Any) -> "IOStreamObject":
def __getitem__(self, value: Any):
if self.base:
self = self.copy()

self.data.append(value)
return self

def copy(self):
return self.__class__(self.data.copy())

Expand All @@ -636,7 +637,6 @@ class Printer(IOStreamObject):
__slots__ = []

input: List[MCString]
cmd: str = "tellraw {targets} {input}"

def __init__(self, data: Optional[List[str]] = None, *, base: bool = False):
super().__init__(data, base=base)
Expand All @@ -653,8 +653,19 @@ def __lshift__(self, other: Any) -> "Printer":
input = self.input[0]
else:
input = "[{0}]".format(','.join((str(i) for i in self.input)))
other.__apply_printer__(self.cmd, input=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):
Expand All @@ -664,11 +675,6 @@ def __lshift__(self, other: Any) -> "Printer":
return self


class TitlePrinter(Printer):

__slots__ = []


class PrinterEOF(IOStreamObject):

__slots__ = []
Expand Down
7 changes: 3 additions & 4 deletions mcdp/config.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from os import PathLike
from functools import partial
from typing import Literal, Union, Optional
from typing import Literal, Union, Optional, List

from .typings import McdpBaseModel, McdpError, McdpVersionError
from .version import (Version, T_version, __version__, version_check, AioCompatVersionChecker)
Expand All @@ -13,12 +12,12 @@ class PydpConfig(McdpBaseModel):
class VmclConfig(McdpBaseModel):
enabled: bool = True
enable_pywheel: bool = True
add_function_comments: bool = True


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


def get_version(mc_version: T_version) -> int:
Expand Down
34 changes: 23 additions & 11 deletions mcdp/context.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import asyncio
import ujson
import warnings
from pathlib import Path
from collections import ChainMap, UserList, defaultdict
from typing import Any, Dict, List, Literal, Optional, Callable, Union, Type
Expand Down Expand Up @@ -226,7 +226,7 @@ def __init__(self, type: _tagType, *, namespace: Optional[str] = None, replace:
if not namespace:
namespace = get_namespace()
self.root_path = Path(namespace, "tags", type).resolve()
self.cache = defaultdict(set)
self.cache = defaultdict(list)

self.name = f"{namespace}:{type}"
self.collect()
Expand All @@ -237,19 +237,22 @@ def add(self, tag: str, item: str, *, namaspace: Optional[str] = None) -> None:
namaspace = get_namespace()
item = f"{namaspace}:{item}"

self.cache[tag].add(item)
if item in self.cache[tag]:
warnings.warn(f"Try to add the tag '{tag}' twice.")
else:
self.cache[tag].append(item)

def __getitem__(self, key: str) -> set:
def __getitem__(self, key: str) -> List[str]:
return self.cache[key]

def __setitem__(self, key: str, item: str) -> None:
self.add(key, item)

def get_tag_data(self, tag: str, replace: bool = False) -> dict:
if not tag in self.cache:
raise McdpContextError
raise McdpContextError(f"Cannot find tag {tag} in the cache.")

values = list(self.cache[tag])
values = self.cache[tag]
if not replace:
replace = self.replace
return {"replace": replace, "values": values}
Expand All @@ -263,18 +266,22 @@ async def apply_tag(self, tag: str, *, replace: bool = False) -> None:

del self.cache[tag]

def apply(self) -> None:
def apply(self) -> List[asyncio.Task]:
tl = []
for tag in self.cache:
asyncio.ensure_future(self.apply_tag(tag))
tl.append(asyncio.ensure_future(self.apply_tag(tag)))
return tl

def collect(self) -> None:
self.collection[self.name] = self

@classmethod
def apply_all(cls) -> None:
def apply_all(cls) -> asyncio.Future:
tl = []
for i in cls.collection.values():
i: TagManager
i.apply()
tl.extend(i.apply())
return asyncio.gather(*tl)

def __del__(self) -> None:
if self.cache:
Expand All @@ -294,8 +301,13 @@ def get_stack_id() -> int:


def add_tag(tag: str, value: Optional[str] = None, *, namespace: Optional[str] = None, type: _tagType = "functions") -> None:
if not namespace:
if ':' in tag:
nt = tag.split(':', 2)
namespace = nt[0]
tag = nt[1]
elif not namespace:
namespace = get_namespace()

if not value:
if type == "functions":
c = Context.top
Expand Down
34 changes: 14 additions & 20 deletions mcdp/mcfunc.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import asyncio
from asyncio.events import get_running_loop
import warnings
from asyncio import iscoroutinefunction, run, all_tasks, current_task, gather
from inspect import signature, Parameter
Expand Down Expand Up @@ -36,7 +35,11 @@ def _get_arguments(name: str, param: Mapping[str, Parameter]) -> Tuple[list, dic
return args, kwds





class MCFunction(McdpVar):

__slots__ = ["__name__", "overload", "namespace", "overload_counter", "config"]
__accessible__ = ["__name__"]

Expand Down Expand Up @@ -158,13 +161,9 @@ def __call__(self, *args: Any, **kwds: Any) -> Any:
@overload
def mcfunc(func: Callable) -> MCFunction:
...


@overload
def mcfunc(*args, **kw) -> Callable[[Callable], MCFunction]:
...


def mcfunc(func: Optional[Callable] = None, *args, **kw):
def wrapper(_func: Callable) -> MCFunction:
m = MCFunction(func.__qualname__, **kw)
Expand All @@ -178,17 +177,13 @@ def wrapper(_func: Callable) -> MCFunction:


@overload
def mcfunc_main(func: Callable) -> NoReturn:
def mcfunc_main(func: Callable) -> None:
...


@overload
def mcfunc_main(*args, **kw) -> Callable[[Callable], NoReturn]:
def mcfunc_main(*args: str, **kw: Any) -> Callable[[Callable], None]:
...


def mcfunc_main(func: Optional[Union[Callable, str]], *args, **kw):
async def md_main(func: Callable[[], Optional[Coroutine]]) -> NoReturn:
def mcfunc_main(func: Optional[Union[Callable, str]] = None, *args, **kw):
async def mf_main(func: Callable[[], Any]) -> None:
#config = get_config()
await build_dirs_from_config()
async with Context:
Expand All @@ -203,16 +198,15 @@ async def md_main(func: Callable[[], Optional[Coroutine]]) -> NoReturn:
async with Context('__init_score__'):
Scoreboard.apply_all()

TagManager.apply_all()
await MCFunction.apply_all()

await get_running_loop().shutdown_asyncgens()
await TagManager.apply_all()
get_counter().print_out()

if callable(func):
run(md_main(func))
run(mf_main(func))
else:
def get_func(func: Callable[[], Optional[Coroutine]]) -> NoReturn:
run(md_main(func))
def get_func(func: Callable[[], Coroutine]) -> None:
run(mf_main(func))

return get_func
return get_func
Loading

0 comments on commit 1a6ee7f

Please sign in to comment.