horiyouta commited on
Commit
efac804
1 Parent(s): a655d6e

2410261406

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Dockerfile ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10
2
+
3
+ RUN useradd -m -u 1000 user
4
+ USER user
5
+ ENV PATH="/home/user/.local/bin:$PATH"
6
+
7
+ WORKDIR /app
8
+
9
+ COPY --chown=user ./requirements.txt requirements.txt
10
+ RUN pip install --no-cache-dir -r requirements.txt
11
+
12
+ COPY --chown=user . /app
13
+ CMD ["python", "app.py"]
README.md CHANGED
@@ -1,8 +1,8 @@
1
  ---
2
  title: Minecraft MOD Maker 4 English
3
- emoji: 🌍
4
- colorFrom: blue
5
- colorTo: yellow
6
  sdk: docker
7
  pinned: false
8
  ---
 
1
  ---
2
  title: Minecraft MOD Maker 4 English
3
+ emoji:
4
+ colorFrom: green
5
+ colorTo: gray
6
  sdk: docker
7
  pinned: false
8
  ---
app.py ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi.middleware.cors import CORSMiddleware
2
+ from fastapi.staticfiles import StaticFiles
3
+ from fastapi import FastAPI, APIRouter
4
+ import base64, json, zipfile, uvicorn
5
+ from strgen import StringGenerator
6
+ from pydantic import BaseModel
7
+ from pathlib import Path
8
+ from io import BytesIO
9
+ from PIL import Image
10
+
11
+ app = FastAPI()
12
+
13
+ app.add_middleware(
14
+ CORSMiddleware,
15
+ allow_origins=["*"],
16
+ allow_credentials=True,
17
+ allow_methods=["*"],
18
+ allow_headers=["*"],
19
+ )
20
+
21
+ router = APIRouter()
22
+ processing = False
23
+
24
+ class TextRequest(BaseModel): text: str
25
+
26
+ @router.post('/save')
27
+ async def save(req_data: TextRequest):
28
+ data = json.loads(req_data.text)
29
+ zip_buffer = BytesIO()
30
+
31
+ with zipfile.ZipFile(zip_buffer, 'w') as zip_file:
32
+ zip_file.writestr('data.xml', data[0].encode('utf-8'))
33
+ zip_file.writestr('data.txt', data[1].encode('utf-8'))
34
+
35
+ for i in range(2, len(data)):
36
+ file_data = base64.b64decode(data[i].split(',', 1)[1])
37
+ file_name = f'{i - 1}.{data[i].split(";")[0].split("/")[1]}'
38
+ zip_file.writestr(file_name, file_data)
39
+
40
+ zip_buffer.seek(0)
41
+ return base64.b64encode(zip_buffer.getvalue()).decode('utf-8')
42
+
43
+ @router.post('/load')
44
+ async def load(zip_data: TextRequest):
45
+ zip_buffer = BytesIO(base64.b64decode(zip_data.text))
46
+ data = []
47
+ with zipfile.ZipFile(zip_buffer, 'r') as zip_file:
48
+ data.append(zip_file.open('data.xml').read().decode('utf-8'))
49
+ data.append(zip_file.open('data.txt').read().decode('utf-8'))
50
+
51
+ for file_info in zip_file.infolist():
52
+ if file_info.filename.startswith('data.'): continue
53
+ with zip_file.open(file_info) as f:
54
+ ext = file_info.filename.split('.')[-1]
55
+ url = base64.b64encode(f.read()).decode('utf-8')
56
+ data.append(f'data:image/{ext};base64,{url}')
57
+
58
+ return data
59
+
60
+ @router.get('/check')
61
+ async def check():
62
+ global processing
63
+ return 'ng' if processing else 'ok'
64
+
65
+ @router.post('/sb3')
66
+ async def sb3(req_data: TextRequest):
67
+ global processing
68
+ if processing: return ''
69
+ processing = True
70
+ data = json.loads(req_data.text)
71
+ with zipfile.ZipFile(Path('public').joinpath('mmp4.zip').resolve(), 'r') as template_zip:
72
+ with template_zip.open('project.json') as f:
73
+ project = json.loads(f.read().decode('utf-8'))
74
+
75
+ # 新しいZIPファイルを作成
76
+ zip_buffer = BytesIO()
77
+ with zipfile.ZipFile(zip_buffer, 'w') as zip_file:
78
+ variables = project['targets'][0]['variables']
79
+ tiles = project['targets'].index([v for v in project['targets'] if v['name'] == 'Tiles'][0])
80
+
81
+ project['targets'][0]['variables'][[v for v in variables if variables[v][0] == 'MODコード'][0]][1] = data[0]
82
+
83
+ names = StringGenerator('[a-f\\d]{32}').render_list(len(data) - 1, unique=True)
84
+ for i in range(1, len(data)):
85
+ name = f'{names[i - 1]}.png'
86
+ image_data = base64.b64decode(data[i].split(',', 1)[1])
87
+
88
+ # 画像をリサイズ
89
+ img = Image.open(BytesIO(image_data))
90
+ img_resized = img.resize((80, 80))
91
+ img_buffer = BytesIO()
92
+ img_resized.save(img_buffer, format='PNG')
93
+ img_buffer.seek(0)
94
+
95
+ # リサイズした画像をZIPに追加
96
+ zip_file.writestr(name, img_buffer.getvalue())
97
+
98
+ project['targets'][tiles]['costumes'].append({
99
+ "name": str(i),
100
+ "bitmapResolution": 2,
101
+ "dataFormat": "png",
102
+ "assetId": names[i - 1],
103
+ "md5ext": f"{names[i - 1]}.png",
104
+ "rotationCenterX": 40,
105
+ "rotationCenterY": 40
106
+ })
107
+
108
+ # 更新されたproject.jsonを書き込む
109
+ zip_file.writestr('project.json', json.dumps(project).encode('utf-8'))
110
+
111
+ # mmp4.zipの他のファイルもコピー
112
+ with zipfile.ZipFile(Path('public').joinpath('mmp4.zip').resolve(), 'r') as template_zip:
113
+ for item in template_zip.infolist():
114
+ if item.filename != 'project.json':
115
+ zip_file.writestr(item.filename, template_zip.read(item.filename))
116
+
117
+ # ZIPファイルのバイナリデータをBase64エンコード
118
+ zip_buffer.seek(0)
119
+ sb3_base64 = base64.b64encode(zip_buffer.getvalue()).decode('utf-8')
120
+
121
+ processing = False
122
+ return sb3_base64
123
+
124
+ app.include_router(router, prefix='/api')
125
+
126
+ if __name__ == '__main__':
127
+ app.mount('/', StaticFiles(directory=Path('public'), html=True), name='public')
128
+ uvicorn.run(app, host='0.0.0.0', port=7860)
public/data.js ADDED
The diff for this file is too large to render. See raw diff
 
