🎉 First commit!

This commit is contained in:
SBDeveloper 2022-06-30 11:06:58 +02:00
commit 4dc99283f4
42 changed files with 4068 additions and 0 deletions

94
.gitignore vendored Normal file
View file

@ -0,0 +1,94 @@
### Jetbrains ###
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
.idea/artifacts
.idea/compiler.xml
.idea/jarRepositories.xml
.idea/modules.xml
.idea/*.iml
.idea/modules
*.iml
*.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
.mvn/wrapper/maven-wrapper.jar
# Eclipse m2e generated files
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath

8
.idea/.gitignore generated vendored Normal file
View file

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

7
.idea/discord.xml generated Normal file
View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="PROJECT_FILES" />
<option name="description" value="" />
</component>
</project>

27
.idea/encodings.xml generated Normal file
View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/API/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/API/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Dist/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Dist/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/NMS-v1_12_R1/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/NMS-v1_12_R1/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/NMS-v1_13_R2/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/NMS-v1_13_R2/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/NMS-v1_14_R1/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/NMS-v1_14_R1/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/NMS-v1_15_R1/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/NMS-v1_15_R1/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/NMS-v1_16_R3/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/NMS-v1_16_R3/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/NMS-v1_17_R1/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/NMS-v1_17_R1/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/NMS-v1_18_R2/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/NMS-v1_18_R2/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/NMS-v1_19_R1/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/NMS-v1_19_R1/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>

22
.idea/misc.xml generated Normal file
View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ComposerSettings">
<execution />
</component>
<component name="EntryPointsManager">
<list size="1">
<item index="0" class="java.lang.String" itemvalue="org.bukkit.event.EventHandler" />
</list>
</component>
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

6
.idea/vcs.xml generated Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

82
API/pom.xml Normal file
View file

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>MapReflectionAPI</artifactId>
<groupId>tech.sbdevelopment</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>MapReflectionAPI-API</artifactId>
<distributionManagement>
<repository>
<id>nexus-snapshots</id>
<url>https://repo.sbdevelopment.tech/repository/maven-snapshots/</url>
</repository>
</distributionManagement>
<properties>
<jdk.version>11</jdk.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0-SNAPSHOT</version>
<configuration>
<release>${jdk.version}</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.0.0-M2</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.13</version>
<executions>
<execution>
<id>default-deploy</id>
<phase>deploy</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
<configuration>
<serverId>nexus-snapshots</serverId>
<nexusUrl>https://repo.sbdevelopment.tech/</nexusUrl>
<skipStaging>true</skipStaging>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>MG-Dev Jenkins CI Maven Repository</id>
<url>https://ci.mg-dev.eu/plugin/repository/everything</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.bergerkiller.bukkit</groupId>
<artifactId>BKCommonLib</artifactId>
<version>1.19-v1</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View file

@ -0,0 +1,48 @@
package tech.sbdevelopment.mapreflectionapi;
import com.bergerkiller.bukkit.common.map.MapColorPalette;
import java.awt.*;
import java.awt.image.BufferedImage;
public class ArrayImage {
public byte[] array;
public int minX = 0;
public int minY = 0;
public int maxX = 128;
public int maxY = 128;
private int width;
private int height;
private int imageType = BufferedImage.TYPE_4BYTE_ABGR;
public ArrayImage(byte[] data) {
this.array = data;
}
/**
* Convert a {@link BufferedImage} to an ArrayImage
*
* @param image image to convert
*/
public ArrayImage(BufferedImage image) {
this.imageType = image.getType();
this.width = image.getWidth();
this.height = image.getHeight();
BufferedImage temp = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = temp.createGraphics();
graphics.drawImage(image, 0, 0, null);
graphics.dispose();
int[] pixels = new int[temp.getWidth() * temp.getHeight()];
temp.getRGB(0, 0, temp.getWidth(), temp.getHeight(), pixels, 0, temp.getWidth());
byte[] result = new byte[temp.getWidth() * temp.getHeight()];
for (int i = 0; i < pixels.length; i++) {
result[i] = MapColorPalette.getColor(new Color(pixels[i], true));
}
this.array = result;
}
}

View file

@ -0,0 +1,150 @@
package tech.sbdevelopment.mapreflectionapi;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import tech.sbdevelopment.mapreflectionapi.exceptions.MapLimitExceededException;
public interface MapController {
/**
* Add a viewer
*
* @param player {@link Player} to add
*/
void addViewer(Player player) throws MapLimitExceededException;
/**
* Remove a viewer
*
* @param player {@link OfflinePlayer} to remove
*/
void removeViewer(OfflinePlayer player);
/**
* Remove all viewers
*/
void clearViewers();
/**
* Check if a player is viewing
*
* @param player {@link OfflinePlayer} to check
* @return <code>true</code> if the player is viewing
*/
boolean isViewing(OfflinePlayer player);
/**
* Get the map ID for a player
*
* @param player {@link OfflinePlayer} to get the ID for
* @return the ID, or <code>-1</code> if no ID exists (i.e. the player is not viewing)
*/
int getMapId(OfflinePlayer player);
/**
* Update the image
*
* @param content new {@link ArrayImage} content
*/
void update(ArrayImage content);
ArrayImage getContent();
/**
* Send the content to a player
*
* @param player {@link Player} receiver of the content
*/
void sendContent(Player player);
/**
* Send the content to a player
*
* @param player {@link Player} receiver of the content
* @param withoutQueue if <code>true</code>, the content will be sent immediately
*/
void sendContent(Player player, boolean withoutQueue);
/**
* Show in a player's inventory
*
* @param player {@link Player}
* @param slot slot to show the map in
* @param force if <code>false</code>, the map will not be shown if the player is in creative mode
*/
void showInInventory(Player player, int slot, boolean force);
/**
* Show in a player's inventory
*
* @param player {@link Player}
* @param slot slot to show the map in
*/
void showInInventory(Player player, int slot);
/**
* Show in a player's hand
*
* @param player {@link Player}
* @param force if <code>false</code>, the map will not be shown if the player is not holding a map, or is in creative mode
* @see #showInFrame(Player, ItemFrame, boolean)
*/
void showInHand(Player player, boolean force);
/**
* Show in a player's hand
*
* @param player {@link Player}
*/
void showInHand(Player player);
/**
* Show in an {@link ItemFrame}
*
* @param player {@link Player} that will be able to see the map
* @param frame {@link ItemFrame} to show the map in
*/
void showInFrame(Player player, ItemFrame frame);
/**
* Show in an {@link ItemFrame}
*
* @param player {@link Player} that will be able to see the map
* @param frame {@link ItemFrame} to show the map in
* @param force if <code>false</code>, the map will not be shown if there is not Map-Item in the ItemFrame
*/
void showInFrame(Player player, ItemFrame frame, boolean force);
/**
* Show in an {@link ItemFrame}
*
* @param player {@link Player} that will be able to see the map
* @param entityId Entity-ID of the {@link ItemFrame} to show the map in
*/
void showInFrame(Player player, int entityId);
/**
* Show in an {@link ItemFrame}
*
* @param player {@link Player} that will be able to see the map
* @param entityId Entity-ID of the {@link ItemFrame} to show the map in
* @param debugInfo {@link String} to show when a player looks at the map, or <code>null</code>
*/
void showInFrame(Player player, int entityId, String debugInfo);
/**
* Clear a frame
*
* @param player {@link Player} that will be able to see the cleared frame
* @param entityId Entity-ID of the {@link ItemFrame} to clear
*/
void clearFrame(Player player, int entityId);
/**
* Clear a frame
*
* @param player {@link Player} that will be able to see the cleared frame
* @param frame {@link ItemFrame} to clear
*/
void clearFrame(Player player, ItemFrame frame);
}

View file

@ -0,0 +1,152 @@
package tech.sbdevelopment.mapreflectionapi;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import tech.sbdevelopment.mapreflectionapi.exceptions.MapLimitExceededException;
import java.awt.image.BufferedImage;
import java.lang.reflect.InvocationTargetException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
public class MapManager {
protected final Set<Integer> OCCUPIED_IDS = new HashSet<>();
private final List<MapWrapper> MANAGED_MAPS = new CopyOnWriteArrayList<>();
private final Class<?> wrapperClass;
public MapManager() throws IllegalStateException {
String packageName = Bukkit.getServer().getClass().getPackage().getName();
String version = packageName.substring(packageName.lastIndexOf('.') + 1);
try {
final Class<?> clazz = Class.forName("tech.sbdevelopment.mapreflectionapi.nms.MapWrapper_" + version);
if (MapWrapper.class.isAssignableFrom(clazz)) {
wrapperClass = clazz;
} else {
throw new IllegalStateException("Plugin corrupted! Detected invalid MapWrapper class.");
}
} catch (Exception ex) {
throw new IllegalStateException("This Spigot version is not supported! Contact the developer to get support.");
}
}
@Nullable
public MapWrapper wrapImage(BufferedImage image) {
return wrapImage(new ArrayImage(image));
}
@Nullable
public MapWrapper wrapImage(ArrayImage image) {
for (MapWrapper wrapper : MANAGED_MAPS) {
if (wrapper.getContent().equals(image)) return wrapper;
}
return wrapNewImage(image);
}
private MapWrapper wrapNewImage(ArrayImage image) {
try {
MapWrapper wrapper = (MapWrapper) wrapperClass.getDeclaredConstructor().newInstance();
MANAGED_MAPS.add(wrapper);
return wrapper;
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
InvocationTargetException e) {
return null;
}
}
public void unwrapImage(MapWrapper wrapper) {
//TODO Cancel IDs
wrapper.getController().clearViewers();
MANAGED_MAPS.remove(wrapper);
}
public Set<MapWrapper> getMapsVisibleTo(OfflinePlayer player) {
Set<MapWrapper> visible = new HashSet<>();
for (MapWrapper wrapper : MANAGED_MAPS) {
if (wrapper.getController().isViewing(player)) {
visible.add(wrapper);
}
}
return visible;
}
public MapWrapper getWrapperForId(OfflinePlayer player, int id) {
for (MapWrapper wrapper : getMapsVisibleTo(player)) {
if (wrapper.getController().getMapId(player) == id) {
return wrapper;
}
}
return null;
}
public void registerOccupiedID(int id) {
OCCUPIED_IDS.add(id);
}
public void unregisterOccupiedID(int id) {
OCCUPIED_IDS.remove(id);
}
public Set<Integer> getOccupiedIdsFor(OfflinePlayer player) {
Set<Integer> ids = new HashSet<>();
for (MapWrapper wrapper : MANAGED_MAPS) {
int s = wrapper.getController().getMapId(player);
if (s >= 0) {
ids.add(s);
}
}
return ids;
}
public boolean isIdUsedBy(OfflinePlayer player, int id) {
return id > 0 && getOccupiedIdsFor(player).contains(id);
}
public int getNextFreeIdFor(Player player) throws MapLimitExceededException {
Set<Integer> occupied = getOccupiedIdsFor(player);
//Add the 'default' occupied IDs
occupied.addAll(OCCUPIED_IDS);
int largest = 0;
for (Integer s : occupied) {
if (s > largest) {
largest = s;
}
}
//Simply increase the maximum id if it's still small enough
if (largest + 1 < Integer.MAX_VALUE) {
return largest + 1;
}
//Otherwise iterate through all options until there is an unused id
for (int s = 0; s < Integer.MAX_VALUE; s++) {
if (!occupied.contains(s)) {
return s;
}
}
//If we end up here, this player has no more free ids. Let's hope nobody uses this many Maps.
throw new MapLimitExceededException("'" + player + "' reached the maximum amount of available Map-IDs");
}
public void clearAllMapsFor(OfflinePlayer player) {
for (MapWrapper wrapper : getMapsVisibleTo(player)) {
wrapper.getController().removeViewer(player);
}
}
public MapWrapper getDuplicate(ArrayImage image) {
for (MapWrapper wrapper : MANAGED_MAPS) {
if (image.equals(wrapper.getContent())) {
return wrapper;
}
}
return null;
}
}

