rewrite to a more platformized structure.
This commit is contained in:
parent
54a730754f
commit
3091083821
20 changed files with 888 additions and 34 deletions
|
@ -5,11 +5,20 @@
|
|||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="9d5d9b6f-43c8-41a4-bb42-a66ffc96c9b0" name="Changes" comment="">
|
||||
<change afterPath="$PROJECT_DIR$/src/main/java/me/tofaa/entitylib/EntityLibPlatform.java" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/main/java/me/tofaa/entitylib/WrapperWorld.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/gradle.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/gradle.xml" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/EntityLib.java" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/EntityLibAPI.java" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/Platform.java" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/WorldWrapper.java" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/event/EntityLibEvent.java" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/event/UserReceiveMetaUpdateEvent.java" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/extras/InvalidVersionException.java" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/meta/EntityMeta.java" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/meta/Metadata.java" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/tick/TickContainer.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/settings.gradle" beforeDir="false" afterPath="$PROJECT_DIR$/settings.gradle" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/api/build.gradle" beforeDir="false" afterPath="$PROJECT_DIR$/api/build.gradle" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/build.gradle" beforeDir="false" afterPath="$PROJECT_DIR$/build.gradle" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/java/me/tofaa/entitylib/meta/Metadata.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/me/tofaa/entitylib/meta/Metadata.java" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
|
@ -72,30 +81,34 @@
|
|||
<option name="showExcludedFiles" value="false" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent"><![CDATA[{
|
||||
"keyToString": {
|
||||
"Gradle.Build EntityLib.executor": "Run",
|
||||
"Gradle.EntityLib:test-plugin [runServer].executor": "Run",
|
||||
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"WebServerToolWindowFactoryState": "false",
|
||||
"git-widget-placeholder": "feat/platform-api",
|
||||
"ignore.virus.scanning.warn.message": "true",
|
||||
"jdk.selected.JAVA_MODULE": "corretto-17",
|
||||
"kotlin-language-version-configured": "true",
|
||||
"last_opened_file_path": "D:/Github/EntityLib",
|
||||
"node.js.detected.package.eslint": "true",
|
||||
"node.js.detected.package.tslint": "true",
|
||||
"node.js.selected.package.eslint": "(autodetect)",
|
||||
"node.js.selected.package.tslint": "(autodetect)",
|
||||
"nodejs_package_manager_path": "npm",
|
||||
"project.structure.last.edited": "Modules",
|
||||
"project.structure.proportion": "0.0",
|
||||
"project.structure.side.proportion": "0.0",
|
||||
"settings.editor.selected.configurable": "preferences.pluginManager",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
<component name="PropertiesComponent">{
|
||||
"keyToString": {
|
||||
"Downloaded.Files.Path.Enabled": "false",
|
||||
"Gradle.Build EntityLib.executor": "Run",
|
||||
"Gradle.EntityLib:test-plugin [runServer].executor": "Run",
|
||||
"Repository.Attach.Annotations": "false",
|
||||
"Repository.Attach.JavaDocs": "false",
|
||||
"Repository.Attach.Sources": "false",
|
||||
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"WebServerToolWindowFactoryState": "false",
|
||||
"git-widget-placeholder": "feat/platform-api",
|
||||
"ignore.virus.scanning.warn.message": "true",
|
||||
"jdk.selected.JAVA_MODULE": "corretto-17",
|
||||
"kotlin-language-version-configured": "true",
|
||||
"last_opened_file_path": "D:/Github/EntityLib",
|
||||
"node.js.detected.package.eslint": "true",
|
||||
"node.js.detected.package.tslint": "true",
|
||||
"node.js.selected.package.eslint": "(autodetect)",
|
||||
"node.js.selected.package.tslint": "(autodetect)",
|
||||
"nodejs_package_manager_path": "npm",
|
||||
"project.structure.last.edited": "Modules",
|
||||
"project.structure.proportion": "0.0",
|
||||
"project.structure.side.proportion": "0.0",
|
||||
"settings.editor.selected.configurable": "preferences.pluginManager",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
}
|
||||
}]]></component>
|
||||
}</component>
|
||||
<component name="RecentsManager">
|
||||
<key name="CopyFile.RECENT_KEYS">
|
||||
<recent name="D:\Github\EntityLib\test-plugin" />
|
||||
|
@ -216,6 +229,10 @@
|
|||
<workItem from="1705578156456" duration="78000" />
|
||||
<workItem from="1705636302508" duration="7111000" />
|
||||
<workItem from="1705951390204" duration="3936000" />
|
||||
<workItem from="1705984769972" duration="76000" />
|
||||
<workItem from="1706183895216" duration="664000" />
|
||||
<workItem from="1706187926445" duration="4339000" />
|
||||
<workItem from="1706248178234" duration="1973000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
plugins {
|
||||
id 'java'
|
||||
id 'java-library'
|
||||
}
|
||||
|
||||
group = 'me.tofaa.entitylib'
|
||||
|
@ -10,10 +11,8 @@ repositories {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation platform('org.junit:junit-bom:5.9.1')
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter'
|
||||
}
|
||||
api 'org.jetbrains:annotations:24.0.0'
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
compileOnlyApi(adventureDependencies)
|
||||
compileOnlyApi 'com.github.retrooper.packetevents:api:2.2.0'
|
||||
}
|
100
api/src/main/java/me/tofaa/entitylib/APISettings.java
Normal file
100
api/src/main/java/me/tofaa/entitylib/APISettings.java
Normal file
|
@ -0,0 +1,100 @@
|
|||
package me.tofaa.entitylib;
|
||||
|
||||
import com.github.retrooper.packetevents.PacketEventsAPI;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
|
||||
public final class APISettings {
|
||||
|
||||
private boolean debugMode = false;
|
||||
private boolean checkForUpdates = false;
|
||||
private boolean tickTickables = false;
|
||||
private PacketEventsAPI<?> packetEvents;
|
||||
private boolean platformLogger = false;
|
||||
|
||||
public APISettings(PacketEventsAPI<?> packetEvents) {
|
||||
this.packetEvents = packetEvents;
|
||||
}
|
||||
|
||||
public boolean requiresUpdate() throws IOException {
|
||||
if (!checkForUpdates) return false;
|
||||
String urlString = "https://api.github.com/repos/Tofaa2/EntityLib/releases/latest";
|
||||
String version = EntityLib.getVersion();
|
||||
|
||||
URL url = new URL(urlString);
|
||||
JsonParser json = new JsonParser();
|
||||
InputStream stream = url.openStream();
|
||||
JsonArray array = json.parse(new InputStreamReader(stream)).getAsJsonArray();
|
||||
String latest = array.get(0).getAsJsonObject().get("tag_name").getAsString();
|
||||
|
||||
stream.close();
|
||||
return !version.equalsIgnoreCase(latest);
|
||||
}
|
||||
|
||||
public @NotNull APISettings usePlatformLogger() {
|
||||
this.platformLogger = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull APISettings usePlatformLogger(boolean platformLogger) {
|
||||
this.platformLogger = platformLogger;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull APISettings debugMode(boolean debugMode) {
|
||||
this.debugMode = debugMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull APISettings checkForUpdates() {
|
||||
this.checkForUpdates = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull APISettings tickTickables() {
|
||||
this.tickTickables = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull APISettings debugMode() {
|
||||
this.debugMode = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull APISettings checkForUpdates(boolean checkForUpdates) {
|
||||
this.checkForUpdates = checkForUpdates;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull APISettings tickTickables(boolean tickTickables) {
|
||||
this.tickTickables = tickTickables;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isDebugMode() {
|
||||
return debugMode;
|
||||
}
|
||||
|
||||
public boolean shouldCheckForUpdate() {
|
||||
return checkForUpdates;
|
||||
}
|
||||
|
||||
public boolean shouldTickTickables() {
|
||||
return tickTickables;
|
||||
}
|
||||
|
||||
public PacketEventsAPI<?> getPacketEvents() {
|
||||
return packetEvents;
|
||||
}
|
||||
|
||||
public boolean shouldUsePlatformLogger() {
|
||||
return platformLogger;
|
||||
}
|
||||
|
||||
}
|
28
api/src/main/java/me/tofaa/entitylib/EntityLib.java
Normal file
28
api/src/main/java/me/tofaa/entitylib/EntityLib.java
Normal file
|
@ -0,0 +1,28 @@
|
|||
package me.tofaa.entitylib;
|
||||
|
||||
public final class EntityLib {
|
||||
|
||||
private EntityLib() {}
|
||||
|
||||
private static String version = "1.2.0-SNAPSHOT";
|
||||
private static Platform platform;
|
||||
private static EntityLibAPI api;
|
||||
|
||||
public static void init(Platform<?> platform, APISettings settings) {
|
||||
EntityLib.platform = platform;
|
||||
platform.setupApi(settings);
|
||||
api = platform.getAPI();
|
||||
}
|
||||
|
||||
public static EntityLibAPI<?, ?> getApi() {
|
||||
return api;
|
||||
}
|
||||
|
||||
public static Platform<?> getPlatform() {
|
||||
return platform;
|
||||
}
|
||||
|
||||
public static String getVersion() {
|
||||
return version;
|
||||
}
|
||||
}
|
43
api/src/main/java/me/tofaa/entitylib/EntityLibAPI.java
Normal file
43
api/src/main/java/me/tofaa/entitylib/EntityLibAPI.java
Normal file
|
@ -0,0 +1,43 @@
|
|||
package me.tofaa.entitylib;
|
||||
|
||||
import com.github.retrooper.packetevents.PacketEventsAPI;
|
||||
import me.tofaa.entitylib.tick.TickContainer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Represents the API for EntityLib.
|
||||
* Handles the loading, enabling, and disabling of the API. And handles platform specific creation of EntityLib content.
|
||||
* @param <W> The {@link WorldWrapper}'s param type for the platform specific World.
|
||||
* @param <T> The {@link TickContainer}'s param type for the platform specific TickContainer.
|
||||
*/
|
||||
public interface EntityLibAPI<W, T> {
|
||||
|
||||
PacketEventsAPI<?> getPacketEvents();
|
||||
|
||||
void onLoad();
|
||||
|
||||
void onEnable();
|
||||
|
||||
@NotNull APISettings getSettings();
|
||||
|
||||
|
||||
/**
|
||||
* If a platform supports ticking
|
||||
* this method should be responsible for setting up the {@link me.tofaa.entitylib.tick.TickContainer}'s.
|
||||
*/
|
||||
void setupTickingContainers();
|
||||
|
||||
|
||||
/**
|
||||
* @return An unmodifiable collection of TickContainers.
|
||||
*/
|
||||
@NotNull Collection<TickContainer<?, T>> getTickContainers();
|
||||
|
||||
/**
|
||||
* Adds a TickContainer to the API. Automatically starts ticking it.
|
||||
* @param tickContainer the TickContainer to add.
|
||||
*/
|
||||
void addTickContainer(@NotNull TickContainer<?, T> tickContainer);
|
||||
}
|
53
api/src/main/java/me/tofaa/entitylib/Platform.java
Normal file
53
api/src/main/java/me/tofaa/entitylib/Platform.java
Normal file
|
@ -0,0 +1,53 @@
|
|||
package me.tofaa.entitylib;
|
||||
|
||||
import me.tofaa.entitylib.event.EntityLibEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* A generic representation of a platform that EntityLib is running on.
|
||||
* @param <P> The platform handle, for Spigot this would be a JavaPlugin. etc etc.
|
||||
*/
|
||||
public interface Platform<P> {
|
||||
|
||||
|
||||
/**
|
||||
* @return the logger EntityLib uses internally.
|
||||
*/
|
||||
@NotNull Logger getLogger();
|
||||
|
||||
/**
|
||||
* Sends an event to the platform. Platform implementations should handle the event accordingly.
|
||||
* @param event the event to send.
|
||||
*/
|
||||
void sendEvent(EntityLibEvent event);
|
||||
|
||||
/**
|
||||
* Registers a listener for the given event class, the handle will be called when the event is sent.
|
||||
* @param eventClass the event class to listen for.
|
||||
* @param handle the handle to call when the event is sent.
|
||||
* @param <T> the event type.
|
||||
*/
|
||||
<T extends EntityLibEvent> void registerListener(Class<T> eventClass, Consumer<T> handle);
|
||||
|
||||
/**
|
||||
* Sets up the API for the platform. This method should be called automatically by the platform. Don't call it yourself.
|
||||
* @param settings
|
||||
*/
|
||||
void setupApi(@NotNull APISettings settings);
|
||||
|
||||
/**
|
||||
* @return The API instance.
|
||||
*/
|
||||
EntityLibAPI<?, ?> getAPI();
|
||||
|
||||
/**
|
||||
* @return the platforms name.
|
||||
*/
|
||||
String getName();
|
||||
|
||||
@NotNull P getHandle();
|
||||
|
||||
}
|
19
api/src/main/java/me/tofaa/entitylib/WorldWrapper.java
Normal file
19
api/src/main/java/me/tofaa/entitylib/WorldWrapper.java
Normal file
|
@ -0,0 +1,19 @@
|
|||
package me.tofaa.entitylib;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
|
||||
/**
|
||||
* Represents a platform specific world.
|
||||
* These are not needed at all times, and should exclusively be used when an Entity needs to be
|
||||
* aware of its surroundings.
|
||||
* @param <W> The platform specific World type.
|
||||
*/
|
||||
public interface WorldWrapper<W> {
|
||||
|
||||
ResourceLocation getPacketEventsWorld();
|
||||
|
||||
WrappedBlockState getBlock(int x, int y, int z);
|
||||
|
||||
W getHandle();
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package me.tofaa.entitylib.event;
|
||||
|
||||
public interface EntityLibEvent {
|
||||
|
||||
boolean isCancelled();
|
||||
|
||||
void setCancelled(boolean cancelled);
|
||||
|
||||
default boolean isAsync() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package me.tofaa.entitylib.event;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.player.User;
|
||||
import me.tofaa.entitylib.meta.EntityMeta;
|
||||
|
||||
public final class UserReceiveMetaUpdateEvent implements EntityLibEvent {
|
||||
|
||||
private final User user;
|
||||
private boolean cancelled;
|
||||
private EntityMeta meta;
|
||||
|
||||
public UserReceiveMetaUpdateEvent(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancelled) {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package me.tofaa.entitylib.extras;
|
||||
|
||||
public class InvalidVersionException extends RuntimeException {
|
||||
|
||||
public InvalidVersionException() {
|
||||
}
|
||||
|
||||
public InvalidVersionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public InvalidVersionException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public InvalidVersionException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public InvalidVersionException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
}
|
221
api/src/main/java/me/tofaa/entitylib/meta/EntityMeta.java
Normal file
221
api/src/main/java/me/tofaa/entitylib/meta/EntityMeta.java
Normal file
|
@ -0,0 +1,221 @@
|
|||
package me.tofaa.entitylib.meta;
|
||||
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.manager.server.VersionComparison;
|
||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
|
||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
|
||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityMetadataProvider;
|
||||
import com.github.retrooper.packetevents.protocol.entity.pose.EntityPose;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityMetadata;
|
||||
import me.tofaa.entitylib.EntityLib;
|
||||
import me.tofaa.entitylib.extras.InvalidVersionException;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class EntityMeta implements EntityMetadataProvider {
|
||||
|
||||
public static final byte OFFSET = 0;
|
||||
public static final byte MAX_OFFSET = OFFSET + 8;
|
||||
|
||||
private final static byte ON_FIRE_BIT = 0x01;
|
||||
private final static byte CROUCHING_BIT = 0x02;
|
||||
private final static byte SPRINTING_BIT = 0x08;
|
||||
private final static byte SWIMMING_BIT = 0x10;
|
||||
private final static byte INVISIBLE_BIT = 0x20;
|
||||
private final static byte HAS_GLOWING_EFFECT_BIT = 0x40;
|
||||
private final static byte FLYING_WITH_ELYTRA_BIT = (byte) 0x80;
|
||||
|
||||
protected final int entityId;
|
||||
protected final Metadata metadata;
|
||||
|
||||
public EntityMeta(int entityId, Metadata metadata) {
|
||||
this.entityId = entityId;
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public boolean isOnFire() {
|
||||
return getMaskBit(OFFSET, ON_FIRE_BIT);
|
||||
}
|
||||
|
||||
public void setOnFire(boolean value) {
|
||||
setMaskBit(OFFSET, ON_FIRE_BIT, value);
|
||||
}
|
||||
|
||||
public boolean isSneaking() {
|
||||
return getMaskBit(OFFSET, CROUCHING_BIT);
|
||||
}
|
||||
|
||||
public void setSneaking(boolean value) {
|
||||
setMaskBit(OFFSET, CROUCHING_BIT, value);
|
||||
}
|
||||
|
||||
public boolean isSprinting() {
|
||||
return getMaskBit(OFFSET, SPRINTING_BIT);
|
||||
}
|
||||
|
||||
public void setSprinting(boolean value) {
|
||||
setMaskBit(OFFSET, SPRINTING_BIT, value);
|
||||
}
|
||||
|
||||
public boolean isInvisible() {
|
||||
return getMaskBit(OFFSET, INVISIBLE_BIT);
|
||||
}
|
||||
|
||||
public void setInvisible(boolean value) {
|
||||
setMaskBit(OFFSET, INVISIBLE_BIT, value);
|
||||
}
|
||||
|
||||
public short getAirTicks() {
|
||||
return this.metadata.getIndex((byte) 1, (short) 300);
|
||||
}
|
||||
|
||||
public void setAirTicks(short value) {
|
||||
this.metadata.setIndex((byte) 1, EntityDataTypes.SHORT, value);
|
||||
}
|
||||
|
||||
public Component getCustomName() {
|
||||
return this.metadata.getIndex(offset(OFFSET, 2), null);
|
||||
}
|
||||
|
||||
public void setCustomName(Component value) {
|
||||
this.metadata.setIndex(offset(OFFSET, 2), EntityDataTypes.ADV_COMPONENT, value);
|
||||
}
|
||||
|
||||
public boolean isCustomNameVisible() {
|
||||
return this.metadata.getIndex(offset(OFFSET, 3), false);
|
||||
}
|
||||
|
||||
public void setCustomNameVisible(boolean value) {
|
||||
this.metadata.setIndex(offset(OFFSET, 3), EntityDataTypes.BOOLEAN, value);
|
||||
}
|
||||
|
||||
public boolean hasGlowingEffect() {
|
||||
return getMaskBit(OFFSET, HAS_GLOWING_EFFECT_BIT);
|
||||
}
|
||||
|
||||
public boolean isSwimming() {
|
||||
return getMaskBit(OFFSET, SWIMMING_BIT);
|
||||
}
|
||||
|
||||
public void setSwimming(boolean value) {
|
||||
setMaskBit(OFFSET, SWIMMING_BIT, value);
|
||||
}
|
||||
|
||||
public void setHasGlowingEffect(boolean value) {
|
||||
setMaskBit(OFFSET, HAS_GLOWING_EFFECT_BIT, value);
|
||||
}
|
||||
|
||||
public boolean isFlyingWithElytra() {
|
||||
return getMaskBit(OFFSET, FLYING_WITH_ELYTRA_BIT);
|
||||
}
|
||||
|
||||
public void setFlyingWithElytra(boolean value) {
|
||||
setMaskBit(OFFSET, FLYING_WITH_ELYTRA_BIT, value);
|
||||
}
|
||||
|
||||
public boolean isSilent() {
|
||||
return this.metadata.getIndex((byte) 4, false);
|
||||
}
|
||||
|
||||
public void setSilent(boolean value) {
|
||||
this.metadata.setIndex((byte) 4, EntityDataTypes.BOOLEAN, value);
|
||||
}
|
||||
|
||||
public boolean isHasNoGravity() {
|
||||
return this.metadata.getIndex(offset(OFFSET, 5), true);
|
||||
}
|
||||
|
||||
public void setHasNoGravity(boolean value) {
|
||||
this.metadata.setIndex(offset(OFFSET, 5), EntityDataTypes.BOOLEAN, value);
|
||||
}
|
||||
|
||||
public EntityPose getPose() {
|
||||
return this.metadata.getIndex(offset(OFFSET, 6), EntityPose.STANDING);
|
||||
}
|
||||
|
||||
public void setPose(EntityPose value) {
|
||||
this.metadata.setIndex(offset(OFFSET, 6), EntityDataTypes.ENTITY_POSE, value);
|
||||
}
|
||||
|
||||
public int getTicksFrozenInPowderedSnow() {
|
||||
return this.metadata.getIndex(offset(OFFSET, 7), 0);
|
||||
}
|
||||
|
||||
public void setTicksFrozenInPowderedSnow(int value) {
|
||||
this.metadata.setIndex(offset(OFFSET, 7), EntityDataTypes.INT, value);
|
||||
}
|
||||
|
||||
public WrapperPlayServerEntityMetadata createPacket() {
|
||||
return metadata.createPacket();
|
||||
}
|
||||
|
||||
protected static void isVersionOlder(ServerVersion version) {
|
||||
if (!EntityLib.getApi().getPacketEvents().getServerManager().getVersion().is(VersionComparison.OLDER_THAN, version)) {
|
||||
throw new InvalidVersionException("This method is only available for versions older than " + version.name() + ".");
|
||||
}
|
||||
}
|
||||
|
||||
protected static void isVersionNewer(ServerVersion version) {
|
||||
if (!EntityLib.getApi().getPacketEvents().getServerManager().getVersion().is(VersionComparison.NEWER_THAN, version)) {
|
||||
throw new InvalidVersionException("This method is only available for versions newer than " + version.name() + ".");
|
||||
}
|
||||
}
|
||||
|
||||
protected static boolean isVersion(ServerVersion version, VersionComparison comparison) {
|
||||
return EntityLib.getApi().getPacketEvents().getServerManager().getVersion().is(comparison, version);
|
||||
}
|
||||
|
||||
protected static boolean isVersion(ServerVersion version) {
|
||||
return EntityLib.getApi().getPacketEvents().getServerManager().getVersion().is(VersionComparison.EQUALS, version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Annoying java 8 not letting me do OFFSET + amount in the method call so this is a workaround
|
||||
* @param value the value to offset
|
||||
* @param amount the amount to offset by
|
||||
* @return the offset value
|
||||
*/
|
||||
protected static byte offset(byte value, int amount) {
|
||||
return (byte) (value + amount);
|
||||
}
|
||||
|
||||
protected byte getMask(byte index) {
|
||||
return this.metadata.getIndex(index, (byte) 0);
|
||||
}
|
||||
|
||||
protected void setMask(byte index, byte mask) {
|
||||
this.metadata.setIndex(index, EntityDataTypes.BYTE, mask);
|
||||
}
|
||||
|
||||
protected boolean getMaskBit(byte index, byte bit) {
|
||||
return (getMask(index) & bit) == bit;
|
||||
}
|
||||
|
||||
protected void setMaskBit(int index, byte bit, boolean value) {
|
||||
byte mask = getMask((byte)index);
|
||||
boolean currentValue = (mask & bit) == bit;
|
||||
if (currentValue == value) {
|
||||
return;
|
||||
}
|
||||
if (value) {
|
||||
mask |= bit;
|
||||
} else {
|
||||
mask &= (byte) ~bit;
|
||||
}
|
||||
setMask((byte)index, mask);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EntityData> entityData(ClientVersion clientVersion) {
|
||||
return metadata.getEntries(); // TODO: Atm this is useless cause of the way the api works. Might change in the future
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EntityData> entityData() {
|
||||
return metadata.getEntries();
|
||||
}
|
||||
|
||||
|
||||
}
|
45
api/src/main/java/me/tofaa/entitylib/meta/Metadata.java
Normal file
45
api/src/main/java/me/tofaa/entitylib/meta/Metadata.java
Normal file
|
@ -0,0 +1,45 @@
|
|||
package me.tofaa.entitylib.meta;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
|
||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataType;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityMetadata;
|
||||
import me.tofaa.entitylib.EntityLib;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class Metadata {
|
||||
|
||||
private final Map<Byte, EntityData> metadataMap = new ConcurrentHashMap<>();
|
||||
private final int entityId;
|
||||
|
||||
public Metadata(int entityId) {
|
||||
this.entityId = entityId;
|
||||
}
|
||||
|
||||
public <T> T getIndex(byte index, @Nullable T defaultValue) {
|
||||
EntityData entityData = metadataMap.get(index);
|
||||
if (entityData == null) return defaultValue;
|
||||
if (entityData.getValue() == null) return defaultValue;
|
||||
return (T) entityData.getValue();
|
||||
}
|
||||
|
||||
public <T> void setIndex(byte index, @NotNull EntityDataType<T> dataType, T value) {
|
||||
EntityData data = new EntityData(index, dataType, value);
|
||||
this.metadataMap.put(index, data);
|
||||
}
|
||||
|
||||
@NotNull List<EntityData> getEntries() {
|
||||
return new ArrayList<>(metadataMap.values());
|
||||
}
|
||||
|
||||
public WrapperPlayServerEntityMetadata createPacket() {
|
||||
return new WrapperPlayServerEntityMetadata(entityId, getEntries());
|
||||
}
|
||||
|
||||
}
|
72
api/src/main/java/me/tofaa/entitylib/tick/TickContainer.java
Normal file
72
api/src/main/java/me/tofaa/entitylib/tick/TickContainer.java
Normal file
|
@ -0,0 +1,72 @@
|
|||
package me.tofaa.entitylib.tick;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Represents a storage/container for {@link Tickable}s.
|
||||
* @param <T> The type of {@link Tickable} to store.
|
||||
* @param <H> If a platform enforces a specific method of ticking, this type represents the handler for that method.
|
||||
*/
|
||||
public abstract class TickContainer<T extends Tickable, H> {
|
||||
|
||||
private final Set<T> tickables = new HashSet<>();
|
||||
private H handle;
|
||||
|
||||
/**
|
||||
* @return The {@link Tickable}s stored in this container. This collection is immutable
|
||||
*/
|
||||
public @NotNull Collection<T> getTickables() {
|
||||
return Collections.unmodifiableCollection(tickables);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link Tickable} to this container.
|
||||
* @param tickable The {@link Tickable} to add.
|
||||
* @return {@code true} if the {@link Tickable} was added, {@code false} otherwise.
|
||||
*/
|
||||
public boolean addTickable(@NotNull T tickable) {
|
||||
return tickables.add(tickable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a {@link Tickable} from this container.
|
||||
* @param tickable The {@link Tickable} to remove.
|
||||
* @return {@code true} if the {@link Tickable} was removed, {@code false} otherwise.
|
||||
*/
|
||||
public boolean removeTickable(T tickable) {
|
||||
return tickables.remove(tickable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ticks all {@link Tickable}s in this container, this method can be overriden to provide a custom implementation.
|
||||
* @param time The current time in milliseconds, incase the {@link Tickable} needs to know the current time.
|
||||
*/
|
||||
public void tick(long time) {
|
||||
for (T tickable : tickables) {
|
||||
tickable.tick(time);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The handler for this container.
|
||||
*/
|
||||
public @NotNull H getHandle() {
|
||||
return handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the handler for this container. This method is only used internally.
|
||||
* @param handle The handler to set.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public void setHandle(@NotNull H handle) {
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
}
|
7
api/src/main/java/me/tofaa/entitylib/tick/Tickable.java
Normal file
7
api/src/main/java/me/tofaa/entitylib/tick/Tickable.java
Normal file
|
@ -0,0 +1,7 @@
|
|||
package me.tofaa.entitylib.tick;
|
||||
|
||||
public interface Tickable {
|
||||
|
||||
void tick(long time);
|
||||
|
||||
}
|
|
@ -5,6 +5,12 @@ plugins {
|
|||
|
||||
allprojects {
|
||||
|
||||
project.ext.adventureVersion = '4.15.0'
|
||||
project.ext.adventureDependencies=["net.kyori:adventure-api:${adventureVersion}",
|
||||
"net.kyori:adventure-text-serializer-gson:${adventureVersion}",
|
||||
"net.kyori:adventure-text-serializer-legacy:${adventureVersion}",
|
||||
"net.kyori:adventure-nbt:${adventureVersion}"]
|
||||
|
||||
apply plugin: 'java'
|
||||
|
||||
group = 'me.tofaa.entitylib'
|
||||
|
|
15
platforms/spigot/build.gradle
Normal file
15
platforms/spigot/build.gradle
Normal file
|
@ -0,0 +1,15 @@
|
|||
plugins {
|
||||
id 'java'
|
||||
}
|
||||
|
||||
group = 'me.tofaa.entitylib'
|
||||
version = '1.0-SNAPSHOT'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":api"))
|
||||
implementation('org.spigotmc:spigot-api:1.20.1-R0.1-SNAPSHOT')
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
package me.tofaa.entitylib.spigot;
|
||||
|
||||
import com.github.retrooper.packetevents.PacketEventsAPI;
|
||||
import me.tofaa.entitylib.APISettings;
|
||||
import me.tofaa.entitylib.EntityLibAPI;
|
||||
import me.tofaa.entitylib.tick.TickContainer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class SpigotEntityLibAPI implements EntityLibAPI<World, BukkitTask> {
|
||||
|
||||
private final SpigotEntityLibPlatform platform;
|
||||
private final PacketEventsAPI<?> packetEvents;
|
||||
private final APISettings settings;
|
||||
private Collection<TickContainer<?, BukkitTask>> tickContainers;
|
||||
|
||||
SpigotEntityLibAPI(SpigotEntityLibPlatform platform, APISettings settings) {
|
||||
this.platform = platform;
|
||||
this.packetEvents = settings.getPacketEvents();
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
this.tickContainers = settings.shouldTickTickables() ? new HashSet<>() : Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
|
||||
}
|
||||
|
||||
@NotNull @Override
|
||||
public APISettings getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupTickingContainers() {
|
||||
if (!getSettings().shouldTickTickables()) {
|
||||
if (getSettings().isDebugMode()) {
|
||||
platform.getLogger().log(Level.CONFIG, "Skipping ticking containers as it is disabled in the settings.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (getSettings().isDebugMode()) {
|
||||
platform.getLogger().log(Level.CONFIG, "Setting up ticking containers...");
|
||||
}
|
||||
if (tickContainers.isEmpty()) {
|
||||
if (getSettings().isDebugMode()) {
|
||||
platform.getLogger().log(Level.CONFIG, "No tick containers found.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (getSettings().isDebugMode()) {
|
||||
platform.getLogger().log(Level.CONFIG, "Found " + tickContainers.size() + " tick containers.");
|
||||
}
|
||||
|
||||
tickContainers.forEach(this::registerNewTickContainer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketEventsAPI<?> getPacketEvents() {
|
||||
return packetEvents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<TickContainer<?, BukkitTask>> getTickContainers() {
|
||||
return tickContainers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTickContainer(@NotNull TickContainer<?, BukkitTask> tickContainer) {
|
||||
tickContainers.add(tickContainer);
|
||||
registerNewTickContainer(tickContainer);
|
||||
}
|
||||
|
||||
public void registerNewTickContainer(TickContainer<?, BukkitTask> tickContainer) {
|
||||
|
||||
if (getSettings().isDebugMode()) {
|
||||
platform.getLogger().log(Level.CONFIG, "Registering new tick container...");
|
||||
}
|
||||
getTickContainers().add(tickContainer);
|
||||
BukkitTask task = Bukkit.getScheduler().runTaskTimerAsynchronously(platform.getHandle(), () -> tickContainer.tick(System.currentTimeMillis()), 1L, 1L);
|
||||
tickContainer.setHandle(task);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package me.tofaa.entitylib.spigot;
|
||||
|
||||
import me.tofaa.entitylib.APISettings;
|
||||
import me.tofaa.entitylib.EntityLibAPI;
|
||||
import me.tofaa.entitylib.Platform;
|
||||
import me.tofaa.entitylib.event.EntityLibEvent;
|
||||
import me.tofaa.entitylib.tick.TickContainer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class SpigotEntityLibPlatform implements Platform<JavaPlugin> {
|
||||
|
||||
private final JavaPlugin plugin;
|
||||
private SpigotEntityLibAPI api;
|
||||
private Logger logger;
|
||||
|
||||
public SpigotEntityLibPlatform(@NotNull JavaPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupApi(@NotNull APISettings settings) {
|
||||
this.logger = settings.shouldUsePlatformLogger() ? plugin.getLogger() : Logger.getLogger("EntityLib");
|
||||
this.api = new SpigotEntityLibAPI(this, settings);
|
||||
this.api.onLoad();
|
||||
this.api.onEnable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Logger getLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendEvent(EntityLibEvent event) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends EntityLibEvent> void registerListener(Class<T> eventClass, Consumer<T> handle) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityLibAPI getAPI() {
|
||||
return api;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull JavaPlugin getHandle() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Spigot";
|
||||
}
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
rootProject.name = 'EntityLib'
|
||||
include 'test-plugin'
|
||||
include 'api'
|
||||
include 'platforms:spigot'
|
||||
findProject(':platforms:spigot')?.name = 'spigot'
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ import org.jetbrains.annotations.NotNull;
|
|||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
|
Loading…
Reference in a new issue