mcmanager 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. mcmanager-0.1.0/MANIFEST.in +5 -0
  2. mcmanager-0.1.0/PKG-INFO +106 -0
  3. mcmanager-0.1.0/README.md +90 -0
  4. mcmanager-0.1.0/mcmanager/__init__.py +0 -0
  5. mcmanager-0.1.0/mcmanager/asgi.py +16 -0
  6. mcmanager-0.1.0/mcmanager/cli.py +115 -0
  7. mcmanager-0.1.0/mcmanager/configs/server.properties +33 -0
  8. mcmanager-0.1.0/mcmanager/console/__init__.py +0 -0
  9. mcmanager-0.1.0/mcmanager/console/admin.py +29 -0
  10. mcmanager-0.1.0/mcmanager/console/apps.py +22 -0
  11. mcmanager-0.1.0/mcmanager/console/models.py +112 -0
  12. mcmanager-0.1.0/mcmanager/console/static/css/font-awesome.css +2337 -0
  13. mcmanager-0.1.0/mcmanager/console/static/css/font-awesome.min.css +4 -0
  14. mcmanager-0.1.0/mcmanager/console/static/css/styles.css +3 -0
  15. mcmanager-0.1.0/mcmanager/console/static/css/tailwind.css +743 -0
  16. mcmanager-0.1.0/mcmanager/console/static/css/toastify.min.css +15 -0
  17. mcmanager-0.1.0/mcmanager/console/static/fonts/fontawesome-webfont.ttf +0 -0
  18. mcmanager-0.1.0/mcmanager/console/static/fonts/fontawesome-webfont.woff +0 -0
  19. mcmanager-0.1.0/mcmanager/console/static/fonts/fontawesome-webfont.woff2 +0 -0
  20. mcmanager-0.1.0/mcmanager/console/static/img/favicon.ico +0 -0
  21. mcmanager-0.1.0/mcmanager/console/static/js/toastify-js.js +15 -0
  22. mcmanager-0.1.0/mcmanager/console/templates/console/index.html +223 -0
  23. mcmanager-0.1.0/mcmanager/console/templates/index.html +42 -0
  24. mcmanager-0.1.0/mcmanager/console/tests.py +3 -0
  25. mcmanager-0.1.0/mcmanager/console/urls.py +14 -0
  26. mcmanager-0.1.0/mcmanager/console/views.py +175 -0
  27. mcmanager-0.1.0/mcmanager/settings.py +158 -0
  28. mcmanager-0.1.0/mcmanager/urls.py +11 -0
  29. mcmanager-0.1.0/mcmanager/wsgi.py +16 -0
  30. mcmanager-0.1.0/mcmanager.egg-info/PKG-INFO +106 -0
  31. mcmanager-0.1.0/mcmanager.egg-info/SOURCES.txt +36 -0
  32. mcmanager-0.1.0/mcmanager.egg-info/dependency_links.txt +1 -0
  33. mcmanager-0.1.0/mcmanager.egg-info/entry_points.txt +2 -0
  34. mcmanager-0.1.0/mcmanager.egg-info/requires.txt +3 -0
  35. mcmanager-0.1.0/mcmanager.egg-info/top_level.txt +1 -0
  36. mcmanager-0.1.0/pyproject.toml +36 -0
  37. mcmanager-0.1.0/requirements.txt +7 -0
  38. mcmanager-0.1.0/setup.cfg +4 -0
