Added embedded upload service feature
This commit is contained in:
1 parent
6af8fd7b76
commit
8a89a33b42
112 files changed
+1164
-222
No files matched your search
+1
-1
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.loohp</groupId>
|
||||
<artifactId>ImageFrame-Parent</artifactId>
|
||||
<version>1.7.14.3</version>
|
||||
<version>1.7.14.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ImageFrame-V1_16</artifactId>
|
||||
|
||||
@@ -200,7 +200,7 @@ public class V1_16 extends NMSWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<byte[], ArrayList<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
public MutablePair<byte[], List<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
CraftMapView craftMapView = (CraftMapView) mapView;
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
RenderData renderData = craftMapView.render(craftPlayer);
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.loohp</groupId>
|
||||
<artifactId>ImageFrame-Parent</artifactId>
|
||||
<version>1.7.14.3</version>
|
||||
<version>1.7.14.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ImageFrame-V1_16_2</artifactId>
|
||||
|
||||
@@ -200,7 +200,7 @@ public class V1_16_2 extends NMSWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<byte[], ArrayList<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
public MutablePair<byte[], List<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
CraftMapView craftMapView = (CraftMapView) mapView;
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
RenderData renderData = craftMapView.render(craftPlayer);
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.loohp</groupId>
|
||||
<artifactId>ImageFrame-Parent</artifactId>
|
||||
<version>1.7.14.3</version>
|
||||
<version>1.7.14.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ImageFrame-V1_16_4</artifactId>
|
||||
|
||||
@@ -200,7 +200,7 @@ public class V1_16_4 extends NMSWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<byte[], ArrayList<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
public MutablePair<byte[], List<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
CraftMapView craftMapView = (CraftMapView) mapView;
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
RenderData renderData = craftMapView.render(craftPlayer);
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.loohp</groupId>
|
||||
<artifactId>ImageFrame-Parent</artifactId>
|
||||
<version>1.7.14.3</version>
|
||||
<version>1.7.14.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ImageFrame-V1_17</artifactId>
|
||||
|
||||
@@ -194,7 +194,7 @@ public class V1_17 extends NMSWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<byte[], ArrayList<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
public MutablePair<byte[], List<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
CraftMapView craftMapView = (CraftMapView) mapView;
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
RenderData renderData = craftMapView.render(craftPlayer);
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.loohp</groupId>
|
||||
<artifactId>ImageFrame-Parent</artifactId>
|
||||
<version>1.7.14.3</version>
|
||||
<version>1.7.14.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ImageFrame-V1_18</artifactId>
|
||||
|
||||
@@ -58,7 +58,6 @@ import net.minecraft.world.level.saveddata.maps.WorldMap;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.v1_18_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_18_R1.entity.CraftEntity;
|
||||
@@ -195,7 +194,7 @@ public class V1_18 extends NMSWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<byte[], ArrayList<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
public MutablePair<byte[], List<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
CraftMapView craftMapView = (CraftMapView) mapView;
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
RenderData renderData = craftMapView.render(craftPlayer);
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.loohp</groupId>
|
||||
<artifactId>ImageFrame-Parent</artifactId>
|
||||
<version>1.7.14.3</version>
|
||||
<version>1.7.14.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ImageFrame-V1_18_2</artifactId>
|
||||
|
||||
@@ -194,7 +194,7 @@ public class V1_18_2 extends NMSWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<byte[], ArrayList<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
public MutablePair<byte[], List<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
CraftMapView craftMapView = (CraftMapView) mapView;
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
RenderData renderData = craftMapView.render(craftPlayer);
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.loohp</groupId>
|
||||
<artifactId>ImageFrame-Parent</artifactId>
|
||||
<version>1.7.14.3</version>
|
||||
<version>1.7.14.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ImageFrame-V1_19</artifactId>
|
||||
|
||||
@@ -193,7 +193,7 @@ public class V1_19 extends NMSWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<byte[], ArrayList<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
public MutablePair<byte[], List<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
CraftMapView craftMapView = (CraftMapView) mapView;
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
RenderData renderData = craftMapView.render(craftPlayer);
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.loohp</groupId>
|
||||
<artifactId>ImageFrame-Parent</artifactId>
|
||||
<version>1.7.14.3</version>
|
||||
<version>1.7.14.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ImageFrame-V1_19_3</artifactId>
|
||||
|
||||
@@ -188,7 +188,7 @@ public class V1_19_3 extends NMSWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<byte[], ArrayList<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
public MutablePair<byte[], List<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
CraftMapView craftMapView = (CraftMapView) mapView;
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
RenderData renderData = craftMapView.render(craftPlayer);
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.loohp</groupId>
|
||||
<artifactId>ImageFrame-Parent</artifactId>
|
||||
<version>1.7.14.3</version>
|
||||
<version>1.7.14.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ImageFrame-V1_19_4</artifactId>
|
||||
|
||||
@@ -188,7 +188,7 @@ public class V1_19_4 extends NMSWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<byte[], ArrayList<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
public MutablePair<byte[], List<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
CraftMapView craftMapView = (CraftMapView) mapView;
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
RenderData renderData = craftMapView.render(craftPlayer);
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.loohp</groupId>
|
||||
<artifactId>ImageFrame-Parent</artifactId>
|
||||
<version>1.7.14.3</version>
|
||||
<version>1.7.14.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ImageFrame-V1_20</artifactId>
|
||||
|
||||
@@ -188,7 +188,7 @@ public class V1_20 extends NMSWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<byte[], ArrayList<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
public MutablePair<byte[], List<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
CraftMapView craftMapView = (CraftMapView) mapView;
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
RenderData renderData = craftMapView.render(craftPlayer);
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.loohp</groupId>
|
||||
<artifactId>ImageFrame-Parent</artifactId>
|
||||
<version>1.7.14.3</version>
|
||||
<version>1.7.14.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ImageFrame-V1_20_2</artifactId>
|
||||
|
||||
@@ -188,7 +188,7 @@ public class V1_20_2 extends NMSWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<byte[], ArrayList<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
public MutablePair<byte[], List<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
CraftMapView craftMapView = (CraftMapView) mapView;
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
RenderData renderData = craftMapView.render(craftPlayer);
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.loohp</groupId>
|
||||
<artifactId>ImageFrame-Parent</artifactId>
|
||||
<version>1.7.14.3</version>
|
||||
<version>1.7.14.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ImageFrame-V1_20_3</artifactId>
|
||||
|
||||
@@ -183,7 +183,7 @@ public class V1_20_3 extends NMSWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<byte[], ArrayList<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
public MutablePair<byte[], List<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
CraftMapView craftMapView = (CraftMapView) mapView;
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
RenderData renderData = craftMapView.render(craftPlayer);
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.loohp</groupId>
|
||||
<artifactId>ImageFrame-Parent</artifactId>
|
||||
<version>1.7.14.3</version>
|
||||
<version>1.7.14.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ImageFrame-V1_20_5</artifactId>
|
||||
|
||||
@@ -189,7 +189,7 @@ public class V1_20_5 extends NMSWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<byte[], ArrayList<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
public MutablePair<byte[], List<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
CraftMapView craftMapView = (CraftMapView) mapView;
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
RenderData renderData = craftMapView.render(craftPlayer);
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.loohp</groupId>
|
||||
<artifactId>ImageFrame-Parent</artifactId>
|
||||
<version>1.7.14.3</version>
|
||||
<version>1.7.14.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ImageFrame-V1_20_6</artifactId>
|
||||
|
||||
@@ -189,7 +189,7 @@ public class V1_20_6 extends NMSWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<byte[], ArrayList<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
public MutablePair<byte[], List<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
CraftMapView craftMapView = (CraftMapView) mapView;
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
RenderData renderData = craftMapView.render(craftPlayer);
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.loohp</groupId>
|
||||
<artifactId>ImageFrame-Parent</artifactId>
|
||||
<version>1.7.14.3</version>
|
||||
<version>1.7.14.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ImageFrame-V1_21</artifactId>
|
||||
|
||||
@@ -189,7 +189,7 @@ public class V1_21 extends NMSWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<byte[], ArrayList<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
public MutablePair<byte[], List<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
CraftMapView craftMapView = (CraftMapView) mapView;
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
RenderData renderData = craftMapView.render(craftPlayer);
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.loohp</groupId>
|
||||
<artifactId>ImageFrame-Parent</artifactId>
|
||||
<version>1.7.14.3</version>
|
||||
<version>1.7.14.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ImageFrame-V1_21_1</artifactId>
|
||||
|
||||
@@ -189,7 +189,7 @@ public class V1_21_1 extends NMSWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<byte[], ArrayList<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
public MutablePair<byte[], List<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
CraftMapView craftMapView = (CraftMapView) mapView;
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
RenderData renderData = craftMapView.render(craftPlayer);
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.loohp</groupId>
|
||||
<artifactId>ImageFrame-Parent</artifactId>
|
||||
<version>1.7.14.3</version>
|
||||
<version>1.7.14.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ImageFrame-V1_21_2</artifactId>
|
||||
|
||||
@@ -189,7 +189,7 @@ public class V1_21_2 extends NMSWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<byte[], ArrayList<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
public MutablePair<byte[], List<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
CraftMapView craftMapView = (CraftMapView) mapView;
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
RenderData renderData = craftMapView.render(craftPlayer);
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.loohp</groupId>
|
||||
<artifactId>ImageFrame-Parent</artifactId>
|
||||
<version>1.7.14.3</version>
|
||||
<version>1.7.14.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ImageFrame-V1_21_3</artifactId>
|
||||
|
||||
@@ -189,7 +189,7 @@ public class V1_21_3 extends NMSWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<byte[], ArrayList<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
public MutablePair<byte[], List<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
CraftMapView craftMapView = (CraftMapView) mapView;
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
RenderData renderData = craftMapView.render(craftPlayer);
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.loohp</groupId>
|
||||
<artifactId>ImageFrame-Parent</artifactId>
|
||||
<version>1.7.14.3</version>
|
||||
<version>1.7.14.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ImageFrame-V1_21_4</artifactId>
|
||||
|
||||
@@ -91,12 +91,14 @@ public class V1_21_4 extends NMSWrapper {
|
||||
private final Field nmsEntityByteDataWatcherField;
|
||||
private final Field craftMapViewWorldMapField;
|
||||
private final Field persistentIdCountsUsedAuxIdsField;
|
||||
private final Field renderDataCursorsField;
|
||||
|
||||
public V1_21_4() {
|
||||
try {
|
||||
nmsEntityByteDataWatcherField = ReflectionUtils.findDeclaredField(net.minecraft.world.entity.Entity.class, DataWatcherObject.class, "DATA_SHARED_FLAGS_ID", "am");
|
||||
craftMapViewWorldMapField = CraftMapView.class.getDeclaredField("worldMap");
|
||||
persistentIdCountsUsedAuxIdsField = ReflectionUtils.findDeclaredField(PersistentIdCounts.class, Object2IntMap.class, "usedAuxIds", "b");
|
||||
renderDataCursorsField = RenderData.class.getField("cursors");
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -188,12 +190,17 @@ public class V1_21_4 extends NMSWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public MutablePair<byte[], ArrayList<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
CraftMapView craftMapView = (CraftMapView) mapView;
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
RenderData renderData = craftMapView.render(craftPlayer);
|
||||
return new MutablePair<>(renderData.buffer, renderData.cursors);
|
||||
public MutablePair<byte[], List<MapCursor>> bukkitRenderMap(MapView mapView, Player player) {
|
||||
try {
|
||||
CraftMapView craftMapView = (CraftMapView) mapView;
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
RenderData renderData = craftMapView.render(craftPlayer);
|
||||
return new MutablePair<>(renderData.buffer, (List<MapCursor>) renderDataCursorsField.get(renderData));
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.loohp</groupId>
|
||||
<artifactId>ImageFrame-Parent</artifactId>
|
||||
<version>1.7.14.3</version>
|
||||
<version>1.7.14.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ImageFrame-Abstraction</artifactId>
|
||||
|
||||
@@ -30,7 +30,6 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.map.MapCursor;
|
||||
import org.bukkit.map.MapView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -54,7 +53,7 @@ public abstract class NMSWrapper {
|
||||
|
||||
public abstract MapView getMapOrCreateMissing(World world, int id);
|
||||
|
||||
public abstract MutablePair<byte[], ArrayList<MapCursor>> bukkitRenderMap(MapView mapView, Player player);
|
||||
public abstract MutablePair<byte[], List<MapCursor>> bukkitRenderMap(MapView mapView, Player player);
|
||||
|
||||
public abstract Set<Player> getEntityTrackers(Entity entity);
|
||||
|
||||
|
||||
+35
-1
@@ -1,4 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ This file is part of ImageFrame.
|
||||
~
|
||||
~ Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
~ Copyright (C) 2025. Contributors
|
||||
~
|
||||
~ This program is free software: you can redistribute it and/or modify
|
||||
~ it under the terms of the GNU General Public License as published by
|
||||
~ the Free Software Foundation, either version 3 of the License, or
|
||||
~ (at your option) any later version.
|
||||
~
|
||||
~ This program is distributed in the hope that it will be useful,
|
||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
~ GNU General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License
|
||||
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
@@ -6,7 +26,7 @@
|
||||
|
||||
<groupId>com.loohp</groupId>
|
||||
<artifactId>ImageFrame</artifactId>
|
||||
<version>1.7.14.3</version>
|
||||
<version>1.7.14.4</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>ImageFrame</name>
|
||||
@@ -30,8 +50,16 @@
|
||||
<filtering>true</filtering>
|
||||
<excludes>
|
||||
<exclude>**/*.java</exclude>
|
||||
<exclude>upload/**</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>false</filtering>
|
||||
<includes>
|
||||
<include>upload/**</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
|
||||
<plugins>
|
||||
@@ -235,6 +263,12 @@
|
||||
<version>1.8.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
<version>1.4</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.clip</groupId>
|
||||
<artifactId>placeholderapi</artifactId>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -41,6 +41,8 @@ import com.loohp.imageframe.objectholders.URLAnimatedImageMap;
|
||||
import com.loohp.imageframe.objectholders.URLImageMap;
|
||||
import com.loohp.imageframe.objectholders.URLStaticImageMap;
|
||||
import com.loohp.imageframe.updater.Updater;
|
||||
import com.loohp.imageframe.upload.ImageUploadManager;
|
||||
import com.loohp.imageframe.upload.PendingUpload;
|
||||
import com.loohp.imageframe.utils.ChatColorUtils;
|
||||
import com.loohp.imageframe.utils.HTTPRequestUtils;
|
||||
import com.loohp.imageframe.utils.ImageMapUtils;
|
||||
@@ -197,6 +199,12 @@ public class Commands implements CommandExecutor, TabCompleter {
|
||||
String url = "Pending...";
|
||||
try {
|
||||
url = args[2];
|
||||
if (ImageFrame.uploadServiceEnabled && url.equalsIgnoreCase("upload")) {
|
||||
UUID user = isConsole ? ImageMap.CONSOLE_CREATOR : player.getUniqueId();
|
||||
PendingUpload pendingUpload = ImageFrame.imageUploadManager.newPendingUpload(user);
|
||||
Scheduler.runTaskLaterAsynchronously(ImageFrame.plugin, () -> sender.sendMessage(ImageFrame.messageUploadLink.replace("{URL}", pendingUpload.getUrl(ImageFrame.uploadServiceHost, user))), 2);
|
||||
url = pendingUpload.getFileBlocking().toURI().toURL().toString();
|
||||
}
|
||||
if (HTTPRequestUtils.getContentSize(url) > ImageFrame.maxImageFileSize) {
|
||||
sender.sendMessage(ImageFrame.messageImageOverMaxFileSize.replace("{Size}", ImageFrame.maxImageFileSize + ""));
|
||||
throw new IOException("Image over max file size");
|
||||
@@ -245,6 +253,8 @@ public class Commands implements CommandExecutor, TabCompleter {
|
||||
}
|
||||
sender.sendMessage(ImageFrame.messageImageMapCreated);
|
||||
creationTask.complete(ImageFrame.messageImageMapCreated);
|
||||
} catch (ImageUploadManager.LinkTimeoutException e) {
|
||||
sender.sendMessage(ImageFrame.messageUploadExpired);
|
||||
} catch (ImageMapCreationTaskManager.EnqueueRejectedException e) {
|
||||
sender.sendMessage(ImageFrame.messageImageMapAlreadyQueued);
|
||||
} catch (Exception e) {
|
||||
@@ -336,18 +346,32 @@ public class Commands implements CommandExecutor, TabCompleter {
|
||||
sender.sendMessage(ImageFrame.messageDuplicateMapName);
|
||||
return true;
|
||||
}
|
||||
if (!ImageFrame.isURLAllowed(args[2])) {
|
||||
sender.sendMessage(ImageFrame.messageURLRestricted);
|
||||
return true;
|
||||
}
|
||||
Scheduler.runTaskAsynchronously(ImageFrame.plugin, () -> {
|
||||
ImageMapCreationTask<ImageMap> creationTask = null;
|
||||
try {
|
||||
creationTask = ImageFrame.imageMapCreationTaskManager.enqueue(owner, name, width, height, () -> MinecraftURLOverlayImageMap.create(ImageFrame.imageMapManager, name, args[2], mapViews, width, height, ditheringType, player.getUniqueId()).get());
|
||||
String url = args[2];
|
||||
if (ImageFrame.uploadServiceEnabled && url.equalsIgnoreCase("upload")) {
|
||||
UUID user = player.getUniqueId();
|
||||
PendingUpload pendingUpload = ImageFrame.imageUploadManager.newPendingUpload(user);
|
||||
Scheduler.runTaskLaterAsynchronously(ImageFrame.plugin, () -> sender.sendMessage(ImageFrame.messageUploadLink.replace("{URL}", pendingUpload.getUrl(ImageFrame.uploadServiceHost, user))), 2);
|
||||
url = pendingUpload.getFileBlocking().toURI().toURL().toString();
|
||||
}
|
||||
if (!ImageFrame.isURLAllowed(url)) {
|
||||
sender.sendMessage(ImageFrame.messageURLRestricted);
|
||||
return;
|
||||
}
|
||||
if (HTTPRequestUtils.getContentSize(url) > ImageFrame.maxImageFileSize) {
|
||||
sender.sendMessage(ImageFrame.messageImageOverMaxFileSize.replace("{Size}", ImageFrame.maxImageFileSize + ""));
|
||||
throw new IOException("Image over max file size");
|
||||
}
|
||||
String finalUrl = url;
|
||||
creationTask = ImageFrame.imageMapCreationTaskManager.enqueue(owner, name, width, height, () -> MinecraftURLOverlayImageMap.create(ImageFrame.imageMapManager, name, finalUrl, mapViews, width, height, ditheringType, player.getUniqueId()).get());
|
||||
ImageMap imageMap = creationTask.get();
|
||||
ImageFrame.imageMapManager.addMap(imageMap);
|
||||
sender.sendMessage(ImageFrame.messageImageMapCreated);
|
||||
creationTask.complete(ImageFrame.messageImageMapCreated);
|
||||
} catch (ImageUploadManager.LinkTimeoutException e) {
|
||||
sender.sendMessage(ImageFrame.messageUploadExpired);
|
||||
} catch (ImageMapCreationTaskManager.EnqueueRejectedException e) {
|
||||
sender.sendMessage(ImageFrame.messageImageMapAlreadyQueued);
|
||||
} catch (Exception e) {
|
||||
@@ -755,11 +779,26 @@ public class Commands implements CommandExecutor, TabCompleter {
|
||||
} else {
|
||||
imageType = imageType.trim();
|
||||
}
|
||||
if (!ImageFrame.isURLAllowed(url)) {
|
||||
sender.sendMessage(ImageFrame.messageURLRestricted);
|
||||
return;
|
||||
}
|
||||
if (imageType.equals(MapUtils.GIF_CONTENT_TYPE) == urlImageMap.requiresAnimationService()) {
|
||||
String oldUrl = urlImageMap.getUrl();
|
||||
if (url != null) {
|
||||
urlImageMap.setUrl(url);
|
||||
}
|
||||
if (ImageFrame.uploadServiceEnabled && urlImageMap.getUrl().equalsIgnoreCase("upload")) {
|
||||
UUID user = !(sender instanceof Player) ? ImageMap.CONSOLE_CREATOR : ((Player) sender).getUniqueId();
|
||||
PendingUpload pendingUpload = ImageFrame.imageUploadManager.newPendingUpload(user);
|
||||
Scheduler.runTaskLaterAsynchronously(ImageFrame.plugin, () -> sender.sendMessage(ImageFrame.messageUploadLink.replace("{URL}", pendingUpload.getUrl(ImageFrame.uploadServiceHost, user))), 2);
|
||||
String newUrl = pendingUpload.getFileBlocking().toURI().toURL().toString();
|
||||
if (HTTPRequestUtils.getContentSize(newUrl) > ImageFrame.maxImageFileSize) {
|
||||
sender.sendMessage(ImageFrame.messageImageOverMaxFileSize.replace("{Size}", ImageFrame.maxImageFileSize + ""));
|
||||
throw new IOException("Image over max file size");
|
||||
}
|
||||
urlImageMap.setUrl(newUrl);
|
||||
}
|
||||
if (ditheringType != null) {
|
||||
urlImageMap.setDitheringType(ditheringType);
|
||||
}
|
||||
@@ -781,6 +820,8 @@ public class Commands implements CommandExecutor, TabCompleter {
|
||||
imageMap.update();
|
||||
sender.sendMessage(ImageFrame.messageImageMapRefreshed);
|
||||
}
|
||||
} catch (ImageUploadManager.LinkTimeoutException e) {
|
||||
sender.sendMessage(ImageFrame.messageUploadExpired);
|
||||
} catch (Exception e) {
|
||||
sender.sendMessage(ImageFrame.messageUnableToLoadMap);
|
||||
e.printStackTrace();
|
||||
@@ -1543,6 +1584,9 @@ public class Commands implements CommandExecutor, TabCompleter {
|
||||
if (sender.hasPermission("imageframe.refresh")) {
|
||||
if ("refresh".equalsIgnoreCase(args[0])) {
|
||||
tab.add("[url]");
|
||||
if (ImageFrame.uploadServiceEnabled && "upload".startsWith(args[1].toLowerCase())) {
|
||||
tab.add("upload");
|
||||
}
|
||||
tab.addAll(ImageMapUtils.getImageMapNameSuggestions(sender, args[1]));
|
||||
for (String ditheringType : DitheringType.values().keySet()) {
|
||||
if (ditheringType.startsWith(args[1].toLowerCase())) {
|
||||
@@ -1660,11 +1704,17 @@ public class Commands implements CommandExecutor, TabCompleter {
|
||||
if (sender.hasPermission("imageframe.create")) {
|
||||
if ("create".equalsIgnoreCase(args[0])) {
|
||||
tab.add("<url>");
|
||||
if (ImageFrame.uploadServiceEnabled && "upload".startsWith(args[2].toLowerCase())) {
|
||||
tab.add("upload");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sender.hasPermission("imageframe.overlay")) {
|
||||
if ("overlay".equalsIgnoreCase(args[0])) {
|
||||
tab.add("<url>");
|
||||
if (ImageFrame.uploadServiceEnabled && "upload".startsWith(args[2].toLowerCase())) {
|
||||
tab.add("upload");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sender.hasPermission("imageframe.clone")) {
|
||||
@@ -1687,6 +1737,9 @@ public class Commands implements CommandExecutor, TabCompleter {
|
||||
ImageMap imageMap = ImageMapUtils.getFromPlayerPrefixedName(sender, args[1]);
|
||||
if (imageMap != null) {
|
||||
tab.add("[url]");
|
||||
if (ImageFrame.uploadServiceEnabled && "upload".startsWith(args[2].toLowerCase())) {
|
||||
tab.add("upload");
|
||||
}
|
||||
for (String ditheringType : DitheringType.values().keySet()) {
|
||||
if (ditheringType.startsWith(args[2].toLowerCase())) {
|
||||
tab.add(ditheringType);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -46,6 +46,7 @@ import com.loohp.imageframe.updater.Updater;
|
||||
import com.loohp.imageframe.utils.ChatColorUtils;
|
||||
import com.loohp.imageframe.utils.MCVersion;
|
||||
import com.loohp.imageframe.utils.ModernEventsUtils;
|
||||
import com.loohp.imageframe.upload.ImageUploadManager;
|
||||
import com.twelvemonkeys.imageio.plugins.webp.WebPImageReaderSpi;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
@@ -138,6 +139,8 @@ public class ImageFrame extends JavaPlugin {
|
||||
public static String messageMarkersLimitReached;
|
||||
public static String messageInvalidOverlayMap;
|
||||
public static String messageGivenInvisibleFrame;
|
||||
public static String messageUploadLink;
|
||||
public static String messageUploadExpired;
|
||||
|
||||
public static SimpleDateFormat dateFormat;
|
||||
|
||||
@@ -167,6 +170,10 @@ public class ImageFrame extends JavaPlugin {
|
||||
public static boolean handleAnimatedMapsOnMainThread;
|
||||
public static boolean sendAnimatedMapsOnMainThread;
|
||||
|
||||
public static boolean uploadServiceEnabled;
|
||||
public static String uploadServiceHost;
|
||||
public static int uploadServicePort;
|
||||
|
||||
public static int invisibleFrameMaxConversionsPerSplash;
|
||||
public static boolean invisibleFrameGlowEmptyFrames;
|
||||
|
||||
@@ -179,11 +186,15 @@ public class ImageFrame extends JavaPlugin {
|
||||
public static RateLimitedPacketSendingManager rateLimitedPacketSendingManager;
|
||||
public static InvisibleFrameManager invisibleFrameManager;
|
||||
public static ImageMapCreationTaskManager imageMapCreationTaskManager;
|
||||
public static ImageUploadManager imageUploadManager;
|
||||
|
||||
public static boolean isURLAllowed(String link) {
|
||||
if (!restrictImageUrlEnabled) {
|
||||
return true;
|
||||
}
|
||||
if ("upload".equals(link) || imageUploadManager.wasUploaded(link)) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
URL url = new URL(link);
|
||||
return restrictImageUrls.stream().anyMatch(whitelisted -> {
|
||||
@@ -315,6 +326,7 @@ public class ImageFrame extends JavaPlugin {
|
||||
Scheduler.runTaskAsynchronously(this, () -> imageMapManager.loadMaps());
|
||||
invisibleFrameManager = new InvisibleFrameManager();
|
||||
imageMapCreationTaskManager = new ImageMapCreationTaskManager(ImageFrame.parallelProcessingLimit);
|
||||
imageUploadManager = new ImageUploadManager(updaterEnabled, uploadServicePort);
|
||||
|
||||
if (isPluginEnabled("PlaceholderAPI")) {
|
||||
new Placeholders().register();
|
||||
@@ -337,6 +349,9 @@ public class ImageFrame extends JavaPlugin {
|
||||
if (combinedMapItemHandler != null) {
|
||||
combinedMapItemHandler.close();
|
||||
}
|
||||
if (imageUploadManager != null) {
|
||||
imageUploadManager.close();
|
||||
}
|
||||
getServer().getConsoleSender().sendMessage(ChatColor.RED + "[ImageFrame] ImageFrame has been Disabled!");
|
||||
}
|
||||
|
||||
@@ -405,6 +420,8 @@ public class ImageFrame extends JavaPlugin {
|
||||
messageMarkersLimitReached = ChatColorUtils.translateAlternateColorCodes('&', config.getConfiguration().getString("Messages.Markers.LimitReached"));
|
||||
messageInvalidOverlayMap = ChatColorUtils.translateAlternateColorCodes('&', config.getConfiguration().getString("Messages.InvalidOverlayMap"));
|
||||
messageGivenInvisibleFrame = ChatColorUtils.translateAlternateColorCodes('&', config.getConfiguration().getString("Messages.GivenInvisibleFrame"));
|
||||
messageUploadLink = ChatColorUtils.translateAlternateColorCodes('&', config.getConfiguration().getString("Messages.UploadLink"));
|
||||
messageUploadExpired = ChatColorUtils.translateAlternateColorCodes('&', config.getConfiguration().getString("Messages.UploadExpired"));
|
||||
|
||||
dateFormat = new SimpleDateFormat(config.getConfiguration().getString("Messages.DateFormat"));
|
||||
|
||||
@@ -462,6 +479,10 @@ public class ImageFrame extends JavaPlugin {
|
||||
handleAnimatedMapsOnMainThread = config.getConfiguration().getBoolean("Settings.HandleAnimatedMapsOnMainThread");
|
||||
sendAnimatedMapsOnMainThread = config.getConfiguration().getBoolean("Settings.SendAnimatedMapsOnMainThread");
|
||||
|
||||
uploadServiceEnabled = config.getConfiguration().getBoolean("UploadService.Enabled");
|
||||
uploadServiceHost = config.getConfiguration().getString("UploadService.Host");
|
||||
uploadServicePort = config.getConfiguration().getInt("UploadService.Port");
|
||||
|
||||
invisibleFrameMaxConversionsPerSplash = config.getConfiguration().getInt("InvisibleFrame.MaxConversionsPerSplash");
|
||||
invisibleFrameGlowEmptyFrames = config.getConfiguration().getBoolean("InvisibleFrame.GlowEmptyFrames");
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2023. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of InteractiveChatDiscordSrvAddon.
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2023. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -84,14 +84,24 @@ public class Charts {
|
||||
metrics.addCustomChart(new Metrics.SingleLineChart("item_frames_made_invisible_in_last_interval", new Callable<Integer>() {
|
||||
@Override
|
||||
public Integer call() throws Exception {
|
||||
return (int) ImageFrame.invisibleFrameManager.getItemFramesMadeInvisible().getAndSet(0);
|
||||
long value = ImageFrame.invisibleFrameManager.getItemFramesMadeInvisible().getAndSet(0);
|
||||
return value > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) value;
|
||||
}
|
||||
}));
|
||||
|
||||
metrics.addCustomChart(new Metrics.SingleLineChart("invisible_item_frames_placed_in_last_interval", new Callable<Integer>() {
|
||||
@Override
|
||||
public Integer call() throws Exception {
|
||||
return (int) ImageFrame.invisibleFrameManager.getInvisibleItemFramesPlaced().getAndSet(0);
|
||||
long value = ImageFrame.invisibleFrameManager.getInvisibleItemFramesPlaced().getAndSet(0);
|
||||
return value > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) value;
|
||||
}
|
||||
}));
|
||||
|
||||
metrics.addCustomChart(new Metrics.SingleLineChart("embedded_service_image_uploaded_in_last_interval", new Callable<Integer>() {
|
||||
@Override
|
||||
public Integer call() throws Exception {
|
||||
long value = ImageFrame.imageUploadManager.getImagesUploadedCounter().getAndSet(0);
|
||||
return value > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) value;
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2023. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2023. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame (1) (com.loohp).
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2024. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2024. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2023. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2023. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2023. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
+38
-39
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -273,47 +273,46 @@ public class CombinedMapItemHandler implements Listener, AutoCloseable {
|
||||
if (player != null && !entityDamageChecking.add(player)) {
|
||||
return;
|
||||
}
|
||||
ItemStack itemStack = itemFrame.getItem();
|
||||
if (itemStack == null || !itemStack.getType().equals(Material.FILLED_MAP)) {
|
||||
entityDamageChecking.remove(player);
|
||||
return;
|
||||
}
|
||||
CombinedMapItemInfo mapItemInfo = NMS.getInstance().getCombinedMapItemInfo(itemStack);
|
||||
if (mapItemInfo == null || !mapItemInfo.hasPlacement()) {
|
||||
entityDamageChecking.remove(player);
|
||||
return;
|
||||
}
|
||||
CombinedMapItemInfo.PlacementInfo placement = mapItemInfo.getPlacement();
|
||||
int id = mapItemInfo.getImageMapIndex();
|
||||
float yaw = placement.getYaw();
|
||||
UUID uuid = placement.getUniqueId();
|
||||
ImageMap imageMap = ImageFrame.imageMapManager.getFromImageId(id);
|
||||
if (imageMap == null) {
|
||||
entityDamageChecking.remove(player);
|
||||
return;
|
||||
}
|
||||
ItemFrameSelectionManager.SelectedItemFrameResult selection = findItemFrames(itemFrame, yaw, imageMap.getWidth(), imageMap.getHeight(), item -> {
|
||||
if (item == null || !item.getType().equals(Material.FILLED_MAP)) {
|
||||
return false;
|
||||
try {
|
||||
ItemStack itemStack = itemFrame.getItem();
|
||||
if (itemStack == null || !itemStack.getType().equals(Material.FILLED_MAP)) {
|
||||
return;
|
||||
}
|
||||
CombinedMapItemInfo info = NMS.getInstance().getCombinedMapItemInfo(item);
|
||||
if (info == null || !info.hasPlacement()) {
|
||||
return false;
|
||||
CombinedMapItemInfo mapItemInfo = NMS.getInstance().getCombinedMapItemInfo(itemStack);
|
||||
if (mapItemInfo == null || !mapItemInfo.hasPlacement()) {
|
||||
return;
|
||||
}
|
||||
return info.getImageMapIndex() == id && info.getPlacement().getUniqueId().equals(uuid);
|
||||
});
|
||||
if (selection == null) {
|
||||
CombinedMapItemInfo.PlacementInfo placement = mapItemInfo.getPlacement();
|
||||
int id = mapItemInfo.getImageMapIndex();
|
||||
float yaw = placement.getYaw();
|
||||
UUID uuid = placement.getUniqueId();
|
||||
ImageMap imageMap = ImageFrame.imageMapManager.getFromImageId(id);
|
||||
if (imageMap == null) {
|
||||
return;
|
||||
}
|
||||
ItemFrameSelectionManager.SelectedItemFrameResult selection = findItemFrames(itemFrame, yaw, imageMap.getWidth(), imageMap.getHeight(), item -> {
|
||||
if (item == null || !item.getType().equals(Material.FILLED_MAP)) {
|
||||
return false;
|
||||
}
|
||||
CombinedMapItemInfo info = NMS.getInstance().getCombinedMapItemInfo(item);
|
||||
if (info == null || !info.hasPlacement()) {
|
||||
return false;
|
||||
}
|
||||
return info.getImageMapIndex() == id && info.getPlacement().getUniqueId().equals(uuid);
|
||||
});
|
||||
if (selection == null) {
|
||||
return;
|
||||
}
|
||||
List<ItemFrame> itemFrames = selection.getItemFrames();
|
||||
if (player == null || itemFrames.stream().allMatch(each -> PlayerUtils.isDamageAllowed(player, each))) {
|
||||
itemFrames.forEach(each -> each.setItem(null, false));
|
||||
itemFrame.setItem(getCombinedMap(imageMap), false);
|
||||
} else {
|
||||
player.sendMessage(ImageFrame.messageItemFrameOccupied);
|
||||
}
|
||||
} finally {
|
||||
entityDamageChecking.remove(player);
|
||||
return;
|
||||
}
|
||||
List<ItemFrame> itemFrames = selection.getItemFrames();
|
||||
if (player == null || itemFrames.stream().allMatch(each -> PlayerUtils.isDamageAllowed(player, each))) {
|
||||
itemFrames.forEach(each -> each.setItem(null, false));
|
||||
itemFrame.setItem(getCombinedMap(imageMap), false);
|
||||
} else {
|
||||
player.sendMessage(ImageFrame.messageItemFrameOccupied);
|
||||
}
|
||||
entityDamageChecking.remove(player);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2024. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2024. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2023. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2023. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2023. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2023. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2023. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2023. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2024. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2024. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -137,6 +137,7 @@ public class ImageMapManager implements AutoCloseable {
|
||||
maps.put(map.getImageIndex(), map);
|
||||
for (MapView mapView : map.getMapViews()) {
|
||||
mapsByView.put(mapView, map);
|
||||
deletedMapIds.remove(mapView.getId());
|
||||
}
|
||||
try {
|
||||
map.save();
|
||||
@@ -147,6 +148,7 @@ public class ImageMapManager implements AutoCloseable {
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
saveDeletedMaps();
|
||||
}
|
||||
|
||||
public boolean hasMap(int imageIndex) {
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2023. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2023. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2023. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2023. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2023. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2023. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2023. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2023. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of InteractionVisualizer.
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.loohp.imageframe.upload;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.RemovalNotification;
|
||||
import com.loohp.imageframe.ImageFrame;
|
||||
import com.loohp.imageframe.objectholders.Scheduler;
|
||||
import com.loohp.imageframe.utils.FileUtils;
|
||||
import com.loohp.imageframe.utils.JarUtils;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import org.apache.commons.fileupload.MultipartStream;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class ImageUploadManager implements AutoCloseable {
|
||||
|
||||
public static final Duration EXPIRATION = Duration.ofMinutes(5);
|
||||
|
||||
private final HttpServer server;
|
||||
private final File webRootDir;
|
||||
private final File uploadDir;
|
||||
private final Map<UUID, PendingUpload> pendingUploads;
|
||||
private final AtomicLong imagesUploadedCounter;
|
||||
|
||||
public ImageUploadManager(boolean enabled, int port) {
|
||||
try {
|
||||
this.webRootDir = new File(ImageFrame.plugin.getDataFolder(), "upload/web");
|
||||
this.uploadDir = new File(ImageFrame.plugin.getDataFolder(), "upload/images");
|
||||
FileUtils.removeFolderRecursively(uploadDir);
|
||||
if (!uploadDir.exists()) {
|
||||
uploadDir.mkdirs();
|
||||
}
|
||||
if (!webRootDir.exists()) {
|
||||
webRootDir.mkdirs();
|
||||
}
|
||||
JarUtils.copyFolderFromJar("upload/web", ImageFrame.plugin.getDataFolder(), JarUtils.CopyOption.COPY_IF_NOT_EXIST);
|
||||
Cache<UUID, PendingUpload> cache = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(EXPIRATION)
|
||||
.removalListener((RemovalNotification<UUID, PendingUpload> notification) -> {
|
||||
if (notification.wasEvicted()) {
|
||||
PendingUpload pendingUpload = notification.getValue();
|
||||
if (pendingUpload != null) {
|
||||
pendingUpload.getFuture().completeExceptionally(new LinkTimeoutException());
|
||||
}
|
||||
}
|
||||
})
|
||||
.build();
|
||||
this.pendingUploads = cache.asMap();
|
||||
this.imagesUploadedCounter = new AtomicLong(0);
|
||||
if (enabled) {
|
||||
this.server = HttpServer.create(new InetSocketAddress(port), 0);
|
||||
this.server.createContext("/", new FileHandler());
|
||||
this.server.createContext("/upload", new UploadHandler());
|
||||
this.server.setExecutor(null);
|
||||
this.server.start();
|
||||
} else {
|
||||
this.server = null;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public PendingUpload newPendingUpload(UUID user) {
|
||||
PendingUpload existing = pendingUploads.remove(user);
|
||||
if (existing != null) {
|
||||
existing.getFuture().completeExceptionally(new LinkTimeoutException());
|
||||
}
|
||||
PendingUpload pendingUpload = PendingUpload.create();
|
||||
pendingUploads.put(user, pendingUpload);
|
||||
return pendingUpload;
|
||||
}
|
||||
|
||||
public AtomicLong getImagesUploadedCounter() {
|
||||
return imagesUploadedCounter;
|
||||
}
|
||||
|
||||
public boolean wasUploaded(String url) {
|
||||
try {
|
||||
File file = Paths.get(new URL(url).toURI()).toFile();
|
||||
return uploadDir.equals(file.getParentFile());
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return server != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (server != null) {
|
||||
server.stop(0);
|
||||
}
|
||||
}
|
||||
|
||||
private class FileHandler implements HttpHandler {
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException {
|
||||
if (!exchange.getRequestMethod().equalsIgnoreCase("GET")) {
|
||||
exchange.sendResponseHeaders(405, -1); // Method Not Allowed
|
||||
return;
|
||||
}
|
||||
if (!webRootDir.exists()) {
|
||||
webRootDir.mkdirs();
|
||||
}
|
||||
File file = resolvePath(webRootDir.toPath().toAbsolutePath(), Paths.get("." + exchange.getRequestURI().getPath())).toFile();
|
||||
byte[] bytes;
|
||||
if (file.exists()) {
|
||||
if (file.isDirectory()) {
|
||||
bytes = Files.readAllBytes(new File(file, "index.html").toPath());
|
||||
} else {
|
||||
bytes = Files.readAllBytes(file.toPath());
|
||||
}
|
||||
} else {
|
||||
bytes = Files.readAllBytes(new File(webRootDir, "index.html").toPath());
|
||||
}
|
||||
exchange.getResponseHeaders().set("Content-Type", "text/html");
|
||||
exchange.sendResponseHeaders(200, bytes.length);
|
||||
exchange.getResponseBody().write(bytes);
|
||||
exchange.getResponseBody().close();
|
||||
}
|
||||
|
||||
private Path resolvePath(Path baseDirPath, Path userPath) {
|
||||
Path resolvedPath = baseDirPath.resolve(userPath).normalize();
|
||||
if (!resolvedPath.startsWith(baseDirPath)) {
|
||||
return baseDirPath;
|
||||
}
|
||||
return resolvedPath;
|
||||
}
|
||||
}
|
||||
|
||||
private class UploadHandler implements HttpHandler {
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException {
|
||||
if (!exchange.getRequestMethod().equalsIgnoreCase("POST")) {
|
||||
exchange.sendResponseHeaders(405, -1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract query parameters
|
||||
String query = exchange.getRequestURI().getQuery();
|
||||
Map<String, String> queryParams = parseQueryParams(query);
|
||||
String user = queryParams.get("user");
|
||||
String id = queryParams.get("id");
|
||||
|
||||
PendingUpload pendingUpload = findPendingUpload(user, id);
|
||||
if (pendingUpload == null) {
|
||||
sendResponse(exchange, 400, "{\"error\":\"Invalid or missing user or id\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> contentType = Arrays.asList(exchange.getRequestHeaders().getFirst("Content-Type").split(";"));
|
||||
if (!contentType.get(0).trim().equals("multipart/form-data")) {
|
||||
sendResponse(exchange, 400, "{\"error\":\"Invalid content type\"}");
|
||||
return;
|
||||
}
|
||||
byte[] boundary = contentType.stream()
|
||||
.map(s -> s.trim())
|
||||
.filter(s -> s.startsWith("boundary="))
|
||||
.findFirst()
|
||||
.map(s -> s.substring("boundary=".length()).getBytes(StandardCharsets.UTF_8))
|
||||
.orElse(null);
|
||||
if (boundary == null) {
|
||||
sendResponse(exchange, 400, "{\"error\":\"Invalid multipart boundary\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
SizeLimitedByteArrayOutputStream output = new SizeLimitedByteArrayOutputStream(ImageFrame.maxImageFileSize);
|
||||
|
||||
try (InputStream inputStream = exchange.getRequestBody()) {
|
||||
MultipartStream multipartStream = new MultipartStream(inputStream, boundary, 2048, null);
|
||||
boolean nextPart = multipartStream.skipPreamble();
|
||||
while (nextPart) {
|
||||
List<String> headers = Arrays.asList(multipartStream.readHeaders().split(";"));
|
||||
String name = headers.stream()
|
||||
.map(s -> s.trim()).filter(s -> s.startsWith("name="))
|
||||
.findFirst()
|
||||
.map(s -> s.substring("name=".length()))
|
||||
.orElse(null);
|
||||
if ("image".equals(name) || "\"image\"".equals(name)) {
|
||||
multipartStream.readBodyData(output);
|
||||
break;
|
||||
} else {
|
||||
multipartStream.discardBodyData();
|
||||
nextPart = multipartStream.readBoundary();
|
||||
}
|
||||
}
|
||||
}
|
||||
byte[] fileData = output.toByteArray();
|
||||
|
||||
// Ensure upload directory exists
|
||||
if (!uploadDir.exists()) {
|
||||
uploadDir.mkdir();
|
||||
}
|
||||
|
||||
// Save the file with UUID as the filename
|
||||
File outputFile = new File(uploadDir, id + ".png");
|
||||
Files.write(outputFile.toPath(), fileData);
|
||||
imagesUploadedCounter.incrementAndGet();
|
||||
|
||||
pendingUploads.remove(UUID.fromString(user));
|
||||
pendingUpload.getFuture().complete(outputFile);
|
||||
Scheduler.runTaskLaterAsynchronously(ImageFrame.plugin, () -> outputFile.delete(), EXPIRATION.toMillis() / 50);
|
||||
|
||||
// Send response
|
||||
sendResponse(exchange, 200, "{\"message\":\"File uploaded successfully\"}");
|
||||
}
|
||||
|
||||
// Parse query parameters from URL
|
||||
private Map<String, String> parseQueryParams(String query) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
if (query != null) {
|
||||
String[] pairs = query.split("&");
|
||||
for (String pair : pairs) {
|
||||
String[] keyValue = pair.split("=");
|
||||
if (keyValue.length == 2) {
|
||||
map.put(keyValue[0], keyValue[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private PendingUpload findPendingUpload(String user, String id) {
|
||||
try {
|
||||
PendingUpload pendingUpload = pendingUploads.get(UUID.fromString(user));
|
||||
if (!pendingUpload.getId().equals(UUID.fromString(id))) {
|
||||
return null;
|
||||
}
|
||||
return pendingUpload;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Send JSON response
|
||||
private void sendResponse(HttpExchange exchange, int statusCode, String message) throws IOException {
|
||||
exchange.getResponseHeaders().set("Content-Type", "application/json");
|
||||
exchange.sendResponseHeaders(statusCode, message.length());
|
||||
exchange.getResponseBody().write(message.getBytes());
|
||||
exchange.getResponseBody().close();
|
||||
}
|
||||
}
|
||||
|
||||
public static class LinkTimeoutException extends Exception {
|
||||
|
||||
public LinkTimeoutException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LinkTimeoutException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public LinkTimeoutException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public LinkTimeoutException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.loohp.imageframe.upload;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
public class PendingUpload {
|
||||
|
||||
public static PendingUpload create() {
|
||||
return new PendingUpload(UUID.randomUUID(), System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(5), new CompletableFuture<>());
|
||||
}
|
||||
|
||||
private final UUID id;
|
||||
private final long expire;
|
||||
private final CompletableFuture<File> future;
|
||||
|
||||
private PendingUpload(UUID id, long expire, CompletableFuture<File> future) {
|
||||
this.id = id;
|
||||
this.expire = expire;
|
||||
this.future = future;
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public long getExpire() {
|
||||
return expire;
|
||||
}
|
||||
|
||||
protected CompletableFuture<File> getFuture() {
|
||||
return future;
|
||||
}
|
||||
|
||||
public File getFileBlocking() throws InterruptedException, ImageUploadManager.LinkTimeoutException {
|
||||
try {
|
||||
return future.get(expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
|
||||
} catch (TimeoutException | ExecutionException e) {
|
||||
throw new ImageUploadManager.LinkTimeoutException();
|
||||
}
|
||||
}
|
||||
|
||||
public String getUrl(String host, UUID user) {
|
||||
String name = Bukkit.getOfflinePlayer(user).getName();
|
||||
if (name == null) {
|
||||
return host + "?user=" + user + "&id=" + id + "&expire=" + expire;
|
||||
} else {
|
||||
return host + "?user=" + user + "&id=" + id + "&expire=" + expire + "&name=" + name;
|
||||
}
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.loohp.imageframe.upload;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
public class SizeLimitedByteArrayOutputStream extends ByteArrayOutputStream {
|
||||
|
||||
private final long maxSize;
|
||||
|
||||
public SizeLimitedByteArrayOutputStream(long maxSize) {
|
||||
this.maxSize = maxSize;
|
||||
}
|
||||
|
||||
private void ensureSize(int added) {
|
||||
if ((size() + added) > maxSize) {
|
||||
throw new IllegalStateException("Size exceeded max size of " + maxSize + " bytes");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void write(int b) {
|
||||
ensureSize(1);
|
||||
super.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void write(byte[] b, int off, int len) {
|
||||
ensureSize(len);
|
||||
super.write(b, off, len);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2023. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2024. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2024. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This file is part of ImageFrame.
|
||||
*
|
||||
* Copyright (C) 2022. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2022. Contributors
|
||||
* Copyright (C) 2025. LoohpJames <jamesloohp@gmail.com>
|
||||
* Copyright (C) 2025. Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
Loaded 100 of 112 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user