View file

@ -0,0 +1,45 @@
package tech.sbdevelopment.mapreflectionapi;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
public class MapReflectionAPI extends JavaPlugin {
private static MapReflectionAPI instance;
private static MapManager mapManager;
public static MapReflectionAPI getInstance() {
if (instance == null) throw new IllegalStateException("The plugin is not enabled yet!");
return instance;
}
public static MapManager getMapManager() {
if (mapManager == null) throw new IllegalStateException("The plugin is not enabled yet!");
return mapManager;
}
@Override
public void onEnable() {
instance = this;
if (!Bukkit.getPluginManager().isPluginEnabled("BKCommonLib")) {
getLogger().severe("MapReflectionAPI requires BKCommonLib to function!");
Bukkit.getPluginManager().disablePlugin(this);
return;
}
try {
mapManager = new MapManager();
} catch (IllegalStateException e) {
e.printStackTrace();
Bukkit.getPluginManager().disablePlugin(this);
return;
}
getLogger().info("MapReflectionAPI is enabled!");
}
@Override
public void onDisable() {
instance = null;
}
}

View file

@ -0,0 +1,7 @@
package tech.sbdevelopment.mapreflectionapi;
public interface MapWrapper {
MapController getController();
ArrayImage getContent();
}

View file

@ -0,0 +1,7 @@
package tech.sbdevelopment.mapreflectionapi.exceptions;
public class MapLimitExceededException extends Exception {
public MapLimitExceededException(String message) {
super(message);
}
}

View file

@ -0,0 +1,8 @@
name: MapReflectionAPI
version: '${project.version}'
main: tech.sbdevelopment.mapreflectionapi.MapReflectionAPI
api-version: 1.13
authors: [ inventivetalent, SBDeveloper ]
description: This API helps developer with viewing images on maps.
website: https://sbdevelopment.tech
softdepend: [ BKCommonLib ]

101
Dist/pom.xml Normal file
View file

@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>MapReflectionAPI</artifactId>
<groupId>tech.sbdevelopment</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>MapReflectionAPI-Dist</artifactId>
<build>
<directory>../target</directory>
<finalName>${project.parent.name}-${project.version}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.0.0-M2</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<!-- Include all the dependencies required by the plugin -->
<artifactSet>
<includes>
<include>tech.sbdevelopment:MapReflectionAPI*</include>
</includes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>tech.sbdevelopment</groupId>
<artifactId>MapReflectionAPI-API</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>tech.sbdevelopment</groupId>
<artifactId>MapReflectionAPI-NMS-v1_19_R1</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>tech.sbdevelopment</groupId>
<artifactId>MapReflectionAPI-NMS-v1_18_R2</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>tech.sbdevelopment</groupId>
<artifactId>MapReflectionAPI-NMS-v1_16_R3</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>tech.sbdevelopment</groupId>
<artifactId>MapReflectionAPI-NMS-v1_17_R1</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>tech.sbdevelopment</groupId>
<artifactId>MapReflectionAPI-NMS-v1_15_R1</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>tech.sbdevelopment</groupId>
<artifactId>MapReflectionAPI-NMS-v1_14_R1</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>tech.sbdevelopment</groupId>
<artifactId>MapReflectionAPI-NMS-v1_13_R2</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>tech.sbdevelopment</groupId>
<artifactId>MapReflectionAPI-NMS-v1_12_R1</artifactId>
<version>${project.parent.version}</version>
</dependency>
</dependencies>
</project>

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) inventivetalent / SBDevelopment
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

54
NMS-v1_12_R1/pom.xml Normal file
View file

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>MapReflectionAPI</artifactId>
<groupId>tech.sbdevelopment</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>MapReflectionAPI-NMS-v1_12_R1</artifactId>
<properties>
<NMSVersion>1.12.2-R0.1-SNAPSHOT</NMSVersion>
<jdk.version>11</jdk.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0-SNAPSHOT</version>
<configuration>
<release>${jdk.version}</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.0.0-M2</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>${NMSVersion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>tech.sbdevelopment</groupId>
<artifactId>MapReflectionAPI-API</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View file

@ -0,0 +1,116 @@
package tech.sbdevelopment.mapreflectionapi.nms;
import net.minecraft.server.v1_12_R1.PacketPlayOutMap;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import tech.sbdevelopment.mapreflectionapi.ArrayImage;
import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class MapSender_v1_12_R1 {
private static final List<QueuedMap> sendQueue = new ArrayList<>();
private static int senderID = -1;
public static void addToQueue(final int id, final ArrayImage content, final Player player) {
QueuedMap toSend = new QueuedMap(id, content, player);
if (sendQueue.contains(toSend)) return;
sendQueue.add(toSend);
runSender();
}
private static void runSender() {
if (Bukkit.getScheduler().isQueued(senderID) || Bukkit.getScheduler().isCurrentlyRunning(senderID) || sendQueue.isEmpty())
return;
senderID = Bukkit.getScheduler().scheduleSyncRepeatingTask(MapReflectionAPI.getInstance(), () -> {
if (sendQueue.isEmpty()) return;
for (int i = 0; i < Math.min(sendQueue.size(), 10 + 1); i++) {
QueuedMap current = sendQueue.get(0);
if (current == null) return;
sendMap(current.id, current.image, current.player);
if (!sendQueue.isEmpty()) sendQueue.remove(0);
}
}, 0, 2);
}
public static void sendMap(final int id0, final ArrayImage content, final Player player) {
if (player == null || !player.isOnline()) {
List<QueuedMap> toRemove = new ArrayList<>();
for (QueuedMap qMap : sendQueue) {
if (qMap == null) continue;
if (qMap.player == null || !qMap.player.isOnline()) {
toRemove.add(qMap);
}
}
Bukkit.getScheduler().cancelTask(senderID);
sendQueue.removeAll(toRemove);
return;
}
final int id = -id0;
Bukkit.getScheduler().runTaskAsynchronously(MapReflectionAPI.getInstance(), () -> {
try {
PacketPlayOutMap packet = new PacketPlayOutMap(
id, //ID
(byte) 0, //Scale
false, //???
new ArrayList<>(), //Icons
content.array, //Data
content.minX, //X pos
content.minY, //Y pos
content.maxX, //X size (2nd X pos)
content.maxY //Y size (2nd Y pos)
);
((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet);
} catch (Exception e) {
e.printStackTrace();
}
});
}
static final class QueuedMap {
private final int id;
private final ArrayImage image;
private final Player player;
QueuedMap(int id, ArrayImage image, Player player) {
this.id = id;
this.image = image;
this.player = player;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
QueuedMap that = (QueuedMap) obj;
return this.id == that.id &&
Objects.equals(this.image, that.image) &&
Objects.equals(this.player, that.player);
}
@Override
public int hashCode() {
return Objects.hash(id, image, player);
}
@Override
public String toString() {
return "QueuedMap[" +
"id=" + id + ", " +
"image=" + image + ", " +
"player=" + player + ']';
}
}
}

View file

@ -0,0 +1,220 @@
package tech.sbdevelopment.mapreflectionapi.nms;
import net.minecraft.server.v1_12_R1.*;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.*;
import org.bukkit.craftbukkit.v1_12_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_12_R1.inventory.CraftItemStack;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.metadata.FixedMetadataValue;
import tech.sbdevelopment.mapreflectionapi.ArrayImage;
import tech.sbdevelopment.mapreflectionapi.MapController;
import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI;
import tech.sbdevelopment.mapreflectionapi.MapWrapper;
import tech.sbdevelopment.mapreflectionapi.exceptions.MapLimitExceededException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class MapWrapper_v1_12_R1 implements MapWrapper {
protected ArrayImage content;
protected MapController controller = new MapController() {
private final Map<UUID, Integer> viewers = new HashMap<>();
@Override
public void addViewer(Player player) throws MapLimitExceededException {
if (!isViewing(player)) {
viewers.put(player.getUniqueId(), MapReflectionAPI.getMapManager().getNextFreeIdFor(player));
}
}
@Override
public void removeViewer(OfflinePlayer player) {
viewers.remove(player.getUniqueId());
}
@Override
public void clearViewers() {
for (UUID uuid : viewers.keySet()) {
viewers.remove(uuid);
}
}
@Override
public boolean isViewing(OfflinePlayer player) {
if (player == null) return false;
return viewers.containsKey(player.getUniqueId());
}
@Override
public int getMapId(OfflinePlayer player) {
if (isViewing(player)) {
return viewers.get(player.getUniqueId());
}
return -1;
}
@Override
public void update(ArrayImage content) {
MapWrapper duplicate = MapReflectionAPI.getMapManager().getDuplicate(content);
if (duplicate != null) {
MapWrapper_v1_12_R1.this.content = duplicate.getContent();
return;
}
MapWrapper_v1_12_R1.this.content = content;
for (UUID id : viewers.keySet()) {
sendContent(Bukkit.getPlayer(id));
}
}
@Override
public ArrayImage getContent() {
return MapWrapper_v1_12_R1.this.getContent();
}
@Override
public void sendContent(Player player) {
sendContent(player, false);
}
@Override
public void sendContent(Player player, boolean withoutQueue) {
if (!isViewing(player)) return;
int id = getMapId(player);
if (withoutQueue) {
MapSender_v1_12_R1.sendMap(id, MapWrapper_v1_12_R1.this.content, player);
} else {
MapSender_v1_12_R1.addToQueue(id, MapWrapper_v1_12_R1.this.content, player);
}
}
@Override
public void showInInventory(Player player, int slot, boolean force) {
if (!isViewing(player)) return;
if (player.getGameMode() == GameMode.CREATIVE && !force) return;
if (slot < 9) {
slot += 36;
} else if (slot > 35 && slot != 45) {
slot = 8 - (slot - 36);
}
CraftPlayer craftPlayer = (CraftPlayer) player;
int windowId = craftPlayer.getHandle().defaultContainer.windowId;
ItemStack stack = new ItemStack(Material.MAP, 1);
net.minecraft.server.v1_12_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack);
PacketPlayOutSetSlot packet = new PacketPlayOutSetSlot(windowId, slot, nmsStack);
((EntityPlayer) player).playerConnection.sendPacket(packet);
}
@Override
public void showInInventory(Player player, int slot) {
showInInventory(player, slot, false);
}
@Override
public void showInHand(Player player, boolean force) {
if (player.getInventory().getItemInMainHand().getType() != Material.MAP && !force) return;
showInInventory(player, player.getInventory().getHeldItemSlot(), force);
}
@Override
public void showInHand(Player player) {
showInHand(player, false);
}
@Override
public void showInFrame(Player player, ItemFrame frame) {
showInFrame(player, frame, false);
}
@Override
public void showInFrame(Player player, ItemFrame frame, boolean force) {
if (frame.getItem().getType() != Material.MAP && !force) return;
showInFrame(player, frame.getEntityId());
}
@Override
public void showInFrame(Player player, int entityId) {
showInFrame(player, entityId, null);
}
@Override
public void showInFrame(Player player, int entityId, String debugInfo) {
if (!isViewing(player)) return;
ItemStack stack = new ItemStack(Material.MAP, 1);
if (debugInfo != null) {
ItemMeta itemMeta = stack.getItemMeta();
itemMeta.setDisplayName(debugInfo);
stack.setItemMeta(itemMeta);
}
Bukkit.getScheduler().runTask(MapReflectionAPI.getInstance(), () -> {
ItemFrame frame = getItemFrameById(player.getWorld(), entityId);
if (frame != null) {
frame.removeMetadata("MAP_WRAPPER_REF", MapReflectionAPI.getInstance());
frame.setMetadata("MAP_WRAPPER_REF", new FixedMetadataValue(MapReflectionAPI.getInstance(), MapWrapper_v1_12_R1.this));
}
sendItemFramePacket(player, entityId, stack, getMapId(player));
});
}
@Override
public void clearFrame(Player player, int entityId) {
}
@Override
public void clearFrame(Player player, ItemFrame frame) {
}
private ItemFrame getItemFrameById(World world, int entityId) {
CraftWorld craftWorld = (CraftWorld) world;
Entity entity = craftWorld.getHandle().getEntity(entityId);
if (entity == null) return null;
org.bukkit.entity.Entity bukkitEntity = entity.getBukkitEntity();
if (bukkitEntity instanceof ItemFrame) return (ItemFrame) bukkitEntity;
return null;
}
private void sendItemFramePacket(Player player, int entityId, ItemStack stack, int mapId) {
net.minecraft.server.v1_12_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack);
nmsStack.getTag().setInt("map", mapId);
DataWatcher watcher = new DataWatcher(null);
watcher.set(DataWatcher.a(EntityItemFrame.class, DataWatcherRegistry.f), nmsStack);
PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(entityId, watcher, true);
((EntityPlayer) player).playerConnection.sendPacket(packet);
}
};
@Override
public MapController getController() {
return controller;
}
@Override
public ArrayImage getContent() {
return content;
}
}