@@ -0,0 +1,5 @@
1
+ recursive-include mcmanager/configs *
2
+ recursive-include mcmanager/console/templates *
3
+ recursive-include mcmanager/console/static *
4
+ include README.md
5
+ include requirements.txt
@@ -0,0 +1,106 @@
1
+ Metadata-Version: 2.4
2
+ Name: mcmanager
3
+ Version: 0.1.0
4
+ Summary: A Django-based web interface to manage Minecraft servers on a VPS
5
+ License: MIT
6
+ Classifier: Programming Language :: Python :: 3
7
+ Classifier: Framework :: Django
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: POSIX :: Linux
10
+ Classifier: Topic :: Games/Entertainment
11
+ Requires-Python: >=3.8
12
+ Description-Content-Type: text/markdown
13
+ Requires-Dist: Django<5.2.0,>=4.2.0
14
+ Requires-Dist: psutil>=5.8.0
15
+ Requires-Dist: whitenoise>=6.0.0
16
+
17
+ # mcmanager (BETA)
18
+
19
+ Um painel web simples baseado em Django para gerenciar servidores Minecraft diretamente na sua VPS Linux.
20
+
21
+ ## Instalação
22
+
23
+ ### 1. Instalar o Java 8 (Necessário para o Minecraft)
24
+
25
+ ```console
26
+ sudo apt-get update
27
+ sudo apt-get install openjdk-8-jre-headless
28
+ ```
29
+
30
+ ### 2. Instalar o mcmanager do PyPI
31
+
32
+ ```console
33
+ pip install mcmanager
34
+ ```
35
+
36
+ ### 3. Inicializar e rodar o painel
37
+
38
+ ```console
39
+ # Inicializa o banco de dados e cria os diretórios na pasta ~/.mcmanager
40
+ mcmanager init
41
+
42
+ # Cria um usuário administrador
43
+ mcmanager createsuperuser
44
+
45
+ # Inicia o painel
46
+ mcmanager run
47
+ ```
48
+
49
+ Pronto! Acesse `http://sua-vps-ip:8000/admin/` para logar com o superusuário criado e começar a gerenciar seus servidores.
50
+
51
+ ---
52
+
53
+ ## Estrutura de Diretórios e Dados
54
+
55
+ Por padrão, todos os dados do painel ficam armazenados de forma isolada na home do usuário:
56
+ - `~/.mcmanager/db.sqlite3` (Banco de dados do painel)
57
+ - `~/.mcmanager/jar/` (Coloque seus arquivos `.jar` de servidor aqui, ex: `spigot.jar`, `vanilla.jar`)
58
+ - `~/.mcmanager/servers/` (Diretório onde cada servidor criado será executado)
59
+ - `~/.mcmanager/configs/` (Onde fica o `server.properties` padrão)
60
+ - `~/.mcmanager/staticfiles/` (Arquivos estáticos compilados do painel)
61
+
62
+ ### Customizações por Variáveis de Ambiente
63
+
64
+ Você pode ajustar o comportamento do painel definindo variáveis de ambiente antes de executar o comando `mcmanager`:
65
+
66
+ * **`MCMANAGER_DATA_DIR`**: Altera a pasta padrão onde os servidores e banco de dados são salvos (padrão: `~/.mcmanager`).
67
+ * **`MCMANAGER_JAVA_BIN`**: Especifica o caminho binário do Java (padrão: `/usr/lib/jvm/java-8-openjdk-amd64/bin/java`). Use `whereis java` para encontrar o caminho correto na sua VPS.
68
+ * **`MCMANAGER_ALLOWED_HOSTS`**: Lista de hosts permitidos separados por vírgula (padrão: `*`).
69
+ * **`MCMANAGER_DEBUG`**: Define se o painel roda em modo debug (`True` ou `False`).
70
+
71
+ Exemplo definindo um caminho diferente de Java e iniciando:
72
+ ```console
73
+ export MCMANAGER_JAVA_BIN="/usr/bin/java"
74
+ mcmanager run
75
+ ```
76
+
77
+ ---
78
+
79
+ ## Desenvolvimento Local
80
+
81
+ Se você deseja contribuir ou modificar o código localmente:
82
+
83
+ 1. Clone o repositório.
84
+ 2. Crie e ative um ambiente virtual.
85
+ 3. Instale as dependências e o pacote local no modo editável:
86
+ ```console
87
+ pip install -r requirements.txt
88
+ pip install -e .
89
+ ```
90
+ 4. Ao rodar `python manage.py runserver`, o painel rodará em modo debug local e usará a própria pasta do projeto para salvar os arquivos de desenvolvimento.
91
+
92
+ ### Comandos de Desenvolvimento Úteis
93
+
94
+ * **Formatar código:**
95
+ ```console
96
+ python manage.py format_code
97
+ ```
98
+ * **Gerar nova Secret Key de desenvolvimento:**
99
+ ```console
100
+ python manage.py generate_secret_key
101
+ ```
102
+
103
+ ## Capturas de Tela
104
+
105
+ ![alt text](screenshot.png)
106
+ ![alt text](screenshot2.png)
@@ -0,0 +1,90 @@
1
+ # mcmanager (BETA)
2
+
3
+ Um painel web simples baseado em Django para gerenciar servidores Minecraft diretamente na sua VPS Linux.
4
+
5
+ ## Instalação
6
+
7
+ ### 1. Instalar o Java 8 (Necessário para o Minecraft)
8
+
9
+ ```console
10
+ sudo apt-get update
11
+ sudo apt-get install openjdk-8-jre-headless
12
+ ```
13
+
14
+ ### 2. Instalar o mcmanager do PyPI
15
+
16
+ ```console
17
+ pip install mcmanager
18
+ ```
19
+
20
+ ### 3. Inicializar e rodar o painel
21
+
22
+ ```console
23
+ # Inicializa o banco de dados e cria os diretórios na pasta ~/.mcmanager
24
+ mcmanager init
25
+
26
+ # Cria um usuário administrador
27
+ mcmanager createsuperuser
28
+
29
+ # Inicia o painel
30
+ mcmanager run
31
+ ```
32
+
33
+ Pronto! Acesse `http://sua-vps-ip:8000/admin/` para logar com o superusuário criado e começar a gerenciar seus servidores.
34
+
35
+ ---
36
+
37
+ ## Estrutura de Diretórios e Dados
38
+
39
+ Por padrão, todos os dados do painel ficam armazenados de forma isolada na home do usuário:
40
+ - `~/.mcmanager/db.sqlite3` (Banco de dados do painel)
41
+ - `~/.mcmanager/jar/` (Coloque seus arquivos `.jar` de servidor aqui, ex: `spigot.jar`, `vanilla.jar`)
42
+ - `~/.mcmanager/servers/` (Diretório onde cada servidor criado será executado)
43
+ - `~/.mcmanager/configs/` (Onde fica o `server.properties` padrão)
44
+ - `~/.mcmanager/staticfiles/` (Arquivos estáticos compilados do painel)
45
+
46
+ ### Customizações por Variáveis de Ambiente
47
+
48
+ Você pode ajustar o comportamento do painel definindo variáveis de ambiente antes de executar o comando `mcmanager`:
49
+
50
+ * **`MCMANAGER_DATA_DIR`**: Altera a pasta padrão onde os servidores e banco de dados são salvos (padrão: `~/.mcmanager`).
51
+ * **`MCMANAGER_JAVA_BIN`**: Especifica o caminho binário do Java (padrão: `/usr/lib/jvm/java-8-openjdk-amd64/bin/java`). Use `whereis java` para encontrar o caminho correto na sua VPS.
52
+ * **`MCMANAGER_ALLOWED_HOSTS`**: Lista de hosts permitidos separados por vírgula (padrão: `*`).
53
+ * **`MCMANAGER_DEBUG`**: Define se o painel roda em modo debug (`True` ou `False`).
54
+
55
+ Exemplo definindo um caminho diferente de Java e iniciando:
56
+ ```console
57
+ export MCMANAGER_JAVA_BIN="/usr/bin/java"
58
+ mcmanager run
59
+ ```
60
+
61
+ ---
62
+
63
+ ## Desenvolvimento Local
64
+
65
+ Se você deseja contribuir ou modificar o código localmente:
66
+
67
+ 1. Clone o repositório.
68
+ 2. Crie e ative um ambiente virtual.
69
+ 3. Instale as dependências e o pacote local no modo editável:
70
+ ```console
71
+ pip install -r requirements.txt
72
+ pip install -e .
73
+ ```
74
+ 4. Ao rodar `python manage.py runserver`, o painel rodará em modo debug local e usará a própria pasta do projeto para salvar os arquivos de desenvolvimento.
75
+
76
+ ### Comandos de Desenvolvimento Úteis
77
+
78
+ * **Formatar código:**
79
+ ```console
80
+ python manage.py format_code
81
+ ```
82
+ * **Gerar nova Secret Key de desenvolvimento:**
83
+ ```console
84
+ python manage.py generate_secret_key
85
+ ```
86
+
87
+ ## Capturas de Tela
88
+
89
+ ![alt text](screenshot.png)
90
+ ![alt text](screenshot2.png)
File without changes
@@ -0,0 +1,16 @@
1
+ """
2
+ ASGI config for mcmanager project.
3
+
4
+ It exposes the ASGI callable as a module-level variable named ``application``.
5
+
6
+ For more information on this file, see
7
+ https://docs.djangoproject.com/en/4.0/howto/deployment/asgi/
8
+ """
9
+
10
+ import os
11
+
12
+ from django.core.asgi import get_asgi_application
13
+
14
+ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mcmanager.settings')
15
+
16
+ application = get_asgi_application()
@@ -0,0 +1,115 @@
1
+ import os
2
+ import sys
3
+ import argparse
4
+ import shutil
5
+ from pathlib import Path
6
+
7
+ def get_data_dir():
8
+ """Determina o diretório de dados com base na variável de ambiente ou home"""
9
+ if os.environ.get("MCMANAGER_DATA_DIR"):
10
+ return Path(os.environ["MCMANAGER_DATA_DIR"]).resolve()
11
+
12
+ debug_mode = os.environ.get("MCMANAGER_DEBUG", "False").lower() in ("true", "1", "yes")
13
+ if debug_mode:
14
+ # Se estiver em modo debug local, usa a pasta do próprio projeto
15
+ return Path(__file__).resolve().parent.parent
16
+ else:
17
+ return Path.home() / ".mcmanager"
18
+
19
+ def main():
20
+ parser = argparse.ArgumentParser(
21
+ description="mcmanager - Painel de Controle de Servidores Minecraft"
22
+ )
23
+ subparsers = parser.add_subparsers(dest="command", required=True, help="Subcomando a executar")
24
+
25
+ # Comando init
26
+ init_parser = subparsers.add_parser("init", help="Inicializa o diretório de dados, banco e arquivos padrões")
27
+
28
+ # Comando run
29
+ run_parser = subparsers.add_parser("run", help="Inicia o servidor web do painel")
30
+ run_parser.add_argument("--host", default="0.0.0.0", help="Endereço IP para escutar (padrão: 0.0.0.0)")
31
+ run_parser.add_argument("--port", type=int, default=8000, help="Porta para escutar (padrão: 8000)")
32
+
33
+ # Comando createsuperuser
34
+ createsuperuser_parser = subparsers.add_parser(
35
+ "createsuperuser", help="Cria um usuário administrador para o painel"
36
+ )
37
+
38
+ # Comando shell
39
+ shell_parser = subparsers.add_parser("shell", help="Inicia o console interativo do Django")
40
+
41
+ args = parser.parse_args()
42
+
43
+ # 1. Obter e criar estrutura de dados do usuário
44
+ data_dir = get_data_dir()
45
+ data_dir.mkdir(parents=True, exist_ok=True)
46
+ (data_dir / "servers").mkdir(exist_ok=True)
47
+ (data_dir / "jar").mkdir(exist_ok=True)
48
+ (data_dir / "configs").mkdir(exist_ok=True)
49
+
50
+ # 2. Copiar server.properties padrão se não existir
51
+ properties_dest = data_dir / "configs" / "server.properties"
52
+ if not properties_dest.exists():
53
+ # Tenta carregar usando importlib.resources (PEP 517)
54
+ copied = False
55
+ try:
56
+ from importlib import resources
57
+ # Python 3.9+
58
+ source_path = resources.files("mcmanager").joinpath("configs/server.properties")
59
+ with source_path.open("rb") as fsrc:
60
+ with open(properties_dest, "wb") as fdst:
61
+ shutil.copyfileobj(fsrc, fdst)
62
+ copied = True
63
+ except Exception:
64
+ pass
65
+
66
+ if not copied:
67
+ # Fallback para caminho relativo
68
+ source_path = Path(__file__).resolve().parent / "configs" / "server.properties"
69
+ if source_path.exists():
70
+ shutil.copy(source_path, properties_dest)
71
+ copied = True
72
+
73
+ if copied:
74
+ print(f"[*] Arquivo server.properties padrão copiado para: {properties_dest}")
75
+ else:
76
+ print("[!] Aviso: Não foi possível copiar o arquivo server.properties padrão.")
77
+
78
+ # 3. Configurar variáveis de ambiente do Django
79
+ os.environ.setdefault("MCMANAGER_DATA_DIR", str(data_dir))
80
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mcmanager.settings")
81
+
82
+ # 4. Inicializar Django
83
+ import django
84
+ django.setup()
85
+
86
+ from django.core.management import call_command
87
+
88
+ # 5. Executar os subcomandos
89
+ if args.command == "init":
90
+ print("[*] Executando migrações do banco de dados...")
91
+ call_command("migrate", interactive=False)
92
+ print("[*] Coletando arquivos estáticos...")
93
+ call_command("collectstatic", "--noinput", "--clear")
94
+ print("\n[+] Inicialização concluída com sucesso!")
95
+ print(f"[+] Seus dados estão em: {data_dir}")
96
+ print("[+] Agora você pode rodar: mcmanager createsuperuser")
97
+
98
+ elif args.command == "run":
99
+ bind_address = f"{args.host}:{args.port}"
100
+ print(f"[*] Iniciando servidor mcmanager em http://{bind_address}/")
101
+ print("[*] Pressione CTRL+C para encerrar.")
102
+ # Em produção, rodamos sem autoreload
103
+ call_command("runserver", "--noreload", "--nostatic", bind_address)
104
+
105
+ elif args.command == "createsuperuser":
106
+ try:
107
+ call_command("createsuperuser")
108
+ except KeyboardInterrupt:
109
+ print("\n[!] Operação cancelada.")
110
+
111
+ elif args.command == "shell":
112
+ call_command("shell")
113
+
114
+ if __name__ == "__main__":
115
+ main()
@@ -0,0 +1,33 @@
1
+ #Minecraft server properties
2
+ #Wed Jul 10 19:30:06 UTC 2024
3
+ generator-settings=
4
+ op-permission-level=4
5
+ allow-nether=true
6
+ level-name=world
7
+ enable-query=false
8
+ allow-flight=true
9
+ announce-player-achievements=true
10
+ server-port=25566
11
+ level-type=DEFAULT
12
+ enable-rcon=false
13
+ force-gamemode=false
14
+ level-seed=
15
+ server-ip=
16
+ max-build-height=256
17
+ spawn-npcs=true
18
+ white-list=false
19
+ spawn-animals=true
20
+ hardcore=false
21
+ snooper-enabled=true
22
+ online-mode=false
23
+ resource-pack=
24
+ pvp=true
25
+ difficulty=1
26
+ enable-command-block=false
27
+ gamemode=0
28
+ player-idle-timeout=0
29
+ max-players=5
30
+ spawn-monsters=true
31
+ generate-structures=true
32
+ view-distance=10
33
+ motd=A Minecraft Server
File without changes
@@ -0,0 +1,29 @@
1
+ from typing import Any
2
+ from django.contrib import admin
3
+ from django.http import HttpRequest
4
+ from django.http.response import HttpResponse
5
+ from .models import Server, Type
6
+
7
+
8
+ @admin.register(Server)
9
+ class ServerAdmin(admin.ModelAdmin):
10
+ list_display = ('name', 'port', 'type', 'status')
11
+ exclude = ('jar', 'server_properties')
12
+ search_fields = ('name', 'port', 'type')
13
+ list_filter = ('type', 'status')
14
+ readonly_fields = ('status',)
15
+
16
+ def get_form(self, request, obj=..., change=..., **kwargs) -> Any:
17
+ if obj is None:
18
+ self.exclude = ('jar', 'server_properties')
19
+ self.readonly_fields = ('status',)
20
+ else:
21
+ self.exclude = None
22
+ self.readonly_fields = ('status', 'jar')
23
+ return super().get_form(request, obj, change, **kwargs)
24
+
25
+
26
+ @admin.register(Type)
27
+ class TypeAdmin(admin.ModelAdmin):
28
+ list_display = ('name',)
29
+ search_fields = ('name',)
@@ -0,0 +1,22 @@
1
+ from django.apps import AppConfig
2
+
3
+
4
+ class ConsoleConfig(AppConfig):
5
+ default_auto_field = 'django.db.models.BigAutoField'
6
+ name = 'mcmanager.console'
7
+
8
+ def ready(self) -> None:
9
+ try:
10
+ print('Checking server status...')
11
+ from .views import is_server_running
12
+ from .models import Server
13
+ for server in Server.objects.all():
14
+ if is_server_running(server.id):
15
+ server.status = True
16
+ server.save()
17
+ else:
18
+ server.status = False
19
+ server.save()
20
+ print('Server status checked!')
21
+ except Exception as e:
22
+ print(e)
@@ -0,0 +1,112 @@
1
+ import uuid
2
+ import os
3
+ import shutil
4
+ from django.db import models
5
+ from django.conf import settings
6
+ from django.dispatch import receiver
7
+ from django.db.models.signals import post_save, pre_save, pre_delete
8
+
9
+
10
+ def get_jar_files():
11
+ jar_dir = getattr(settings, 'JAR_DIR', os.path.join(settings.BASE_DIR, 'jar'))
12
+ if not os.path.exists(jar_dir):
13
+ os.makedirs(jar_dir)
14
+ return [(x, x) for x in os.listdir(jar_dir) if x.endswith('.jar')]
15
+
16
+
17
+ def get_default_server_prop():
18
+ configs_dir = getattr(settings, 'CONFIGS_DIR', os.path.join(settings.BASE_DIR, 'configs'))
19
+ with open(os.path.join(configs_dir, 'server.properties'), 'r', encoding='utf-8') as arq:
20
+ text = arq.read()
21
+ return text
22
+
23
+
24
+ class Type(models.Model):
25
+ name = models.CharField(max_length=100)
26
+ dependencies = models.JSONField(blank=True, null=True)
27
+ created_at = models.DateTimeField(auto_now_add=True)
28
+ updated_at = models.DateTimeField(auto_now=True)
29
+
30
+ def __str__(self):
31
+ return self.name
32
+
33
+
34
+ class Server(models.Model):
35
+ name = models.CharField(max_length=100)
36
+ jar_template = models.CharField(max_length=100, choices=get_jar_files())
37
+ jar = models.CharField(max_length=100, blank=True, null=True)
38
+ # ip = models.GenericIPAddressField(blank=True, null=True)
39
+ port = models.IntegerField(default=25565)
40
+ memory_limit = models.IntegerField("Memory Limit (MB)", default=1024)
41
+ created_at = models.DateTimeField(auto_now_add=True)
42
+ updated_at = models.DateTimeField(auto_now=True)
43
+ type = models.ForeignKey(
44
+ Type, on_delete=models.CASCADE, related_name='servers')
45
+ status = models.BooleanField(default=False)
46
+ server_properties = models.TextField(blank=True, null=True)
47
+
48
+ def __str__(self):
49
+ return self.name
50
+
51
+
52
+ @receiver(pre_delete, sender=Server)
53
+ def pre_delete_server(sender, instance, **kwargs):
54
+ servers_dir = getattr(settings, 'SERVERS_DIR', os.path.join(settings.BASE_DIR, 'servers'))
55
+ server_path = os.path.join(servers_dir, f'server_{instance.id}')
56
+ if os.path.exists(server_path):
57
+ shutil.rmtree(server_path)
58
+
59
+
60
+ pre_delete.connect(pre_delete_server, sender=Server)
61
+
62
+
63
+ @receiver(post_save, sender=Server)
64
+ def post_save_server(sender, instance, **kwargs):
65
+ servers_dir = getattr(settings, 'SERVERS_DIR', os.path.join(settings.BASE_DIR, 'servers'))
66
+ jar_dir = getattr(settings, 'JAR_DIR', os.path.join(settings.BASE_DIR, 'jar'))
67
+ configs_dir = getattr(settings, 'CONFIGS_DIR', os.path.join(settings.BASE_DIR, 'configs'))
68
+
69
+ server_path = os.path.join(servers_dir, f'server_{instance.id}')
70
+ properties_path = os.path.join(server_path, 'server.properties')
71
+
72
+ if not instance.jar:
73
+ instance.jar = str(instance.id) + "_" + instance.jar_template
74
+ os.makedirs(server_path, exist_ok=True)
75
+ shutil.copy(os.path.join(jar_dir, instance.jar_template), os.path.join(server_path, instance.jar))
76
+ shutil.copy(os.path.join(configs_dir, 'server.properties'), properties_path)
77
+
78
+ if instance.type.dependencies:
79
+ for dependency in instance.type.dependencies:
80
+ dep_source = os.path.join(jar_dir, dependency)
81
+ dep_dest = os.path.join(server_path, dependency)
82
+ if os.path.isdir(dep_source):
83
+ shutil.copytree(dep_source, dep_dest)
84
+ else:
85
+ shutil.copy(dep_source, dep_dest)
86
+
87
+ with open(os.path.join(server_path, 'eula.txt'), 'w', encoding='utf-8') as f:
88
+ f.write('eula=true')
89
+
90
+ new_server_properties = []
91
+ with open(properties_path, 'r', encoding='utf-8', errors='ignore') as f:
92
+ for line in f:
93
+ if line.startswith('server-port='):
94
+ new_server_properties.append(f'server-port={instance.port}\n')
95
+ else:
96
+ new_server_properties.append(line)
97
+
98
+ with open(properties_path, 'w', encoding='utf-8') as f:
99
+ f.write(''.join(new_server_properties))
100
+
101
+ with open(properties_path, 'r', encoding='utf-8', errors='ignore') as f:
102
+ text = f.read()
103
+
104
+ instance.server_properties = text
105
+ instance.save()
106
+ else:
107
+ with open(properties_path, 'w', encoding='utf-8') as f:
108
+ f.write(instance.server_properties)
109
+
110
+
111
+ post_save.connect(post_save_server, sender=Server)
112
+