Skip to content

Commit

Permalink
clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
paulzzh committed May 14, 2024
1 parent a1ef964 commit ca68960
Show file tree
Hide file tree
Showing 10 changed files with 250 additions and 231 deletions.
12 changes: 4 additions & 8 deletions urlimg-common/src/main/java/com/paulzzh/urlimg/Image.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
import java.math.BigDecimal;
import java.math.RoundingMode;

public class Image {
public class Image<I> {
private String hash;
private Object image;
private I image;
private int width;
private int height;

public Image(String hash, Object image, int width, int height, int maxHeight) {
public Image(String hash, I image, int width, int height, int maxHeight) {
this.hash = hash;
this.image = image;
BigDecimal b = new BigDecimal((float) height / width);
Expand All @@ -22,17 +22,13 @@ public Image(String hash, Object image, int width, int height, int maxHeight) {
this.height = maxHeight;
this.width = (int) (maxHeight / hx);
}
while ((this.width > 300 || this.height > maxHeight) && this.height > 16) {
this.height--;
this.width = (int) (this.height / hx);
}
}

public String getHash() {
return this.hash;
}

public Object getImage() {
public I getImage() {
return this.image;
}

Expand Down
117 changes: 74 additions & 43 deletions urlimg-common/src/main/java/com/paulzzh/urlimg/ImageManager.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
package com.paulzzh.urlimg;

import javax.net.ssl.HttpsURLConnection;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public interface ImageManager {
Map<String, Image> cache = Collections.synchronizedMap(new HashMap<>());
Map<String, List<Image>> images = Collections.synchronizedMap(new HashMap<>());
public abstract class ImageManager {
private static final Map<String, Image<?>> cache = Collections.synchronizedMap(new HashMap<>());
private static final Map<String, List<Image<?>>> images = Collections.synchronizedMap(new HashMap<>());
private static final List<String> hashes = Collections.synchronizedList(new ArrayList<>());
private final ExecutorService executor = Executors.newCachedThreadPool();
private final ExecutorService executor2 = Executors.newCachedThreadPool();

static String bytesToHex(byte[] hash) {
public static String bytesToHex(byte[] hash) {
StringBuilder hexString = new StringBuilder(2 * hash.length);
for (byte b : hash) {
String hex = Integer.toHexString(0xff & b);
Expand All @@ -25,69 +36,89 @@ static String bytesToHex(byte[] hash) {
return hexString.toString();
}

static Image getImage(String hash) {
return cache.get(hash);
}
public abstract Image<?> readImage(String hash, InputStream in);

public abstract Image<?> readAndSaveImage(String hash, InputStream in, File out);

public abstract void showImages(String id);

static List<Image> getImages(String hash) {
return images.get(hash);
public List<Image<?>> getImages(String hash) {
synchronized (images) {
return images.get(hash);
}
}

default void addImages(List<String> list) {
new Thread(() -> {
List<Image> imgs = new ArrayList<>();
public void addImages(List<String> list) {
executor.submit(() -> {
List<Image<?>> imgs = new ArrayList<>();
List<Future<Image<?>>> futures = new ArrayList<>();
for (String url : list) {
Image img = addImage(url);
if (img != null) {
imgs.add(img);
futures.add(executor2.submit(() -> addImage(url)));
}
for (Future<Image<?>> future : futures) {
try {
Image<?> img = future.get();
if (img != null) {
imgs.add(img);
}
} catch (Exception ignored) {

}
}
if (!imgs.isEmpty()) {
final String uuid = UUID.randomUUID().toString().replace("-", "");
images.put(uuid, imgs);
synchronized (images) {
images.put(uuid, imgs);
}
showImages(uuid);
}
}).start();
});
}

default Image addImage(String url) {
public Image<?> addImage(String url) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
String hash = bytesToHex(md.digest(url.getBytes(StandardCharsets.UTF_8)));
Path path = Paths.get("urlimgcache/" + hash + ".png");
File out = Paths.get("urlimgcache/" + hash + ".png").toFile();
Files.createDirectories(Paths.get("urlimgcache/"));
if (cache.containsKey(hash)) {
return cache.get(hash);
} else if (path.toFile().isFile()) {
Image img = readImage(hash, Files.newInputStream(path));
if (img == null) {
img = readImage(hash, new URL(url).openStream());
if (img != null) {
saveImage(img, path);
synchronized (hashes) {
if (hashes.contains(hash)) {
hash = hashes.get(hashes.indexOf(hash));
} else {
hashes.add(hash);
}
}
synchronized (hash) {
synchronized (cache) {
if (cache.containsKey(hash)) {
return cache.get(hash);
}
}
if (img != null) {
cache.put(hash, img);
return cache.get(hash);
Image<?> img;
if (out.isFile()) {
img = readImage(hash, new FileInputStream(out));
} else {
URL u = new URL(url);
URLConnection conn = u.openConnection();
if (conn instanceof HttpURLConnection || conn instanceof HttpsURLConnection) {
conn.setConnectTimeout(10000);
conn.setReadTimeout(10000);
conn.setRequestProperty("User-Agent", "urlimg");
img = readAndSaveImage(hash, conn.getInputStream(), out);
} else {
throw new MalformedURLException("no protocol: " + u.getProtocol());
}
}
} else {
Image img = readImage(hash, new URL(url).openStream());
if (img != null) {
saveImage(img, path);
cache.put(hash, img);
return cache.get(hash);
synchronized (cache) {
cache.put(hash, img);
}
}
return img;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return null;
}

Image readImage(String hash, InputStream bin);

void saveImage(Image obj, Path out);

void showImages(String id);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,59 @@

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static net.minecraft.text.ClickEvent.Action.OPEN_URL;

public class Mod implements ClientModInitializer, ImageManager {
public class Mod implements ClientModInitializer {
// This logger is used to write text to the console and the log file.
// It is considered best practice to use your mod id as the logger's name.
// That way, it's clear which mod wrote info, warnings, and errors.
public static final Logger LOGGER = LoggerFactory.getLogger("urlimg");
public static final Map<OrderedText, StringVisitable> line_map = new HashMap<>();
private static final int line = 5;
private static final int line_height = 10;
public static final ImageManager IM = new ImageManager() {
public void showImages(String msg) {
MinecraftClient mc = MinecraftClient.getInstance();
mc.inGameHud.getChatHud().addMessage(Text.of("urlimg=" + msg));
for (int i = 0; i < line; i++) {
mc.inGameHud.getChatHud().addMessage(Text.of(""));
}
}

@Override
public Image<NativeImage> readImage(String hash, InputStream in) {
try {
NativeImage nativeImage = NativeImage.read(in);
Identifier id = Identifier.of("urlimg", hash);
MinecraftClient.getInstance().getTextureManager().registerTexture(id, new NativeImageBackedTexture(nativeImage));
return new Image<>(hash, nativeImage, nativeImage.getWidth(), nativeImage.getHeight(), line * line_height);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

@Override
public Image<NativeImage> readAndSaveImage(String hash, InputStream in, File out) {
try {
BufferedImage bufferedImage = ImageIO.read(in); //1.20.3+ can't read jpeg
ImageIO.write(bufferedImage, "png", out);
LOGGER.info("cache image: {}", out.getName());
return readImage(hash, new FileInputStream(out));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
};

public static List<String> getLinksFromChat(Text message) {
List<String> list = new ArrayList<>();
Expand All @@ -56,51 +90,15 @@ public static void getLinksFromChat1(List<String> list, Text message) {
String url = event.getValue();
if (!list.contains(url)) {
list.add(url);
LOGGER.info(url);
//LOGGER.info(url);
}
}
}

@Override
public void onInitializeClient() {
LOGGER.info("Hello Fabric world!");
ClientReceiveMessageEvents.CHAT.register((message, signedMessage, sender, params, receptionTimestamp) -> {
addImages(getLinksFromChat(message));
});
ClientReceiveMessageEvents.GAME.register((message, overlay) -> {
addImages(getLinksFromChat(message));
});
}

public void showImages(String msg) {
MinecraftClient mc = MinecraftClient.getInstance();
mc.inGameHud.getChatHud().addMessage(Text.of("urlimg=" + msg));
for (int i = 0; i < line; i++) {
mc.inGameHud.getChatHud().addMessage(Text.of(""));
}
}

public Image readImage(String hash, InputStream bin) {
try {
BufferedImage bufferedImage = ImageIO.read(bin); //1.20.3+ can't read jpeg
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "png", byteArrayOut);
NativeImage nativeImage = NativeImage.read(new ByteArrayInputStream(byteArrayOut.toByteArray()));
Identifier id = Identifier.of("urlimg", hash);
MinecraftClient.getInstance().getTextureManager().registerTexture(id, new NativeImageBackedTexture(nativeImage));
return new Image(hash, nativeImage, nativeImage.getWidth(), nativeImage.getHeight(), line * line_height);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

public void saveImage(Image image, Path out) {
try {
NativeImage nativeImage = (NativeImage) image.getImage();
nativeImage.writeTo(out);
} catch (Exception e) {
e.printStackTrace();
}
ClientReceiveMessageEvents.CHAT.register((message, signedMessage, sender, params, receptionTimestamp) -> IM.addImages(getLinksFromChat(message)));
ClientReceiveMessageEvents.GAME.register((message, overlay) -> IM.addImages(getLinksFromChat(message)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import com.llamalad7.mixinextras.sugar.ref.LocalIntRef;
import com.mojang.blaze3d.systems.RenderSystem;
import com.paulzzh.urlimg.Image;
import com.paulzzh.urlimg.ImageManager;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.hud.ChatHud;
import net.minecraft.client.util.math.MatrixStack;
Expand All @@ -15,6 +14,7 @@
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

import static com.paulzzh.urlimg.Mod.IM;
import static com.paulzzh.urlimg.Mod.line_map;
import static net.minecraft.client.gui.DrawableHelper.drawTexture;

Expand All @@ -34,7 +34,7 @@ private int injected3(TextRenderer instance, MatrixStack matrixStack, OrderedTex
String uuid = sv.getString().substring(7, 39);
RenderSystem.enableBlend();
int indexX = 0;
for (Image img : ImageManager.getImages(uuid)) {
for (Image<?> img : IM.getImages(uuid)) {
RenderSystem.setShaderTexture(0, Identifier.of("urlimg", img.getHash()));
drawTexture(matrixStack, indexX, argRef.get(), 0, 0, img.getWidth(), img.getHeight(), img.getWidth(), img.getHeight());
indexX += img.getWidth();
Expand Down
Loading

0 comments on commit ca68960

Please sign in to comment.