54
NMS-v1_13_R2/pom.xml Normal file
View file

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>MapReflectionAPI</artifactId>
<groupId>tech.sbdevelopment</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>MapReflectionAPI-NMS-v1_13_R2</artifactId>
<properties>
<NMSVersion>1.13.2-R0.1-SNAPSHOT</NMSVersion>
<jdk.version>11</jdk.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0-SNAPSHOT</version>
<configuration>
<release>${jdk.version}</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.0.0-M2</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>${NMSVersion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>tech.sbdevelopment</groupId>
<artifactId>MapReflectionAPI-API</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View file

@ -0,0 +1,116 @@
package tech.sbdevelopment.mapreflectionapi.nms;
import net.minecraft.server.v1_13_R2.PacketPlayOutMap;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer;
import org.bukkit.entity.Player;
import tech.sbdevelopment.mapreflectionapi.ArrayImage;
import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class MapSender_v1_13_R2 {
private static final List<QueuedMap> sendQueue = new ArrayList<>();
private static int senderID = -1;
public static void addToQueue(final int id, final ArrayImage content, final Player player) {
QueuedMap toSend = new QueuedMap(id, content, player);
if (sendQueue.contains(toSend)) return;
sendQueue.add(toSend);
runSender();
}
private static void runSender() {
if (Bukkit.getScheduler().isQueued(senderID) || Bukkit.getScheduler().isCurrentlyRunning(senderID) || sendQueue.isEmpty())
return;
senderID = Bukkit.getScheduler().scheduleSyncRepeatingTask(MapReflectionAPI.getInstance(), () -> {
if (sendQueue.isEmpty()) return;
for (int i = 0; i < Math.min(sendQueue.size(), 10 + 1); i++) {
QueuedMap current = sendQueue.get(0);
if (current == null) return;
sendMap(current.id, current.image, current.player);
if (!sendQueue.isEmpty()) sendQueue.remove(0);
}
}, 0, 2);
}
public static void sendMap(final int id0, final ArrayImage content, final Player player) {
if (player == null || !player.isOnline()) {
List<QueuedMap> toRemove = new ArrayList<>();
for (QueuedMap qMap : sendQueue) {
if (qMap == null) continue;
if (qMap.player == null || !qMap.player.isOnline()) {
toRemove.add(qMap);
}
}
Bukkit.getScheduler().cancelTask(senderID);
sendQueue.removeAll(toRemove);
return;
}
final int id = -id0;
Bukkit.getScheduler().runTaskAsynchronously(MapReflectionAPI.getInstance(), () -> {
try {
PacketPlayOutMap packet = new PacketPlayOutMap(
id, //ID
(byte) 0, //Scale
false, //???
new ArrayList<>(), //Icons
content.array, //Data
content.minX, //X pos
content.minY, //Y pos
content.maxX, //X size (2nd X pos)
content.maxY //Y size (2nd Y pos)
);
((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet);
} catch (Exception e) {
e.printStackTrace();
}
});
}
static final class QueuedMap {
private final int id;
private final ArrayImage image;
private final Player player;
QueuedMap(int id, ArrayImage image, Player player) {
this.id = id;
this.image = image;
this.player = player;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (QueuedMap) obj;
return this.id == that.id &&
Objects.equals(this.image, that.image) &&
Objects.equals(this.player, that.player);
}
@Override
public int hashCode() {
return Objects.hash(id, image, player);
}
@Override
public String toString() {
return "QueuedMap[" +
"id=" + id + ", " +
"image=" + image + ", " +
"player=" + player + ']';
}
}
}

View file

@ -0,0 +1,220 @@
package tech.sbdevelopment.mapreflectionapi.nms;
import net.minecraft.server.v1_13_R2.*;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.*;
import org.bukkit.craftbukkit.v1_13_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_13_R2.inventory.CraftItemStack;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.metadata.FixedMetadataValue;
import tech.sbdevelopment.mapreflectionapi.ArrayImage;
import tech.sbdevelopment.mapreflectionapi.MapController;
import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI;
import tech.sbdevelopment.mapreflectionapi.MapWrapper;
import tech.sbdevelopment.mapreflectionapi.exceptions.MapLimitExceededException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class MapWrapper_v1_13_R2 implements MapWrapper {
protected ArrayImage content;
protected MapController controller = new MapController() {
private final Map<UUID, Integer> viewers = new HashMap<>();
@Override
public void addViewer(Player player) throws MapLimitExceededException {
if (!isViewing(player)) {
viewers.put(player.getUniqueId(), MapReflectionAPI.getMapManager().getNextFreeIdFor(player));
}
}
@Override
public void removeViewer(OfflinePlayer player) {
viewers.remove(player.getUniqueId());
}
@Override
public void clearViewers() {
for (UUID uuid : viewers.keySet()) {
viewers.remove(uuid);
}
}
@Override
public boolean isViewing(OfflinePlayer player) {
if (player == null) return false;
return viewers.containsKey(player.getUniqueId());
}
@Override
public int getMapId(OfflinePlayer player) {
if (isViewing(player)) {
return viewers.get(player.getUniqueId());
}
return -1;
}
@Override
public void update(ArrayImage content) {
MapWrapper duplicate = MapReflectionAPI.getMapManager().getDuplicate(content);
if (duplicate != null) {
MapWrapper_v1_13_R2.this.content = duplicate.getContent();
return;
}
MapWrapper_v1_13_R2.this.content = content;
for (UUID id : viewers.keySet()) {
sendContent(Bukkit.getPlayer(id));
}
}
@Override
public ArrayImage getContent() {
return MapWrapper_v1_13_R2.this.getContent();
}
@Override
public void sendContent(Player player) {
sendContent(player, false);
}
@Override
public void sendContent(Player player, boolean withoutQueue) {
if (!isViewing(player)) return;
int id = getMapId(player);
if (withoutQueue) {
MapSender_v1_13_R2.sendMap(id, MapWrapper_v1_13_R2.this.content, player);
} else {
MapSender_v1_13_R2.addToQueue(id, MapWrapper_v1_13_R2.this.content, player);
}
}
@Override
public void showInInventory(Player player, int slot, boolean force) {
if (!isViewing(player)) return;
if (player.getGameMode() == GameMode.CREATIVE && !force) return;
if (slot < 9) {
slot += 36;
} else if (slot > 35 && slot != 45) {
slot = 8 - (slot - 36);
}
CraftPlayer craftPlayer = (CraftPlayer) player;
int windowId = craftPlayer.getHandle().defaultContainer.windowId;
ItemStack stack = new ItemStack(Material.MAP, 1);
net.minecraft.server.v1_13_R2.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack);
PacketPlayOutSetSlot packet = new PacketPlayOutSetSlot(windowId, slot, nmsStack);
((EntityPlayer) player).playerConnection.sendPacket(packet);
}
@Override
public void showInInventory(Player player, int slot) {
showInInventory(player, slot, false);
}
@Override
public void showInHand(Player player, boolean force) {
if (player.getInventory().getItemInMainHand().getType() != Material.MAP && !force) return;
showInInventory(player, player.getInventory().getHeldItemSlot(), force);
}
@Override
public void showInHand(Player player) {
showInHand(player, false);
}
@Override
public void showInFrame(Player player, ItemFrame frame) {
showInFrame(player, frame, false);
}
@Override
public void showInFrame(Player player, ItemFrame frame, boolean force) {
if (frame.getItem().getType() != Material.MAP && !force) return;
showInFrame(player, frame.getEntityId());
}
@Override
public void showInFrame(Player player, int entityId) {
showInFrame(player, entityId, null);
}
@Override
public void showInFrame(Player player, int entityId, String debugInfo) {
if (!isViewing(player)) return;
ItemStack stack = new ItemStack(Material.MAP, 1);
if (debugInfo != null) {
ItemMeta itemMeta = stack.getItemMeta();
itemMeta.setDisplayName(debugInfo);
stack.setItemMeta(itemMeta);
}
Bukkit.getScheduler().runTask(MapReflectionAPI.getInstance(), () -> {
ItemFrame frame = getItemFrameById(player.getWorld(), entityId);
if (frame != null) {
frame.removeMetadata("MAP_WRAPPER_REF", MapReflectionAPI.getInstance());
frame.setMetadata("MAP_WRAPPER_REF", new FixedMetadataValue(MapReflectionAPI.getInstance(), MapWrapper_v1_13_R2.this));
}
sendItemFramePacket(player, entityId, stack, getMapId(player));
});
}
@Override
public void clearFrame(Player player, int entityId) {
}
@Override
public void clearFrame(Player player, ItemFrame frame) {
}
private ItemFrame getItemFrameById(World world, int entityId) {
CraftWorld craftWorld = (CraftWorld) world;
Entity entity = craftWorld.getHandle().getEntity(entityId);
if (entity == null) return null;
org.bukkit.entity.Entity bukkitEntity = entity.getBukkitEntity();
if (bukkitEntity instanceof ItemFrame) return (ItemFrame) bukkitEntity;
return null;
}
private void sendItemFramePacket(Player player, int entityId, ItemStack stack, int mapId) {
net.minecraft.server.v1_13_R2.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack);
nmsStack.getOrCreateTag().setInt("map", mapId);
DataWatcher watcher = new DataWatcher(null);
watcher.set(DataWatcher.a(EntityItemFrame.class, DataWatcherRegistry.g), nmsStack);
PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(entityId, watcher, true);
((EntityPlayer) player).playerConnection.sendPacket(packet);
}
};
@Override
public MapController getController() {
return controller;
}
@Override
public ArrayImage getContent() {
return content;
}
}