public/data/1.png ADDED
public/data/10.png ADDED
public/data/100.png ADDED
public/data/101.png ADDED
public/data/102.png ADDED
public/data/103.png ADDED
public/data/104.png ADDED
public/data/105.png ADDED
public/data/106.png ADDED
public/data/107.png ADDED
public/data/108.png ADDED
public/data/109.png ADDED
public/data/11.png ADDED
public/data/110.png ADDED
public/data/111.png ADDED
public/data/112.png ADDED
public/data/113.png ADDED
public/data/114.png ADDED
public/data/115.png ADDED
public/data/116.png ADDED
public/data/117.png ADDED
public/data/118.png ADDED
public/data/119.png ADDED
public/data/12.png ADDED
public/data/120.png ADDED
public/data/121.png ADDED
public/data/122.png ADDED
public/data/123.png ADDED
public/data/124.png ADDED
public/data/125.png ADDED
public/data/126.png ADDED
public/data/127.png ADDED
public/data/128.png ADDED
public/data/129.png ADDED
public/data/13.png ADDED
public/data/130.png ADDED
public/data/131.png ADDED
public/data/132.png ADDED
public/data/133.png ADDED
public/data/134.png ADDED
public/data/135.png ADDED
public/data/136.png ADDED
public/data/137.png ADDED
public/data/138.png ADDED
public/data/139.png ADDED
public/data/14.png ADDED