wip modding (4): event api, logger, example in Modding.md

This commit is contained in:
Bixilon 2020-09-27 19:26:42 +02:00
parent 5e2ac9646d
commit 30cbabe1c8
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
12 changed files with 335 additions and 15 deletions

View File

@ -68,4 +68,57 @@ There are different phases (states) for the loading. There are the following pha
The most important thing is performance. To archive fast loading times, etc, all mods (if they don't on each other) are getting loaded async.
One phase is completed (= Next phase starts), once all mods have completed the previous phase. Everything is async.
If your start function needs much time, you can set the loading priority in the `mod.json` to start at the beginning. The `start` method returns a success boolean.
If your start function needs much time, you can set the loading priority in the `mod.json` to start at the beginning. The `start` method returns a success boolean.
## Getting started
Add Minosoft to your maven dependencies with
Repository:
```xml
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
```
Dependency:
```xml
<dependency>
<groupId>de.bixilon.gitlab.bixilon</groupId>
<artifactId>minosoft</artifactId>
<version>master-SNAPSHOT</version>
</dependency>
```
Create a Main class, here is an example
```java
package de.bixilon.example.mod.main;
import de.bixilon.minosoft.modding.MinosoftMod;
import de.bixilon.minosoft.modding.loading.ModPhases;
public class TestMod extends MinosoftMod {
public boolean start(ModPhases phase) {
if (phase == ModPhases.BOOTING) {
getLogger().info("Hello world!");
}
return true;
}
}
```
Your `mod.json` can look like this
```json
{
"uuid": "1f37a8e0-9ec7-45db-ad2f-40afd2eb5a07",
"versionId": 1,
"versionName": "1.0",
"authors": ["Bixilon"],
"name": "Example Mod",
"identifier": "example",
"mainClass": "de.bixilon.example.mod.main.TestMod"
}
```
## Events
There are global events (which works on all connections) and connections events (server specific).

View File

@ -25,8 +25,8 @@ public class Log {
static LogLevels level = LogLevels.PROTOCOL;
static Thread logThread;
public static void log(LogLevels l, String message, TextComponent.ChatAttributes color) {
if (l.ordinal() > level.ordinal()) {
public static void log(LogLevels level, String message, TextComponent.ChatAttributes color) {
if (level.ordinal() > Log.level.ordinal()) {
// log level too low
return;
}
@ -36,7 +36,7 @@ public class Log {
builder.append("] [");
builder.append(Thread.currentThread().getName());
builder.append("] [");
builder.append(l.name());
builder.append(level.name());
builder.append("] ");
if (color != null && Config.colorLog) {
builder.append(color);

View File

@ -0,0 +1,93 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.modding;
import de.bixilon.minosoft.game.datatypes.TextComponent;
import de.bixilon.minosoft.logging.Log;
import de.bixilon.minosoft.logging.LogLevels;
public class Logger {
private final String modName;
public Logger(String modName) {
this.modName = modName;
}
public void log(LogLevels level, String message, TextComponent.ChatAttributes color) {
Log.log(level, String.format("[%s] %s", modName, message), color);
}
/**
* Logs all game related things (chunk loading, rendering, ...)
*
* @param message Raw message to log
*/
public void game(String message) {
log(LogLevels.GAME, message, TextComponent.ChatAttributes.GREEN);
}
/**
* Logs all fatal errors (critical exceptions, etc)
*
* @param message Raw message to log
*/
public void fatal(String message) {
log(LogLevels.FATAL, message, TextComponent.ChatAttributes.DARK_RED);
}
/**
* Logs all general infos (connecting to server, ...)
*
* @param message Raw message to log
*/
public void info(String message) {
log(LogLevels.INFO, message, TextComponent.ChatAttributes.WHITE);
}
/**
* Logs all warnings (connection to server failed, ...)
*
* @param message Raw message to log
*/
public void warn(String message) {
log(LogLevels.WARNING, message, TextComponent.ChatAttributes.RED);
}
/**
* Logs all debug relevant infos (...)
*
* @param message Raw message to log
*/
public void debug(String message) {
log(LogLevels.DEBUG, message, TextComponent.ChatAttributes.GRAY);
}
/**
* Logs all debug relevant infos (even higher level!) (connection status, ...)
*
* @param message Raw message to log
*/
public void verbose(String message) {
log(LogLevels.VERBOSE, message, TextComponent.ChatAttributes.YELLOW);
}
/**
* Logs all protocol data (received protocol with length and command x,...)
*
* @param message Raw message to log
*/
public void protocol(String message) {
log(LogLevels.PROTOCOL, message, TextComponent.ChatAttributes.BLUE);
}
}

View File

@ -13,11 +13,43 @@
package de.bixilon.minosoft.modding;
import de.bixilon.minosoft.modding.loading.ModInfo;
import de.bixilon.minosoft.modding.loading.ModPhases;
interface MinosoftModInterface {
/**
* @param phase The current loading phase
* @return If the loading was successful. If not, the mod is getting disabled.
*/
boolean start(ModPhases phase);
}
public abstract class MinosoftMod implements MinosoftModInterface {
protected boolean enabled = false;
private ModInfo info;
private Logger logger;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public ModInfo getInfo() {
return info;
}
public void setInfo(ModInfo info) {
if (this.info != null) {
throw new RuntimeException(String.format("Mod info already set %s vs %s", this.info, info));
}
this.info = info;
this.logger = new Logger(info.getName());
}
public Logger getLogger() {
return logger;
}
}

View File

@ -0,0 +1,22 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.modding.event;
import de.bixilon.minosoft.modding.event.events.ChatMessageReceivingEvent;
public class EventListener {
public void onChatMessageReceiving(ChatMessageReceivingEvent event) {
}
}

View File

@ -0,0 +1,47 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.modding.event.events;
import de.bixilon.minosoft.game.datatypes.ChatTextPositions;
import de.bixilon.minosoft.game.datatypes.TextComponent;
import java.util.UUID;
public class ChatMessageReceivingEvent extends Event {
private final TextComponent message;
private final ChatTextPositions position;
private final UUID sender;
public ChatMessageReceivingEvent(TextComponent message, ChatTextPositions position, UUID sender) {
this.message = message;
this.position = position;
this.sender = sender;
}
public TextComponent getMessage() {
return message;
}
public ChatTextPositions getPosition() {
return position;
}
/**
* @return The uuid of the sender
*/
@MinimumProtocolVersion(protocolId = 718)
public UUID getSender() {
return this.sender;
}
}

View File

@ -0,0 +1,29 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.modding.event.events;
public class Event {
boolean cancelled = false;
protected Event() {
}
public boolean isCancelled() {
return cancelled;
}
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
}

View File

@ -0,0 +1,18 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.modding.event.events;
public @interface MaximumProtocolVersion {
int protocolId() default Integer.MAX_VALUE;
}

View File

@ -0,0 +1,18 @@
/*
* Codename Minosoft
* Copyright (C) 2020 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.modding.event.events;
public @interface MinimumProtocolVersion {
int protocolId() default 0;
}

View File

@ -28,8 +28,6 @@ import java.util.zip.ZipFile;
public class ModLoader {
static TreeMap<ModInfo, MinosoftMod> modMap;
ModPhases currentPhase;
public static void loadMods() {
modMap = new TreeMap<>((a, b) -> {
LoadingPriorities priorityA = getLoadingPriorityOrDefault(a);
@ -61,6 +59,7 @@ public class ModLoader {
JclObjectFactory factory = JclObjectFactory.getInstance();
MinosoftMod instance = (MinosoftMod) factory.create(jcl, modInfo.getMainClass());
instance.setInfo(modInfo);
Log.verbose(String.format("[MOD] Mod file loaded (%s)", modInfo));
modMap.put(modInfo, instance);
zipFile.close();

View File

@ -29,20 +29,15 @@ public class PacketChatMessageReceiving implements ClientboundPacket {
@Override
public boolean read(InByteBuffer buffer) {
message = buffer.readTextComponent();
if (buffer.getProtocolId() < 7) {
message = buffer.readTextComponent();
position = ChatTextPositions.CHAT_BOX;
return true;
}
if (buffer.getProtocolId() < 718) {
message = buffer.readTextComponent();
position = ChatTextPositions.byId(buffer.readByte());
return true;
}
message = buffer.readTextComponent();
position = ChatTextPositions.byId(buffer.readByte());
sender = buffer.readUUID();
if (buffer.getProtocolId() >= 718) {
sender = buffer.readUUID();
}
return true;
}

View File

@ -34,4 +34,18 @@ public class ServerAddress {
public String toString() {
return getHostname() + ":" + getPort();
}
@Override
public int hashCode() {
return hostname.hashCode() * port;
}
@Override
public boolean equals(Object obj) {
if (super.equals(obj)) {
return true;
}
ServerAddress their = (ServerAddress) obj;
return hostname.equals(their.getHostname()) && port == their.getPort();
}
}