54
NMS-v1_14_R1/pom.xml Normal file
View file

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>MapReflectionAPI</artifactId>
<groupId>tech.sbdevelopment</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>MapReflectionAPI-NMS-v1_14_R1</artifactId>
<properties>
<NMSVersion>1.14.4-R0.1-SNAPSHOT</NMSVersion>
<jdk.version>11</jdk.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0-SNAPSHOT</version>
<configuration>
<release>${jdk.version}</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.0.0-M2</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>${NMSVersion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>tech.sbdevelopment</groupId>
<artifactId>MapReflectionAPI-API</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View file

@ -0,0 +1,117 @@
package tech.sbdevelopment.mapreflectionapi.nms;
import net.minecraft.server.v1_14_R1.PacketPlayOutMap;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import tech.sbdevelopment.mapreflectionapi.ArrayImage;
import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class MapSender_v1_14_R1 {
private static final List<QueuedMap> sendQueue = new ArrayList<>();
private static int senderID = -1;
public static void addToQueue(final int id, final ArrayImage content, final Player player) {
QueuedMap toSend = new QueuedMap(id, content, player);
if (sendQueue.contains(toSend)) return;
sendQueue.add(toSend);
runSender();
}
private static void runSender() {
if (Bukkit.getScheduler().isQueued(senderID) || Bukkit.getScheduler().isCurrentlyRunning(senderID) || sendQueue.isEmpty())
return;
senderID = Bukkit.getScheduler().scheduleSyncRepeatingTask(MapReflectionAPI.getInstance(), () -> {
if (sendQueue.isEmpty()) return;
for (int i = 0; i < Math.min(sendQueue.size(), 10 + 1); i++) {
QueuedMap current = sendQueue.get(0);
if (current == null) return;
sendMap(current.id, current.image, current.player);
if (!sendQueue.isEmpty()) sendQueue.remove(0);
}
}, 0, 2);
}
public static void sendMap(final int id0, final ArrayImage content, final Player player) {
if (player == null || !player.isOnline()) {
List<QueuedMap> toRemove = new ArrayList<>();
for (QueuedMap qMap : sendQueue) {
if (qMap == null) continue;
if (qMap.player == null || !qMap.player.isOnline()) {
toRemove.add(qMap);
}
}
Bukkit.getScheduler().cancelTask(senderID);
sendQueue.removeAll(toRemove);
return;
}
final int id = -id0;
Bukkit.getScheduler().runTaskAsynchronously(MapReflectionAPI.getInstance(), () -> {
try {
PacketPlayOutMap packet = new PacketPlayOutMap(
id, //ID
(byte) 0, //Scale
false, //Tracking position
false, //Locked
new ArrayList<>(), //Icons
content.array, //Data
content.minX, //X pos
content.minY, //Y pos
content.maxX, //X size (2nd X pos)
content.maxY //Y size (2nd Y pos)
);
((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet);
} catch (Exception e) {
e.printStackTrace();
}
});
}
static final class QueuedMap {
private final int id;
private final ArrayImage image;
private final Player player;
QueuedMap(int id, ArrayImage image, Player player) {
this.id = id;
this.image = image;
this.player = player;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (QueuedMap) obj;
return this.id == that.id &&
Objects.equals(this.image, that.image) &&
Objects.equals(this.player, that.player);
}
@Override
public int hashCode() {
return Objects.hash(id, image, player);
}
@Override
public String toString() {
return "QueuedMap[" +
"id=" + id + ", " +
"image=" + image + ", " +
"player=" + player + ']';
}
}
}

View file

@ -0,0 +1,220 @@
package tech.sbdevelopment.mapreflectionapi.nms;
import net.minecraft.server.v1_14_R1.*;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.*;
import org.bukkit.craftbukkit.v1_14_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftItemStack;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.metadata.FixedMetadataValue;
import tech.sbdevelopment.mapreflectionapi.ArrayImage;
import tech.sbdevelopment.mapreflectionapi.MapController;
import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI;
import tech.sbdevelopment.mapreflectionapi.MapWrapper;
import tech.sbdevelopment.mapreflectionapi.exceptions.MapLimitExceededException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class MapWrapper_v1_14_R1 implements MapWrapper {
protected ArrayImage content;
protected MapController controller = new MapController() {
private final Map<UUID, Integer> viewers = new HashMap<>();
@Override
public void addViewer(Player player) throws MapLimitExceededException {
if (!isViewing(player)) {
viewers.put(player.getUniqueId(), MapReflectionAPI.getMapManager().getNextFreeIdFor(player));
}
}
@Override
public void removeViewer(OfflinePlayer player) {
viewers.remove(player.getUniqueId());
}
@Override
public void clearViewers() {
for (UUID uuid : viewers.keySet()) {
viewers.remove(uuid);
}
}
@Override
public boolean isViewing(OfflinePlayer player) {
if (player == null) return false;
return viewers.containsKey(player.getUniqueId());
}
@Override
public int getMapId(OfflinePlayer player) {
if (isViewing(player)) {
return viewers.get(player.getUniqueId());
}
return -1;
}
@Override
public void update(ArrayImage content) {
MapWrapper duplicate = MapReflectionAPI.getMapManager().getDuplicate(content);
if (duplicate != null) {
MapWrapper_v1_14_R1.this.content = duplicate.getContent();
return;
}
MapWrapper_v1_14_R1.this.content = content;
for (UUID id : viewers.keySet()) {
sendContent(Bukkit.getPlayer(id));
}
}
@Override
public ArrayImage getContent() {
return MapWrapper_v1_14_R1.this.getContent();
}
@Override
public void sendContent(Player player) {
sendContent(player, false);
}
@Override
public void sendContent(Player player, boolean withoutQueue) {
if (!isViewing(player)) return;
int id = getMapId(player);
if (withoutQueue) {
MapSender_v1_14_R1.sendMap(id, MapWrapper_v1_14_R1.this.content, player);
} else {
MapSender_v1_14_R1.addToQueue(id, MapWrapper_v1_14_R1.this.content, player);
}
}
@Override
public void showInInventory(Player player, int slot, boolean force) {
if (!isViewing(player)) return;
if (player.getGameMode() == GameMode.CREATIVE && !force) return;
if (slot < 9) {
slot += 36;
} else if (slot > 35 && slot != 45) {
slot = 8 - (slot - 36);
}
CraftPlayer craftPlayer = (CraftPlayer) player;
int windowId = craftPlayer.getHandle().defaultContainer.windowId;
ItemStack stack = new ItemStack(Material.MAP, 1);
net.minecraft.server.v1_14_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack);
PacketPlayOutSetSlot packet = new PacketPlayOutSetSlot(windowId, slot, nmsStack);
((EntityPlayer) player).playerConnection.sendPacket(packet);
}
@Override
public void showInInventory(Player player, int slot) {
showInInventory(player, slot, false);
}
@Override
public void showInHand(Player player, boolean force) {
if (player.getInventory().getItemInMainHand().getType() != Material.MAP && !force) return;
showInInventory(player, player.getInventory().getHeldItemSlot(), force);
}
@Override
public void showInHand(Player player) {
showInHand(player, false);
}
@Override
public void showInFrame(Player player, ItemFrame frame) {
showInFrame(player, frame, false);
}
@Override
public void showInFrame(Player player, ItemFrame frame, boolean force) {
if (frame.getItem().getType() != Material.MAP && !force) return;
showInFrame(player, frame.getEntityId());
}
@Override
public void showInFrame(Player player, int entityId) {
showInFrame(player, entityId, null);
}
@Override
public void showInFrame(Player player, int entityId, String debugInfo) {
if (!isViewing(player)) return;
ItemStack stack = new ItemStack(Material.MAP, 1);
if (debugInfo != null) {
ItemMeta itemMeta = stack.getItemMeta();
itemMeta.setDisplayName(debugInfo);
stack.setItemMeta(itemMeta);
}
Bukkit.getScheduler().runTask(MapReflectionAPI.getInstance(), () -> {
ItemFrame frame = getItemFrameById(player.getWorld(), entityId);
if (frame != null) {
frame.removeMetadata("MAP_WRAPPER_REF", MapReflectionAPI.getInstance());
frame.setMetadata("MAP_WRAPPER_REF", new FixedMetadataValue(MapReflectionAPI.getInstance(), MapWrapper_v1_14_R1.this));
}
sendItemFramePacket(player, entityId, stack, getMapId(player));
});
}
@Override
public void clearFrame(Player player, int entityId) {
}
@Override
public void clearFrame(Player player, ItemFrame frame) {
}
private ItemFrame getItemFrameById(World world, int entityId) {
CraftWorld craftWorld = (CraftWorld) world;
Entity entity = craftWorld.getHandle().getEntity(entityId);
if (entity == null) return null;
org.bukkit.entity.Entity bukkitEntity = entity.getBukkitEntity();
if (bukkitEntity instanceof ItemFrame) return (ItemFrame) bukkitEntity;
return null;
}
private void sendItemFramePacket(Player player, int entityId, ItemStack stack, int mapId) {
net.minecraft.server.v1_14_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack);
nmsStack.getOrCreateTag().setInt("map", mapId);
DataWatcher watcher = new DataWatcher(null);
watcher.set(DataWatcher.a(EntityItemFrame.class, DataWatcherRegistry.g), nmsStack);
PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(entityId, watcher, true);
((EntityPlayer) player).playerConnection.sendPacket(packet);
}
};
@Override
public MapController getController() {
return controller;
}
@Override
public ArrayImage getContent() {
return content;
}
}

