new file: .gitignore

new file:   README.md
	new file:   database/schema.sql
	new file:   paper-plugin/pom.xml
	new file:   paper-plugin/src/main/java/de/simolzimol/mclogger/paper/PaperLoggerPlugin.java
	new file:   paper-plugin/src/main/java/de/simolzimol/mclogger/paper/commands/MCLoggerCommand.java
	new file:   paper-plugin/src/main/java/de/simolzimol/mclogger/paper/database/DatabaseManager.java
	new file:   paper-plugin/src/main/java/de/simolzimol/mclogger/paper/listeners/BlockListener.java
	new file:   paper-plugin/src/main/java/de/simolzimol/mclogger/paper/listeners/EntityListener.java
	new file:   paper-plugin/src/main/java/de/simolzimol/mclogger/paper/listeners/InventoryListener.java
	new file:   paper-plugin/src/main/java/de/simolzimol/mclogger/paper/listeners/LuckPermsListener.java
	new file:   paper-plugin/src/main/java/de/simolzimol/mclogger/paper/listeners/PlayerChatCommandListener.java
	new file:   paper-plugin/src/main/java/de/simolzimol/mclogger/paper/listeners/PlayerDeathListener.java
	new file:   paper-plugin/src/main/java/de/simolzimol/mclogger/paper/listeners/PlayerMiscListener.java
	new file:   paper-plugin/src/main/java/de/simolzimol/mclogger/paper/listeners/PlayerSessionListener.java
	new file:   paper-plugin/src/main/java/de/simolzimol/mclogger/paper/listeners/WorldListener.java
	new file:   paper-plugin/src/main/resources/config.yml
	new file:   paper-plugin/src/main/resources/plugin.yml
	new file:   paper-plugin/target/classes/config.yml
	new file:   paper-plugin/target/classes/de/simolzimol/mclogger/paper/PaperLoggerPlugin.class
	new file:   paper-plugin/target/classes/de/simolzimol/mclogger/paper/commands/MCLoggerCommand$RsConsumer.class
	new file:   paper-plugin/target/classes/de/simolzimol/mclogger/paper/commands/MCLoggerCommand.class
	new file:   paper-plugin/target/classes/de/simolzimol/mclogger/paper/database/DatabaseManager$ThrowingRunnable.class
	new file:   paper-plugin/target/classes/de/simolzimol/mclogger/paper/database/DatabaseManager.class
	new file:   paper-plugin/target/classes/de/simolzimol/mclogger/paper/listeners/BlockListener.class
	new file:   paper-plugin/target/classes/de/simolzimol/mclogger/paper/listeners/EntityListener.class
	new file:   paper-plugin/target/classes/de/simolzimol/mclogger/paper/listeners/InventoryListener.class
	new file:   paper-plugin/target/classes/de/simolzimol/mclogger/paper/listeners/LuckPermsListener.class
	new file:   paper-plugin/target/classes/de/simolzimol/mclogger/paper/listeners/PlayerChatCommandListener.class
	new file:   paper-plugin/target/classes/de/simolzimol/mclogger/paper/listeners/PlayerDeathListener.class
	new file:   paper-plugin/target/classes/de/simolzimol/mclogger/paper/listeners/PlayerMiscListener.class
	new file:   paper-plugin/target/classes/de/simolzimol/mclogger/paper/listeners/PlayerSessionListener.class
	new file:   paper-plugin/target/classes/de/simolzimol/mclogger/paper/listeners/WorldListener.class
	new file:   paper-plugin/target/classes/plugin.yml
	new file:   paper-plugin/target/maven-archiver/pom.properties
	new file:   paper-plugin/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
	new file:   paper-plugin/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
	new file:   paper-plugin/target/mclogger-paper-1.0.0.jar
	new file:   paper-plugin/target/original-mclogger-paper-1.0.0.jar
	new file:   velocity-plugin/pom.xml
	new file:   velocity-plugin/src/main/java/de/simolzimol/mclogger/velocity/VelocityLoggerPlugin.java
	new file:   velocity-plugin/src/main/java/de/simolzimol/mclogger/velocity/database/VelocityDatabaseManager.java
	new file:   velocity-plugin/src/main/java/de/simolzimol/mclogger/velocity/listeners/VelocityEventListener.java
	new file:   velocity-plugin/src/main/resources/velocity-config.yml
	new file:   velocity-plugin/target/classes/de/simolzimol/mclogger/velocity/VelocityLoggerPlugin.class
	new file:   velocity-plugin/target/classes/de/simolzimol/mclogger/velocity/database/VelocityDatabaseManager$ThrowingRunnable.class
	new file:   velocity-plugin/target/classes/de/simolzimol/mclogger/velocity/database/VelocityDatabaseManager.class
	new file:   velocity-plugin/target/classes/de/simolzimol/mclogger/velocity/listeners/VelocityEventListener.class
	new file:   velocity-plugin/target/classes/velocity-config.yml
	new file:   velocity-plugin/target/classes/velocity-plugin.json
	new file:   velocity-plugin/target/maven-archiver/pom.properties
	new file:   velocity-plugin/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
	new file:   velocity-plugin/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
	new file:   velocity-plugin/target/mclogger-velocity-1.0.0.jar
	new file:   velocity-plugin/target/original-mclogger-velocity-1.0.0.jar
	new file:   web/Dockerfile
	new file:   web/app.py
	new file:   web/blueprints/__init__.py
	new file:   web/blueprints/auth.py
	new file:   web/blueprints/group_admin.py
	new file:   web/blueprints/panel.py
	new file:   web/blueprints/site_admin.py
	new file:   web/config.py
	new file:   web/crypto.py
	new file:   web/docker-compose.yml
	new file:   web/panel_db.py
	new file:   web/requirements.txt
	new file:   web/static/css/style.css
	new file:   web/static/js/main.js
	new file:   web/templates/_pagination.html
	new file:   web/templates/admin/base.html
	new file:   web/templates/admin/dashboard.html
	new file:   web/templates/admin/group_edit.html
	new file:   web/templates/admin/group_members.html
	new file:   web/templates/admin/groups.html
	new file:   web/templates/admin/user_edit.html
	new file:   web/templates/admin/users.html
	new file:   web/templates/auth/admin_login.html
	new file:   web/templates/auth/login.html
	new file:   web/templates/base.html
	new file:   web/templates/blocks.html
	new file:   web/templates/chat.html
	new file:   web/templates/commands.html
	new file:   web/templates/dashboard.html
	new file:   web/templates/deaths.html
	new file:   web/templates/group_admin/base.html
	new file:   web/templates/group_admin/dashboard.html
	new file:   web/templates/group_admin/database.html
	new file:   web/templates/group_admin/member_edit.html
	new file:   web/templates/group_admin/members.html
	new file:   web/templates/login.html
	new file:   web/templates/panel/blocks.html
	new file:   web/templates/panel/chat.html
	new file:   web/templates/panel/commands.html
	new file:   web/templates/panel/dashboard.html
	new file:   web/templates/panel/deaths.html
	new file:   web/templates/panel/no_db.html
	new file:   web/templates/panel/perms.html
	new file:   web/templates/panel/player_detail.html
	new file:   web/templates/panel/players.html
	new file:   web/templates/panel/proxy.html
	new file:   web/templates/panel/server_events.html
	new file:   web/templates/panel/sessions.html
	new file:   web/templates/perms.html
	new file:   web/templates/player_detail.html
	new file:   web/templates/players.html
	new file:   web/templates/proxy.html
	new file:   web/templates/server_events.html
	new file:   web/templates/sessions.html