54
NMS-v1_15_R1/pom.xml Normal file
View file

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>MapReflectionAPI</artifactId>
<groupId>tech.sbdevelopment</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>MapReflectionAPI-NMS-v1_15_R1</artifactId>
<properties>
<NMSVersion>1.15.2-R0.1-SNAPSHOT</NMSVersion>
<jdk.version>11</jdk.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0-SNAPSHOT</version>
<configuration>
<release>${jdk.version}</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.0.0-M2</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>${NMSVersion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>tech.sbdevelopment</groupId>
<artifactId>MapReflectionAPI-API</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View file

@ -0,0 +1,117 @@
package tech.sbdevelopment.mapreflectionapi.nms;
import net.minecraft.server.v1_15_R1.PacketPlayOutMap;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import tech.sbdevelopment.mapreflectionapi.ArrayImage;
import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class MapSender_v1_15_R1 {
private static final List<QueuedMap> sendQueue = new ArrayList<>();
private static int senderID = -1;
public static void addToQueue(final int id, final ArrayImage content, final Player player) {
QueuedMap toSend = new QueuedMap(id, content, player);
if (sendQueue.contains(toSend)) return;
sendQueue.add(toSend);
runSender();
}
private static void runSender() {
if (Bukkit.getScheduler().isQueued(senderID) || Bukkit.getScheduler().isCurrentlyRunning(senderID) || sendQueue.isEmpty())
return;
senderID = Bukkit.getScheduler().scheduleSyncRepeatingTask(MapReflectionAPI.getInstance(), () -> {
if (sendQueue.isEmpty()) return;
for (int i = 0; i < Math.min(sendQueue.size(), 10 + 1); i++) {
QueuedMap current = sendQueue.get(0);
if (current == null) return;
sendMap(current.id, current.image, current.player);
if (!sendQueue.isEmpty()) sendQueue.remove(0);
}
}, 0, 2);
}
public static void sendMap(final int id0, final ArrayImage content, final Player player) {
if (player == null || !player.isOnline()) {
List<QueuedMap> toRemove = new ArrayList<>();
for (QueuedMap qMap : sendQueue) {
if (qMap == null) continue;
if (qMap.player == null || !qMap.player.isOnline()) {
toRemove.add(qMap);
}
}
Bukkit.getScheduler().cancelTask(senderID);
sendQueue.removeAll(toRemove);
return;
}
final int id = -id0;
Bukkit.getScheduler().runTaskAsynchronously(MapReflectionAPI.getInstance(), () -> {
try {
PacketPlayOutMap packet = new PacketPlayOutMap(
id, //ID
(byte) 0, //Scale
false, //Tracking position
false, //Locked
new ArrayList<>(), //Icons
content.array, //Data
content.minX, //X pos
content.minY, //Y pos
content.maxX, //X size (2nd X pos)
content.maxY //Y size (2nd Y pos)
);
((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet);
} catch (Exception e) {
e.printStackTrace();
}
});
}
static final class QueuedMap {
private final int id;
private final ArrayImage image;
private final Player player;
QueuedMap(int id, ArrayImage image, Player player) {
this.id = id;
this.image = image;
this.player = player;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (QueuedMap) obj;
return this.id == that.id &&
Objects.equals(this.image, that.image) &&
Objects.equals(this.player, that.player);
}
@Override
public int hashCode() {
return Objects.hash(id, image, player);
}
@Override
public String toString() {
return "QueuedMap[" +
"id=" + id + ", " +
"image=" + image + ", " +
"player=" + player + ']';
}
}
}

View file

@ -0,0 +1,220 @@
package tech.sbdevelopment.mapreflectionapi.nms;
import net.minecraft.server.v1_15_R1.*;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.*;
import org.bukkit.craftbukkit.v1_15_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.metadata.FixedMetadataValue;
import tech.sbdevelopment.mapreflectionapi.ArrayImage;
import tech.sbdevelopment.mapreflectionapi.MapController;
import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI;
import tech.sbdevelopment.mapreflectionapi.MapWrapper;
import tech.sbdevelopment.mapreflectionapi.exceptions.MapLimitExceededException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class MapWrapper_v1_15_R1 implements MapWrapper {
protected ArrayImage content;
protected MapController controller = new MapController() {
private final Map<UUID, Integer> viewers = new HashMap<>();
@Override
public void addViewer(Player player) throws MapLimitExceededException {
if (!isViewing(player)) {
viewers.put(player.getUniqueId(), MapReflectionAPI.getMapManager().getNextFreeIdFor(player));
}
}
@Override
public void removeViewer(OfflinePlayer player) {
viewers.remove(player.getUniqueId());
}
@Override
public void clearViewers() {
for (UUID uuid : viewers.keySet()) {
viewers.remove(uuid);
}
}
@Override
public boolean isViewing(OfflinePlayer player) {
if (player == null) return false;
return viewers.containsKey(player.getUniqueId());
}
@Override
public int getMapId(OfflinePlayer player) {
if (isViewing(player)) {
return viewers.get(player.getUniqueId());
}
return -1;
}
@Override
public void update(ArrayImage content) {
MapWrapper duplicate = MapReflectionAPI.getMapManager().getDuplicate(content);
if (duplicate != null) {
MapWrapper_v1_15_R1.this.content = duplicate.getContent();
return;
}
MapWrapper_v1_15_R1.this.content = content;
for (UUID id : viewers.keySet()) {
sendContent(Bukkit.getPlayer(id));
}
}
@Override
public ArrayImage getContent() {
return MapWrapper_v1_15_R1.this.getContent();
}
@Override
public void sendContent(Player player) {
sendContent(player, false);
}
@Override
public void sendContent(Player player, boolean withoutQueue) {
if (!isViewing(player)) return;
int id = getMapId(player);
if (withoutQueue) {
MapSender_v1_15_R1.sendMap(id, MapWrapper_v1_15_R1.this.content, player);
} else {
MapSender_v1_15_R1.addToQueue(id, MapWrapper_v1_15_R1.this.content, player);
}
}
@Override
public void showInInventory(Player player, int slot, boolean force) {
if (!isViewing(player)) return;
if (player.getGameMode() == GameMode.CREATIVE && !force) return;
if (slot < 9) {
slot += 36;
} else if (slot > 35 && slot != 45) {
slot = 8 - (slot - 36);
}
CraftPlayer craftPlayer = (CraftPlayer) player;
int windowId = craftPlayer.getHandle().defaultContainer.windowId;
ItemStack stack = new ItemStack(Material.MAP, 1);
net.minecraft.server.v1_15_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack);
PacketPlayOutSetSlot packet = new PacketPlayOutSetSlot(windowId, slot, nmsStack);
((EntityPlayer) player).playerConnection.sendPacket(packet);
}
@Override
public void showInInventory(Player player, int slot) {
showInInventory(player, slot, false);
}
@Override
public void showInHand(Player player, boolean force) {
if (player.getInventory().getItemInMainHand().getType() != Material.MAP && !force) return;
showInInventory(player, player.getInventory().getHeldItemSlot(), force);
}
@Override
public void showInHand(Player player) {
showInHand(player, false);
}
@Override
public void showInFrame(Player player, ItemFrame frame) {
showInFrame(player, frame, false);
}
@Override
public void showInFrame(Player player, ItemFrame frame, boolean force) {
if (frame.getItem().getType() != Material.MAP && !force) return;
showInFrame(player, frame.getEntityId());
}
@Override
public void showInFrame(Player player, int entityId) {
showInFrame(player, entityId, null);
}
@Override
public void showInFrame(Player player, int entityId, String debugInfo) {
if (!isViewing(player)) return;
ItemStack stack = new ItemStack(Material.MAP, 1);
if (debugInfo != null) {
ItemMeta itemMeta = stack.getItemMeta();
itemMeta.setDisplayName(debugInfo);
stack.setItemMeta(itemMeta);
}
Bukkit.getScheduler().runTask(MapReflectionAPI.getInstance(), () -> {
ItemFrame frame = getItemFrameById(player.getWorld(), entityId);
if (frame != null) {
frame.removeMetadata("MAP_WRAPPER_REF", MapReflectionAPI.getInstance());
frame.setMetadata("MAP_WRAPPER_REF", new FixedMetadataValue(MapReflectionAPI.getInstance(), MapWrapper_v1_15_R1.this));
}
sendItemFramePacket(player, entityId, stack, getMapId(player));
});
}
@Override
public void clearFrame(Player player, int entityId) {
}
@Override
public void clearFrame(Player player, ItemFrame frame) {
}
private ItemFrame getItemFrameById(World world, int entityId) {
CraftWorld craftWorld = (CraftWorld) world;
Entity entity = craftWorld.getHandle().getEntity(entityId);
if (entity == null) return null;
org.bukkit.entity.Entity bukkitEntity = entity.getBukkitEntity();
if (bukkitEntity instanceof ItemFrame) return (ItemFrame) bukkitEntity;
return null;
}
private void sendItemFramePacket(Player player, int entityId, ItemStack stack, int mapId) {
net.minecraft.server.v1_15_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack);
nmsStack.getOrCreateTag().setInt("map", mapId);
DataWatcher watcher = new DataWatcher(null);
watcher.set(DataWatcher.a(EntityItemFrame.class, DataWatcherRegistry.g), nmsStack);
PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(entityId, watcher, true);
((EntityPlayer) player).playerConnection.sendPacket(packet);
}
};
@Override
public MapController getController() {
return controller;
}
@Override
public ArrayImage getContent() {
return content;
}
}

54
NMS-v1_16_R3/pom.xml Normal file
View file

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>MapReflectionAPI</artifactId>
<groupId>tech.sbdevelopment</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>MapReflectionAPI-NMS-v1_16_R3</artifactId>
<properties>
<NMSVersion>1.16.4-R0.1-SNAPSHOT</NMSVersion>
<jdk.version>11</jdk.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0-SNAPSHOT</version>
<configuration>
<release>${jdk.version}</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.0.0-M2</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>${NMSVersion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>tech.sbdevelopment</groupId>
<artifactId>MapReflectionAPI-API</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View file

@ -0,0 +1,117 @@
package tech.sbdevelopment.mapreflectionapi.nms;
import net.minecraft.server.v1_16_R3.PacketPlayOutMap;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
import org.bukkit.entity.Player;
import tech.sbdevelopment.mapreflectionapi.ArrayImage;
import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class MapSender_v1_16_R3 {
private static final List<QueuedMap> sendQueue = new ArrayList<>();
private static int senderID = -1;
public static void addToQueue(final int id, final ArrayImage content, final Player player) {
QueuedMap toSend = new QueuedMap(id, content, player);
if (sendQueue.contains(toSend)) return;
sendQueue.add(toSend);
runSender();
}
private static void runSender() {
if (Bukkit.getScheduler().isQueued(senderID) || Bukkit.getScheduler().isCurrentlyRunning(senderID) || sendQueue.isEmpty())
return;
senderID = Bukkit.getScheduler().scheduleSyncRepeatingTask(MapReflectionAPI.getInstance(), () -> {
if (sendQueue.isEmpty()) return;
for (int i = 0; i < Math.min(sendQueue.size(), 10 + 1); i++) {
QueuedMap current = sendQueue.get(0);
if (current == null) return;
sendMap(current.id, current.image, current.player);
if (!sendQueue.isEmpty()) sendQueue.remove(0);
}
}, 0, 2);
}
public static void sendMap(final int id0, final ArrayImage content, final Player player) {
if (player == null || !player.isOnline()) {
List<QueuedMap> toRemove = new ArrayList<>();
for (QueuedMap qMap : sendQueue) {
if (qMap == null) continue;
if (qMap.player == null || !qMap.player.isOnline()) {
toRemove.add(qMap);
}
}
Bukkit.getScheduler().cancelTask(senderID);
sendQueue.removeAll(toRemove);
return;
}
final int id = -id0;
Bukkit.getScheduler().runTaskAsynchronously(MapReflectionAPI.getInstance(), () -> {
try {
PacketPlayOutMap packet = new PacketPlayOutMap(
id, //ID
(byte) 0, //Scale
false, //Tracking position
false, //Locked
new ArrayList<>(), //Icons
content.array, //Data
content.minX, //X pos
content.minY, //Y pos
content.maxX, //X size (2nd X pos)
content.maxY //Y size (2nd Y pos)
);
((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet);
} catch (Exception e) {
e.printStackTrace();
}
});
}
static final class QueuedMap {
private final int id;
private final ArrayImage image;
private final Player player;
QueuedMap(int id, ArrayImage image, Player player) {
this.id = id;
this.image = image;
this.player = player;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (QueuedMap) obj;
return this.id == that.id &&
Objects.equals(this.image, that.image) &&
Objects.equals(this.player, that.player);
}
@Override
public int hashCode() {
return Objects.hash(id, image, player);
}
@Override
public String toString() {
return "QueuedMap[" +
"id=" + id + ", " +
"image=" + image + ", " +
"player=" + player + ']';
}
}
}

View file

@ -0,0 +1,220 @@
package tech.sbdevelopment.mapreflectionapi.nms;
import net.minecraft.server.v1_16_R3.*;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.*;
import org.bukkit.craftbukkit.v1_16_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.metadata.FixedMetadataValue;
import tech.sbdevelopment.mapreflectionapi.ArrayImage;
import tech.sbdevelopment.mapreflectionapi.MapController;
import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI;
import tech.sbdevelopment.mapreflectionapi.MapWrapper;
import tech.sbdevelopment.mapreflectionapi.exceptions.MapLimitExceededException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class MapWrapper_v1_16_R3 implements MapWrapper {
protected ArrayImage content;
protected MapController controller = new MapController() {
private final Map<UUID, Integer> viewers = new HashMap<>();
@Override
public void addViewer(Player player) throws MapLimitExceededException {
if (!isViewing(player)) {
viewers.put(player.getUniqueId(), MapReflectionAPI.getMapManager().getNextFreeIdFor(player));
}
}
@Override
public void removeViewer(OfflinePlayer player) {
viewers.remove(player.getUniqueId());
}
@Override
public void clearViewers() {
for (UUID uuid : viewers.keySet()) {
viewers.remove(uuid);
}
}
@Override
public boolean isViewing(OfflinePlayer player) {
if (player == null) return false;
return viewers.containsKey(player.getUniqueId());
}
@Override
public int getMapId(OfflinePlayer player) {
if (isViewing(player)) {
return viewers.get(player.getUniqueId());
}
return -1;
}
@Override
public void update(ArrayImage content) {
MapWrapper duplicate = MapReflectionAPI.getMapManager().getDuplicate(content);
if (duplicate != null) {
MapWrapper_v1_16_R3.this.content = duplicate.getContent();
return;
}
MapWrapper_v1_16_R3.this.content = content;
for (UUID id : viewers.keySet()) {
sendContent(Bukkit.getPlayer(id));
}
}
@Override
public ArrayImage getContent() {
return MapWrapper_v1_16_R3.this.getContent();
}
@Override
public void sendContent(Player player) {
sendContent(player, false);
}
@Override
public void sendContent(Player player, boolean withoutQueue) {
if (!isViewing(player)) return;
int id = getMapId(player);
if (withoutQueue) {
MapSender_v1_16_R3.sendMap(id, MapWrapper_v1_16_R3.this.content, player);
} else {
MapSender_v1_16_R3.addToQueue(id, MapWrapper_v1_16_R3.this.content, player);
}
}
@Override
public void showInInventory(Player player, int slot, boolean force) {
if (!isViewing(player)) return;
if (player.getGameMode() == GameMode.CREATIVE && !force) return;
if (slot < 9) {
slot += 36;
} else if (slot > 35 && slot != 45) {
slot = 8 - (slot - 36);
}
CraftPlayer craftPlayer = (CraftPlayer) player;
int windowId = craftPlayer.getHandle().defaultContainer.windowId;
ItemStack stack = new ItemStack(Material.MAP, 1);
net.minecraft.server.v1_16_R3.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack);
PacketPlayOutSetSlot packet = new PacketPlayOutSetSlot(windowId, slot, nmsStack);
((EntityPlayer) player).playerConnection.sendPacket(packet);
}
@Override
public void showInInventory(Player player, int slot) {
showInInventory(player, slot, false);
}
@Override
public void showInHand(Player player, boolean force) {
if (player.getInventory().getItemInMainHand().getType() != Material.MAP && !force) return;
showInInventory(player, player.getInventory().getHeldItemSlot(), force);
}
@Override
public void showInHand(Player player) {
showInHand(player, false);
}
@Override
public void showInFrame(Player player, ItemFrame frame) {
showInFrame(player, frame, false);
}
@Override
public void showInFrame(Player player, ItemFrame frame, boolean force) {
if (frame.getItem().getType() != Material.MAP && !force) return;
showInFrame(player, frame.getEntityId());
}
@Override
public void showInFrame(Player player, int entityId) {
showInFrame(player, entityId, null);
}
@Override
public void showInFrame(Player player, int entityId, String debugInfo) {
if (!isViewing(player)) return;
ItemStack stack = new ItemStack(Material.MAP, 1);
if (debugInfo != null) {
ItemMeta itemMeta = stack.getItemMeta();
itemMeta.setDisplayName(debugInfo);
stack.setItemMeta(itemMeta);
}
Bukkit.getScheduler().runTask(MapReflectionAPI.getInstance(), () -> {
ItemFrame frame = getItemFrameById(player.getWorld(), entityId);
if (frame != null) {
frame.removeMetadata("MAP_WRAPPER_REF", MapReflectionAPI.getInstance());
frame.setMetadata("MAP_WRAPPER_REF", new FixedMetadataValue(MapReflectionAPI.getInstance(), MapWrapper_v1_16_R3.this));
}
sendItemFramePacket(player, entityId, stack, getMapId(player));
});
}
@Override
public void clearFrame(Player player, int entityId) {
}
@Override
public void clearFrame(Player player, ItemFrame frame) {
}
private ItemFrame getItemFrameById(World world, int entityId) {
CraftWorld craftWorld = (CraftWorld) world;
Entity entity = craftWorld.getHandle().getEntity(entityId);
if (entity == null) return null;
org.bukkit.entity.Entity bukkitEntity = entity.getBukkitEntity();
if (bukkitEntity instanceof ItemFrame) return (ItemFrame) bukkitEntity;
return null;
}
private void sendItemFramePacket(Player player, int entityId, ItemStack stack, int mapId) {
net.minecraft.server.v1_16_R3.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack);
nmsStack.getOrCreateTag().setInt("map", mapId);
DataWatcher watcher = new DataWatcher(null);
watcher.set(DataWatcher.a(EntityItemFrame.class, DataWatcherRegistry.g), nmsStack);
PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(entityId, watcher, true);
((EntityPlayer) player).playerConnection.sendPacket(packet);
}
};
@Override
public MapController getController() {
return controller;
}
@Override
public ArrayImage getContent() {
return content;
}
}

98
NMS-v1_17_R1/pom.xml Normal file
View file

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>MapReflectionAPI</artifactId>
<groupId>tech.sbdevelopment</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>MapReflectionAPI-NMS-v1_17_R1</artifactId>
<properties>
<NMSVersion>1.17.1-R0.1-SNAPSHOT</NMSVersion>
<jdk.version>16</jdk.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0-SNAPSHOT</version>
<configuration>
<release>${jdk.version}</release>
</configuration>
</plugin>
<plugin>
<groupId>net.md-5</groupId>
<artifactId>specialsource-maven-plugin</artifactId>
<version>1.2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>remap</goal>
</goals>
<id>remap-obf</id>
<configuration>
<srgIn>org.spigotmc:minecraft-server:${NMSVersion}:txt:maps-mojang</srgIn>
<reverse>true</reverse>
<remappedDependencies>org.spigotmc:spigot:${NMSVersion}:jar:remapped-mojang
</remappedDependencies>
<remappedArtifactAttached>true</remappedArtifactAttached>
<remappedClassifierName>remapped-obf</remappedClassifierName>
</configuration>
</execution>
<execution>
<phase>package</phase>
<goals>
<goal>remap</goal>
</goals>
<id>remap-spigot</id>
<configuration>
<inputFile>
${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar
</inputFile>
<srgIn>org.spigotmc:minecraft-server:${NMSVersion}:csrg:maps-spigot</srgIn>
<remappedDependencies>org.spigotmc:spigot:${NMSVersion}:jar:remapped-obf
</remappedDependencies>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.0.0-M2</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>minecraft-server</artifactId>
<version>${NMSVersion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>${NMSVersion}</version>
<classifier>remapped-mojang</classifier>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>tech.sbdevelopment</groupId>
<artifactId>MapReflectionAPI-API</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View file

@ -0,0 +1,88 @@
package tech.sbdevelopment.mapreflectionapi.nms;
import net.minecraft.network.protocol.game.PacketPlayOutMap;
import net.minecraft.world.level.saveddata.maps.WorldMap;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import tech.sbdevelopment.mapreflectionapi.ArrayImage;
import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI;
import java.util.ArrayList;
import java.util.List;
public class MapSender_v1_17_R1 {
private static final List<QueuedMap> sendQueue = new ArrayList<>();
private static int senderID = -1;
public static void addToQueue(final int id, final ArrayImage content, final Player player) {
QueuedMap toSend = new QueuedMap(id, content, player);
if (sendQueue.contains(toSend)) return;
sendQueue.add(toSend);
runSender();
}
private static void runSender() {
if (Bukkit.getScheduler().isQueued(senderID) || Bukkit.getScheduler().isCurrentlyRunning(senderID) || sendQueue.isEmpty())
return;
senderID = Bukkit.getScheduler().scheduleSyncRepeatingTask(MapReflectionAPI.getInstance(), () -> {
if (sendQueue.isEmpty()) return;
for (int i = 0; i < Math.min(sendQueue.size(), 10 + 1); i++) {
QueuedMap current = sendQueue.get(0);
if (current == null) return;
sendMap(current.id, current.image, current.player);
if (!sendQueue.isEmpty()) sendQueue.remove(0);
}
}, 0, 2);
}
public static void sendMap(final int id0, final ArrayImage content, final Player player) {
if (player == null || !player.isOnline()) {
List<QueuedMap> toRemove = new ArrayList<>();
for (QueuedMap qMap : sendQueue) {
if (qMap == null) continue;
if (qMap.player == null || !qMap.player.isOnline()) {
toRemove.add(qMap);
}
}
Bukkit.getScheduler().cancelTask(senderID);
sendQueue.removeAll(toRemove);
return;
}
final int id = -id0;
Bukkit.getScheduler().runTaskAsynchronously(MapReflectionAPI.getInstance(), () -> {
try {
WorldMap.b updateData = new WorldMap.b(
content.minX, //X pos
content.minY, //Y pos
content.maxX, //X size (2nd X pos)
content.maxY, //Y size (2nd Y pos)
content.array //Data
);
PacketPlayOutMap packet = new PacketPlayOutMap(
id, //ID
(byte) 0, //Scale
false, //Show icons
new ArrayList<>(), //Icons
updateData
);
((CraftPlayer) player).getHandle().connection.send(packet);
} catch (Exception e) {
e.printStackTrace();
}
});
}
record QueuedMap(int id, ArrayImage image, Player player) {
}
}

View file

@ -0,0 +1,224 @@
package tech.sbdevelopment.mapreflectionapi.nms;
import net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata;
import net.minecraft.network.protocol.game.PacketPlayOutSetSlot;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherRegistry;
import net.minecraft.server.level.EntityPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.decoration.EntityItemFrame;
import org.bukkit.*;
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.metadata.FixedMetadataValue;
import tech.sbdevelopment.mapreflectionapi.ArrayImage;
import tech.sbdevelopment.mapreflectionapi.MapController;
import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI;
import tech.sbdevelopment.mapreflectionapi.MapWrapper;
import tech.sbdevelopment.mapreflectionapi.exceptions.MapLimitExceededException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class MapWrapper_v1_17_R1 implements MapWrapper {
protected ArrayImage content;
protected MapController controller = new MapController() {
private final Map<UUID, Integer> viewers = new HashMap<>();
@Override
public void addViewer(Player player) throws MapLimitExceededException {
if (!isViewing(player)) {
viewers.put(player.getUniqueId(), MapReflectionAPI.getMapManager().getNextFreeIdFor(player));
}
}
@Override
public void removeViewer(OfflinePlayer player) {
viewers.remove(player.getUniqueId());
}
@Override
public void clearViewers() {
for (UUID uuid : viewers.keySet()) {
viewers.remove(uuid);
}
}
@Override
public boolean isViewing(OfflinePlayer player) {
if (player == null) return false;
return viewers.containsKey(player.getUniqueId());
}
@Override
public int getMapId(OfflinePlayer player) {
if (isViewing(player)) {
return viewers.get(player.getUniqueId());
}
return -1;
}
@Override
public void update(ArrayImage content) {
MapWrapper duplicate = MapReflectionAPI.getMapManager().getDuplicate(content);
if (duplicate != null) {
MapWrapper_v1_17_R1.this.content = duplicate.getContent();
return;
}
MapWrapper_v1_17_R1.this.content = content;
for (UUID id : viewers.keySet()) {
sendContent(Bukkit.getPlayer(id));
}
}
@Override
public ArrayImage getContent() {
return MapWrapper_v1_17_R1.this.getContent();
}
@Override
public void sendContent(Player player) {
sendContent(player, false);
}
@Override
public void sendContent(Player player, boolean withoutQueue) {
if (!isViewing(player)) return;
int id = getMapId(player);
if (withoutQueue) {
MapSender_v1_17_R1.sendMap(id, MapWrapper_v1_17_R1.this.content, player);
} else {
MapSender_v1_17_R1.addToQueue(id, MapWrapper_v1_17_R1.this.content, player);
}
}
@Override
public void showInInventory(Player player, int slot, boolean force) {
if (!isViewing(player)) return;
if (player.getGameMode() == GameMode.CREATIVE && !force) return;
if (slot < 9) {
slot += 36;
} else if (slot > 35 && slot != 45) {
slot = 8 - (slot - 36);
}
CraftPlayer craftPlayer = (CraftPlayer) player;
int windowId = craftPlayer.getHandle().inventoryMenu.containerId;
int stateId = craftPlayer.getHandle().inventoryMenu.getStateId();
ItemStack stack = new ItemStack(Material.MAP, 1);
net.minecraft.world.item.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack);
PacketPlayOutSetSlot packet = new PacketPlayOutSetSlot(windowId, stateId, slot, nmsStack);
((EntityPlayer) player).connection.sendPacket(packet);
}
@Override
public void showInInventory(Player player, int slot) {
showInInventory(player, slot, false);
}
@Override
public void showInHand(Player player, boolean force) {
if (player.getInventory().getItemInMainHand().getType() != Material.MAP && !force) return;
showInInventory(player, player.getInventory().getHeldItemSlot(), force);
}
@Override
public void showInHand(Player player) {
showInHand(player, false);
}
@Override
public void showInFrame(Player player, ItemFrame frame) {
showInFrame(player, frame, false);
}
@Override
public void showInFrame(Player player, ItemFrame frame, boolean force) {
if (frame.getItem().getType() != Material.MAP && !force) return;
showInFrame(player, frame.getEntityId());
}
@Override
public void showInFrame(Player player, int entityId) {
showInFrame(player, entityId, null);
}
@Override
public void showInFrame(Player player, int entityId, String debugInfo) {
if (!isViewing(player)) return;
ItemStack stack = new ItemStack(Material.MAP, 1);
if (debugInfo != null) {
ItemMeta itemMeta = stack.getItemMeta();
itemMeta.setDisplayName(debugInfo);
stack.setItemMeta(itemMeta);
}
Bukkit.getScheduler().runTask(MapReflectionAPI.getInstance(), () -> {
ItemFrame frame = getItemFrameById(player.getWorld(), entityId);
if (frame != null) {
frame.removeMetadata("MAP_WRAPPER_REF", MapReflectionAPI.getInstance());
frame.setMetadata("MAP_WRAPPER_REF", new FixedMetadataValue(MapReflectionAPI.getInstance(), MapWrapper_v1_17_R1.this));
}
sendItemFramePacket(player, entityId, stack, getMapId(player));
});
}
@Override
public void clearFrame(Player player, int entityId) {
}
@Override
public void clearFrame(Player player, ItemFrame frame) {
}
private ItemFrame getItemFrameById(World world, int entityId) {
CraftWorld craftWorld = (CraftWorld) world;
Entity entity = craftWorld.getHandle().getEntity(entityId);
if (entity == null) return null;
if (entity instanceof ItemFrame) return (ItemFrame) entity;
return null;
}
private void sendItemFramePacket(Player player, int entityId, ItemStack stack, int mapId) {
net.minecraft.world.item.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack);
nmsStack.getOrCreateTag().setInt("map", mapId);
DataWatcher watcher = new DataWatcher(null);
watcher.set(DataWatcher.a(EntityItemFrame.class, DataWatcherRegistry.ITEM_STACK), nmsStack);
PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(entityId, watcher, true);
((EntityPlayer) player).connection.sendPacket(packet);
}
};
@Override
public MapController getController() {
return controller;
}
@Override
public ArrayImage getContent() {
return content;
}
}