This commit is contained in:
SimolZimol
2026-04-01 01:36:01 +02:00
commit b918dadb0c
109 changed files with 9196 additions and 0 deletions

View File

@@ -0,0 +1,182 @@
{% extends "base.html" %}
{% block title %}{{ player.username }}{% endblock %}
{% block page_title %}<i class="bi bi-person-fill me-2"></i>{{ player.username }}{% endblock %}
{% block content %}
<!-- Spieler-Info Karte -->
<div class="row g-3 mb-4">
<div class="col-12 col-md-4">
<div class="card h-100">
<div class="card-body text-center py-4">
<img src="https://minotar.net/avatar/{{ player.username }}/80"
class="rounded mb-3" alt="{{ player.username }}" onerror="this.src='/static/img/default.png'">
<h5 class="fw-bold mb-1">{{ player.username }}</h5>
{% if player.is_op %}
<span class="badge bg-warning text-dark mb-2"><i class="bi bi-shield-fill"></i> OP</span>
{% endif %}
<table class="table table-sm mt-2 text-start">
<tr><th>UUID</th><td class="small text-break">{{ player.uuid }}</td></tr>
<tr><th>IP</th><td class="small">{{ player.ip_address or '—' }}</td></tr>
<tr><th>Locale</th><td class="small">{{ player.locale or '—' }}</td></tr>
<tr><th>Playtime</th><td>{{ player.total_playtime_sec | fmt_duration }}</td></tr>
<tr><th>Since</th><td class="small">{{ player.first_seen | fmt_dt }}</td></tr>
<tr><th>Last Seen</th><td class="small">{{ player.last_seen | fmt_dt }}</td></tr>
</table>
</div>
</div>
</div>
<div class="col-12 col-md-8">
<!-- Tabs -->
<ul class="nav nav-tabs mb-3" id="playerTabs">
<li class="nav-item"><a class="nav-link active" data-bs-toggle="tab" href="#tab-sessions">Sessions ({{ sessions|length }})</a></li>
<li class="nav-item"><a class="nav-link" data-bs-toggle="tab" href="#tab-chat">Chat ({{ chat|length }})</a></li>
<li class="nav-item"><a class="nav-link" data-bs-toggle="tab" href="#tab-cmds">Commands ({{ commands|length }})</a></li>
<li class="nav-item"><a class="nav-link" data-bs-toggle="tab" href="#tab-deaths">Deaths ({{ deaths|length }})</a></li>
<li class="nav-item"><a class="nav-link" data-bs-toggle="tab" href="#tab-tp">Teleports ({{ teleports|length }})</a></li>
<li class="nav-item"><a class="nav-link" data-bs-toggle="tab" href="#tab-stats">Stats ({{ stats|length }})</a></li>
<li class="nav-item"><a class="nav-link" data-bs-toggle="tab" href="#tab-proxy">Proxy ({{ proxy_events|length }})</a></li>
</ul>
<div class="tab-content">
<!-- Sessions -->
<div class="tab-pane fade show active" id="tab-sessions">
<div class="table-responsive" style="max-height:400px; overflow-y:auto;">
<table class="table table-sm table-hover">
<thead class="table-dark sticky-top"><tr><th>Login</th><th>Logout</th><th>Duration</th><th>Server</th><th>IP</th></tr></thead>
<tbody>
{% for s in sessions %}
<tr>
<td class="small text-nowrap">{{ s.login_time | fmt_dt }}</td>
<td class="small text-nowrap">{{ s.logout_time | fmt_dt }}</td>
<td class="small">{{ s.duration_sec | fmt_duration }}</td>
<td><span class="badge bg-secondary">{{ s.server_name or '—' }}</span></td>
<td class="small text-muted">{{ s.ip_address or '—' }}</td>
</tr>
{% else %}<tr><td colspan="5" class="text-center text-muted">No sessions</td></tr>{% endfor %}
</tbody>
</table>
</div>
</div>
<!-- Chat -->
<div class="tab-pane fade" id="tab-chat">
<div class="table-responsive" style="max-height:400px; overflow-y:auto;">
<table class="table table-sm table-hover">
<thead class="table-dark sticky-top"><tr><th>Time</th><th>Server</th><th>Message</th></tr></thead>
<tbody>
{% for c in chat %}
<tr>
<td class="small text-nowrap text-muted">{{ c.timestamp | fmt_dt }}</td>
<td><span class="badge bg-secondary">{{ c.server_name or '—' }}</span></td>
<td class="small">{{ c.message }}</td>
</tr>
{% else %}<tr><td colspan="3" class="text-center text-muted">No chat messages</td></tr>{% endfor %}
</tbody>
</table>
</div>
</div>
<!-- Commands -->
<div class="tab-pane fade" id="tab-cmds">
<div class="table-responsive" style="max-height:400px; overflow-y:auto;">
<table class="table table-sm table-hover">
<thead class="table-dark sticky-top"><tr><th>Time</th><th>Server</th><th>Command</th><th>Position</th></tr></thead>
<tbody>
{% for c in commands %}
<tr>
<td class="small text-nowrap text-muted">{{ c.timestamp | fmt_dt }}</td>
<td><span class="badge bg-secondary">{{ c.server_name or '—' }}</span></td>
<td class="small font-monospace">{{ c.command }}</td>
<td class="small text-muted">{{ c.world or '' }} {% if c.x %}({{ c.x|round(1) }}, {{ c.y|round(1) }}, {{ c.z|round(1) }}){% endif %}</td>
</tr>
{% else %}<tr><td colspan="4" class="text-center text-muted">No commands</td></tr>{% endfor %}
</tbody>
</table>
</div>
</div>
<!-- Tode -->
<div class="tab-pane fade" id="tab-deaths">
<div class="table-responsive" style="max-height:400px; overflow-y:auto;">
<table class="table table-sm table-hover">
<thead class="table-dark sticky-top"><tr><th>Time</th><th>Cause</th><th>Killer</th><th>Level</th><th>World</th></tr></thead>
<tbody>
{% for d in deaths %}
<tr>
<td class="small text-nowrap text-muted">{{ d.timestamp | fmt_dt }}</td>
<td><span class="badge bg-danger">{{ d.cause or '—' }}</span></td>
<td class="small">{{ d.killer_name or '—' }}</td>
<td class="small">{{ d.exp_level }}</td>
<td class="small text-muted">{{ d.world }}</td>
</tr>
{% else %}<tr><td colspan="5" class="text-center text-muted">No deaths</td></tr>{% endfor %}
</tbody>
</table>
</div>
</div>
<!-- Teleports -->
<div class="tab-pane fade" id="tab-tp">
<div class="table-responsive" style="max-height:400px; overflow-y:auto;">
<table class="table table-sm table-hover">
<thead class="table-dark sticky-top"><tr><th>Time</th><th>From</th><th>To</th><th>Cause</th></tr></thead>
<tbody>
{% for t in teleports %}
<tr>
<td class="small text-nowrap text-muted">{{ t.timestamp | fmt_dt }}</td>
<td class="small">{{ t.from_world }} ({{ t.from_x|round(0)|int }}, {{ t.from_y|round(0)|int }}, {{ t.from_z|round(0)|int }})</td>
<td class="small">{{ t.to_world }} ({{ t.to_x|round(0)|int }}, {{ t.to_y|round(0)|int }}, {{ t.to_z|round(0)|int }})</td>
<td><span class="badge bg-info text-dark">{{ t.cause or '—' }}</span></td>
</tr>
{% else %}<tr><td colspan="4" class="text-center text-muted">No teleports</td></tr>{% endfor %}
</tbody>
</table>
</div>
</div>
<!-- Stats -->
<div class="tab-pane fade" id="tab-stats">
<div class="table-responsive" style="max-height:400px; overflow-y:auto;">
<table class="table table-sm table-hover">
<thead class="table-dark sticky-top"><tr><th>Time</th><th>Type</th><th>Old</th><th>New</th></tr></thead>
<tbody>
{% for s in stats %}
<tr>
<td class="small text-nowrap text-muted">{{ s.timestamp | fmt_dt }}</td>
<td><span class="badge bg-secondary">{{ s.event_type }}</span></td>
<td class="small">{{ s.old_value or '—' }}</td>
<td class="small">{{ s.new_value or '—' }}</td>
</tr>
{% else %}<tr><td colspan="4" class="text-center text-muted">No stats</td></tr>{% endfor %}
</tbody>
</table>
</div>
</div>
<!-- Proxy-Events -->
<div class="tab-pane fade" id="tab-proxy">
<div class="table-responsive" style="max-height:400px; overflow-y:auto;">
<table class="table table-sm table-hover">
<thead class="table-dark sticky-top"><tr><th>Time</th><th>Type</th><th>From</th><th>To</th></tr></thead>
<tbody>
{% for e in proxy_events %}
<tr>
<td class="small text-nowrap text-muted">{{ e.timestamp | fmt_dt }}</td>
<td><span class="badge bg-primary">{{ e.event_type }}</span></td>
<td class="small">{{ e.from_server or '—' }}</td>
<td class="small">{{ e.to_server or '—' }}</td>
</tr>
{% else %}<tr><td colspan="4" class="text-center text-muted">No proxy events</td></tr>{% endfor %}
</tbody>
</table>
</div>
</div>
</div><!-- /tab-content -->
</div>
</div>
<a href="{{ url_for('players') }}" class="btn btn-outline-secondary">
<i class="bi bi-arrow-left me-1"></i>Back to Overview
</a>
{% endblock %}