98
NMS-v1_18_R2/pom.xml Normal file
View file

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>MapReflectionAPI</artifactId>
<groupId>tech.sbdevelopment</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>MapReflectionAPI-NMS-v1_18_R2</artifactId>
<properties>
<NMSVersion>1.18.2-R0.1-SNAPSHOT</NMSVersion>
<jdk.version>17</jdk.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0-SNAPSHOT</version>
<configuration>
<release>${jdk.version}</release>
</configuration>
</plugin>
<plugin>
<groupId>net.md-5</groupId>
<artifactId>specialsource-maven-plugin</artifactId>
<version>1.2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>remap</goal>
</goals>
<id>remap-obf</id>
<configuration>
<srgIn>org.spigotmc:minecraft-server:${NMSVersion}:txt:maps-mojang</srgIn>
<reverse>true</reverse>
<remappedDependencies>org.spigotmc:spigot:${NMSVersion}:jar:remapped-mojang
</remappedDependencies>
<remappedArtifactAttached>true</remappedArtifactAttached>
<remappedClassifierName>remapped-obf</remappedClassifierName>
</configuration>
</execution>
<execution>
<phase>package</phase>
<goals>
<goal>remap</goal>
</goals>
<id>remap-spigot</id>
<configuration>
<inputFile>
${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar
</inputFile>
<srgIn>org.spigotmc:minecraft-server:${NMSVersion}:csrg:maps-spigot</srgIn>
<remappedDependencies>org.spigotmc:spigot:${NMSVersion}:jar:remapped-obf
</remappedDependencies>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.0.0-M2</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>minecraft-server</artifactId>
<version>${NMSVersion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>${NMSVersion}</version>
<classifier>remapped-mojang</classifier>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>tech.sbdevelopment</groupId>
<artifactId>MapReflectionAPI-API</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View file

@ -0,0 +1,88 @@
package tech.sbdevelopment.mapreflectionapi.nms;
import net.minecraft.network.protocol.game.PacketPlayOutMap;
import net.minecraft.world.level.saveddata.maps.WorldMap;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer;
import org.bukkit.entity.Player;
import tech.sbdevelopment.mapreflectionapi.ArrayImage;
import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI;
import java.util.ArrayList;
import java.util.List;
public class MapSender_v1_18_R2 {
private static final List<QueuedMap> sendQueue = new ArrayList<>();
private static int senderID = -1;
public static void addToQueue(final int id, final ArrayImage content, final Player player) {
QueuedMap toSend = new QueuedMap(id, content, player);
if (sendQueue.contains(toSend)) return;
sendQueue.add(toSend);
runSender();
}
private static void runSender() {
if (Bukkit.getScheduler().isQueued(senderID) || Bukkit.getScheduler().isCurrentlyRunning(senderID) || sendQueue.isEmpty())
return;
senderID = Bukkit.getScheduler().scheduleSyncRepeatingTask(MapReflectionAPI.getInstance(), () -> {
if (sendQueue.isEmpty()) return;
for (int i = 0; i < Math.min(sendQueue.size(), 10 + 1); i++) {
QueuedMap current = sendQueue.get(0);
if (current == null) return;
sendMap(current.id, current.image, current.player);
if (!sendQueue.isEmpty()) sendQueue.remove(0);
}
}, 0, 2);
}
public static void sendMap(final int id0, final ArrayImage content, final Player player) {
if (player == null || !player.isOnline()) {
List<QueuedMap> toRemove = new ArrayList<>();
for (QueuedMap qMap : sendQueue) {
if (qMap == null) continue;
if (qMap.player == null || !qMap.player.isOnline()) {
toRemove.add(qMap);
}
}
Bukkit.getScheduler().cancelTask(senderID);
sendQueue.removeAll(toRemove);
return;
}
final int id = -id0;
Bukkit.getScheduler().runTaskAsynchronously(MapReflectionAPI.getInstance(), () -> {
try {
WorldMap.b updateData = new WorldMap.b(
content.minX, //X pos
content.minY, //Y pos
content.maxX, //X size (2nd X pos)
content.maxY, //Y size (2nd Y pos)
content.array //Data
);
PacketPlayOutMap packet = new PacketPlayOutMap(
id, //ID
(byte) 0, //Scale
false, //Show icons
new ArrayList<>(), //Icons
updateData
);
((CraftPlayer) player).getHandle().connection.send(packet);
} catch (Exception e) {
e.printStackTrace();
}
});
}
record QueuedMap(int id, ArrayImage image, Player player) {
}
}

View file

@ -0,0 +1,224 @@
package tech.sbdevelopment.mapreflectionapi.nms;
import net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata;
import net.minecraft.network.protocol.game.PacketPlayOutSetSlot;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherRegistry;
import net.minecraft.server.level.EntityPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.decoration.EntityItemFrame;
import org.bukkit.*;
import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.metadata.FixedMetadataValue;
import tech.sbdevelopment.mapreflectionapi.ArrayImage;
import tech.sbdevelopment.mapreflectionapi.MapController;
import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI;
import tech.sbdevelopment.mapreflectionapi.MapWrapper;
import tech.sbdevelopment.mapreflectionapi.exceptions.MapLimitExceededException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class MapWrapper_v1_18_R2 implements MapWrapper {
protected ArrayImage content;
protected MapController controller = new MapController() {
private final Map<UUID, Integer> viewers = new HashMap<>();
@Override
public void addViewer(Player player) throws MapLimitExceededException {
if (!isViewing(player)) {
viewers.put(player.getUniqueId(), MapReflectionAPI.getMapManager().getNextFreeIdFor(player));
}
}
@Override
public void removeViewer(OfflinePlayer player) {
viewers.remove(player.getUniqueId());
}
@Override
public void clearViewers() {
for (UUID uuid : viewers.keySet()) {
viewers.remove(uuid);
}
}
@Override
public boolean isViewing(OfflinePlayer player) {
if (player == null) return false;
return viewers.containsKey(player.getUniqueId());
}
@Override
public int getMapId(OfflinePlayer player) {
if (isViewing(player)) {
return viewers.get(player.getUniqueId());
}
return -1;
}
@Override
public void update(ArrayImage content) {
MapWrapper duplicate = MapReflectionAPI.getMapManager().getDuplicate(content);
if (duplicate != null) {
MapWrapper_v1_18_R2.this.content = duplicate.getContent();
return;
}
MapWrapper_v1_18_R2.this.content = content;
for (UUID id : viewers.keySet()) {
sendContent(Bukkit.getPlayer(id));
}
}
@Override
public ArrayImage getContent() {
return MapWrapper_v1_18_R2.this.getContent();
}
@Override
public void sendContent(Player player) {
sendContent(player, false);
}
@Override
public void sendContent(Player player, boolean withoutQueue) {
if (!isViewing(player)) return;
int id = getMapId(player);
if (withoutQueue) {
MapSender_v1_18_R2.sendMap(id, MapWrapper_v1_18_R2.this.content, player);
} else {
MapSender_v1_18_R2.addToQueue(id, MapWrapper_v1_18_R2.this.content, player);
}
}
@Override
public void showInInventory(Player player, int slot, boolean force) {
if (!isViewing(player)) return;
if (player.getGameMode() == GameMode.CREATIVE && !force) return;
if (slot < 9) {
slot += 36;
} else if (slot > 35 && slot != 45) {
slot = 8 - (slot - 36);
}
CraftPlayer craftPlayer = (CraftPlayer) player;
int windowId = craftPlayer.getHandle().inventoryMenu.containerId;
int stateId = craftPlayer.getHandle().inventoryMenu.getStateId();
ItemStack stack = new ItemStack(Material.MAP, 1);
net.minecraft.world.item.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack);
PacketPlayOutSetSlot packet = new PacketPlayOutSetSlot(windowId, stateId, slot, nmsStack);
((EntityPlayer) player).connection.send(packet);
}
@Override
public void showInInventory(Player player, int slot) {
showInInventory(player, slot, false);
}
@Override
public void showInHand(Player player, boolean force) {
if (player.getInventory().getItemInMainHand().getType() != Material.MAP && !force) return;
showInInventory(player, player.getInventory().getHeldItemSlot(), force);
}
@Override
public void showInHand(Player player) {
showInHand(player, false);
}
@Override
public void showInFrame(Player player, ItemFrame frame) {
showInFrame(player, frame, false);
}
@Override
public void showInFrame(Player player, ItemFrame frame, boolean force) {
if (frame.getItem().getType() != Material.MAP && !force) return;
showInFrame(player, frame.getEntityId());
}
@Override
public void showInFrame(Player player, int entityId) {
showInFrame(player, entityId, null);
}
@Override
public void showInFrame(Player player, int entityId, String debugInfo) {
if (!isViewing(player)) return;
ItemStack stack = new ItemStack(Material.MAP, 1);
if (debugInfo != null) {
ItemMeta itemMeta = stack.getItemMeta();
itemMeta.setDisplayName(debugInfo);
stack.setItemMeta(itemMeta);
}
Bukkit.getScheduler().runTask(MapReflectionAPI.getInstance(), () -> {
ItemFrame frame = getItemFrameById(player.getWorld(), entityId);
if (frame != null) {
frame.removeMetadata("MAP_WRAPPER_REF", MapReflectionAPI.getInstance());
frame.setMetadata("MAP_WRAPPER_REF", new FixedMetadataValue(MapReflectionAPI.getInstance(), MapWrapper_v1_18_R2.this));
}
sendItemFramePacket(player, entityId, stack, getMapId(player));
});
}
@Override
public void clearFrame(Player player, int entityId) {
}
@Override
public void clearFrame(Player player, ItemFrame frame) {
}
private ItemFrame getItemFrameById(World world, int entityId) {
CraftWorld craftWorld = (CraftWorld) world;
Entity entity = craftWorld.getHandle().getEntity(entityId);
if (entity == null) return null;
if (entity instanceof ItemFrame) return (ItemFrame) entity;
return null;
}
private void sendItemFramePacket(Player player, int entityId, ItemStack stack, int mapId) {
net.minecraft.world.item.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack);
nmsStack.getOrCreateTag().putInt("map", mapId);
DataWatcher watcher = new DataWatcher(null);
watcher.set(DataWatcher.defineId(EntityItemFrame.class, DataWatcherRegistry.ITEM_STACK), nmsStack);
PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(entityId, watcher, true);
((EntityPlayer) player).connection.send(packet);
}
};
@Override
public MapController getController() {
return controller;
}
@Override
public ArrayImage getContent() {
return content;
}
}

98
NMS-v1_19_R1/pom.xml Normal file
View file

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>MapReflectionAPI</artifactId>
<groupId>tech.sbdevelopment</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>MapReflectionAPI-NMS-v1_19_R1</artifactId>
<properties>
<NMSVersion>1.19-R0.1-SNAPSHOT</NMSVersion>
<jdk.version>17</jdk.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0-SNAPSHOT</version>
<configuration>
<release>${jdk.version}</release>
</configuration>
</plugin>
<plugin>
<groupId>net.md-5</groupId>
<artifactId>specialsource-maven-plugin</artifactId>
<version>1.2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>remap</goal>
</goals>
<id>remap-obf</id>
<configuration>
<srgIn>org.spigotmc:minecraft-server:${NMSVersion}:txt:maps-mojang</srgIn>
<reverse>true</reverse>
<remappedDependencies>org.spigotmc:spigot:${NMSVersion}:jar:remapped-mojang
</remappedDependencies>
<remappedArtifactAttached>true</remappedArtifactAttached>
<remappedClassifierName>remapped-obf</remappedClassifierName>
</configuration>
</execution>
<execution>
<phase>package</phase>
<goals>
<goal>remap</goal>
</goals>
<id>remap-spigot</id>
<configuration>
<inputFile>
${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar
</inputFile>
<srgIn>org.spigotmc:minecraft-server:${NMSVersion}:csrg:maps-spigot</srgIn>
<remappedDependencies>org.spigotmc:spigot:${NMSVersion}:jar:remapped-obf
</remappedDependencies>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.0.0-M2</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>minecraft-server</artifactId>
<version>${NMSVersion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>${NMSVersion}</version>
<classifier>remapped-mojang</classifier>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>tech.sbdevelopment</groupId>
<artifactId>MapReflectionAPI-API</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View file

@ -0,0 +1,88 @@
package tech.sbdevelopment.mapreflectionapi.nms;
import net.minecraft.network.protocol.game.PacketPlayOutMap;
import net.minecraft.world.level.saveddata.maps.WorldMap;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import tech.sbdevelopment.mapreflectionapi.ArrayImage;
import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI;
import java.util.ArrayList;
import java.util.List;
public class MapSender_v1_19_R1 {
private static final List<QueuedMap> sendQueue = new ArrayList<>();
private static int senderID = -1;
public static void addToQueue(final int id, final ArrayImage content, final Player player) {
QueuedMap toSend = new QueuedMap(id, content, player);
if (sendQueue.contains(toSend)) return;
sendQueue.add(toSend);
runSender();
}
private static void runSender() {
if (Bukkit.getScheduler().isQueued(senderID) || Bukkit.getScheduler().isCurrentlyRunning(senderID) || sendQueue.isEmpty())
return;
senderID = Bukkit.getScheduler().scheduleSyncRepeatingTask(MapReflectionAPI.getInstance(), () -> {
if (sendQueue.isEmpty()) return;
for (int i = 0; i < Math.min(sendQueue.size(), 10 + 1); i++) {
QueuedMap current = sendQueue.get(0);
if (current == null) return;
sendMap(current.id, current.image, current.player);
if (!sendQueue.isEmpty()) sendQueue.remove(0);
}
}, 0, 2);
}
public static void sendMap(final int id0, final ArrayImage content, final Player player) {
if (player == null || !player.isOnline()) {
List<QueuedMap> toRemove = new ArrayList<>();
for (QueuedMap qMap : sendQueue) {
if (qMap == null) continue;
if (qMap.player == null || !qMap.player.isOnline()) {
toRemove.add(qMap);
}
}
Bukkit.getScheduler().cancelTask(senderID);
sendQueue.removeAll(toRemove);
return;
}
final int id = -id0;
Bukkit.getScheduler().runTaskAsynchronously(MapReflectionAPI.getInstance(), () -> {
try {
WorldMap.b updateData = new WorldMap.b(
content.minX, //X pos
content.minY, //Y pos
content.maxX, //X size (2nd X pos)
content.maxY, //Y size (2nd Y pos)
content.array //Data
);
PacketPlayOutMap packet = new PacketPlayOutMap(
id, //ID
(byte) 0, //Scale
false, //Show icons
new ArrayList<>(), //Icons
updateData
);
((CraftPlayer) player).getHandle().connection.send(packet);
} catch (Exception e) {
e.printStackTrace();
}
});
}
record QueuedMap(int id, ArrayImage image, Player player) {
}
}

View file

@ -0,0 +1,224 @@
package tech.sbdevelopment.mapreflectionapi.nms;
import net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata;
import net.minecraft.network.protocol.game.PacketPlayOutSetSlot;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherRegistry;
import net.minecraft.server.level.EntityPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.decoration.EntityItemFrame;
import org.bukkit.*;
import org.bukkit.craftbukkit.v1_19_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftItemStack;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.metadata.FixedMetadataValue;
import tech.sbdevelopment.mapreflectionapi.ArrayImage;
import tech.sbdevelopment.mapreflectionapi.MapController;
import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI;
import tech.sbdevelopment.mapreflectionapi.MapWrapper;
import tech.sbdevelopment.mapreflectionapi.exceptions.MapLimitExceededException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class MapWrapper_v1_19_R1 implements MapWrapper {
protected ArrayImage content;
protected MapController controller = new MapController() {
private final Map<UUID, Integer> viewers = new HashMap<>();
@Override
public void addViewer(Player player) throws MapLimitExceededException {
if (!isViewing(player)) {
viewers.put(player.getUniqueId(), MapReflectionAPI.getMapManager().getNextFreeIdFor(player));
}
}
@Override
public void removeViewer(OfflinePlayer player) {
viewers.remove(player.getUniqueId());
}
@Override
public void clearViewers() {
for (UUID uuid : viewers.keySet()) {
viewers.remove(uuid);
}
}
@Override
public boolean isViewing(OfflinePlayer player) {
if (player == null) return false;
return viewers.containsKey(player.getUniqueId());
}
@Override
public int getMapId(OfflinePlayer player) {
if (isViewing(player)) {
return viewers.get(player.getUniqueId());
}
return -1;
}
@Override
public void update(ArrayImage content) {
MapWrapper duplicate = MapReflectionAPI.getMapManager().getDuplicate(content);
if (duplicate != null) {
MapWrapper_v1_19_R1.this.content = duplicate.getContent();
return;
}
MapWrapper_v1_19_R1.this.content = content;
for (UUID id : viewers.keySet()) {
sendContent(Bukkit.getPlayer(id));
}
}
@Override
public ArrayImage getContent() {
return MapWrapper_v1_19_R1.this.getContent();
}
@Override
public void sendContent(Player player) {
sendContent(player, false);
}
@Override
public void sendContent(Player player, boolean withoutQueue) {
if (!isViewing(player)) return;
int id = getMapId(player);
if (withoutQueue) {
MapSender_v1_19_R1.sendMap(id, MapWrapper_v1_19_R1.this.content, player);
} else {
MapSender_v1_19_R1.addToQueue(id, MapWrapper_v1_19_R1.this.content, player);
}
}
@Override
public void showInInventory(Player player, int slot, boolean force) {
if (!isViewing(player)) return;
if (player.getGameMode() == GameMode.CREATIVE && !force) return;
if (slot < 9) {
slot += 36;
} else if (slot > 35 && slot != 45) {
slot = 8 - (slot - 36);
}
CraftPlayer craftPlayer = (CraftPlayer) player;
int windowId = craftPlayer.getHandle().inventoryMenu.containerId;
int stateId = craftPlayer.getHandle().inventoryMenu.getStateId();
ItemStack stack = new ItemStack(Material.MAP, 1);
net.minecraft.world.item.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack);
PacketPlayOutSetSlot packet = new PacketPlayOutSetSlot(windowId, stateId, slot, nmsStack);
((EntityPlayer) player).connection.send(packet);
}
@Override
public void showInInventory(Player player, int slot) {
showInInventory(player, slot, false);
}
@Override
public void showInHand(Player player, boolean force) {
if (player.getInventory().getItemInMainHand().getType() != Material.MAP && !force) return;
showInInventory(player, player.getInventory().getHeldItemSlot(), force);
}
@Override
public void showInHand(Player player) {
showInHand(player, false);
}
@Override
public void showInFrame(Player player, ItemFrame frame) {
showInFrame(player, frame, false);
}
@Override
public void showInFrame(Player player, ItemFrame frame, boolean force) {
if (frame.getItem().getType() != Material.MAP && !force) return;
showInFrame(player, frame.getEntityId());
}
@Override
public void showInFrame(Player player, int entityId) {
showInFrame(player, entityId, null);
}
@Override
public void showInFrame(Player player, int entityId, String debugInfo) {
if (!isViewing(player)) return;
ItemStack stack = new ItemStack(Material.MAP, 1);
if (debugInfo != null) {
ItemMeta itemMeta = stack.getItemMeta();
itemMeta.setDisplayName(debugInfo);
stack.setItemMeta(itemMeta);
}
Bukkit.getScheduler().runTask(MapReflectionAPI.getInstance(), () -> {
ItemFrame frame = getItemFrameById(player.getWorld(), entityId);
if (frame != null) {
frame.removeMetadata("MAP_WRAPPER_REF", MapReflectionAPI.getInstance());
frame.setMetadata("MAP_WRAPPER_REF", new FixedMetadataValue(MapReflectionAPI.getInstance(), MapWrapper_v1_19_R1.this));
}
sendItemFramePacket(player, entityId, stack, getMapId(player));
});
}
@Override
public void clearFrame(Player player, int entityId) {
}
@Override
public void clearFrame(Player player, ItemFrame frame) {
}
private ItemFrame getItemFrameById(World world, int entityId) {
CraftWorld craftWorld = (CraftWorld) world;
Entity entity = craftWorld.getHandle().getEntity(entityId);
if (entity == null) return null;
if (entity instanceof ItemFrame) return (ItemFrame) entity;
return null;
}
private void sendItemFramePacket(Player player, int entityId, ItemStack stack, int mapId) {
net.minecraft.world.item.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack);
nmsStack.getOrCreateTag().putInt("map", mapId);
DataWatcher watcher = new DataWatcher(null);
watcher.set(DataWatcher.defineId(EntityItemFrame.class, DataWatcherRegistry.ITEM_STACK), nmsStack);
PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(entityId, watcher, true);
((EntityPlayer) player).connection.send(packet);
}
};
@Override
public MapController getController() {
return controller;
}
@Override
public ArrayImage getContent() {
return content;
}
}

12
README.md Normal file
View file

@ -0,0 +1,12 @@
# MapReflectionAPI
This API helps developer with viewing images on maps. It supports Spigot 1.12 - 1.19.
## Dependencies:
- [BKCommonLib](https://www.spigotmc.org/resources/bkcommonlib.39590/)
## Credits:
The source is based on [MapManager](https://github.com/InventivetalentDev/MapManager). It removes the PacketListenerAPI
dependency and uses NMS with submodules instead of reflection to make the code easier to edit.

88
pom.xml Normal file
View file

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>tech.sbdevelopment</groupId>
<artifactId>MapReflectionAPI</artifactId>
<packaging>pom</packaging>
<version>${revision}</version>
<properties>
<revision>1.0-SNAPSHOT</revision>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jdk.version>11</jdk.version>
</properties>
<modules>
<module>API</module>
<module>Dist</module>
<module>NMS-v1_19_R1</module>
<module>NMS-v1_18_R2</module>
<module>NMS-v1_17_R1</module>
<module>NMS-v1_16_R3</module>
<module>NMS-v1_15_R1</module>
<module>NMS-v1_14_R1</module>
<module>NMS-v1_13_R2</module>
<module>NMS-v1_12_R1</module>
</modules>
<build>
<defaultGoal>clean package</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-toolchains-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<goals>
<goal>toolchain</goal>
</goals>
</execution>
</executions>
<configuration>
<toolchains>
<jdk>
<version>${jdk.version}</version>
</jdk>
</toolchains>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<release>${jdk.version}</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.0.0-M2</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.19-R0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>