From edd61363546f69a8677df52c2b15b9d5cb5ba79d Mon Sep 17 00:00:00 2001 From: Algent Date: Fri, 14 Aug 2026 22:08:30 +0200 Subject: [PATCH] refactor: port MicroMaterialRegistry to Java Replaces MicroMaterialRegistry.scala with a Java registry, its companion singleton and the two nested interfaces. Both nested interfaces are descriptor-identical to the reference and MODULE$ keeps every instance method ProjRed links against. Ten jars reference this type and three more reach it reflectively, so the surface was checked member by member rather than by descriptor count. getIdMap keeps its scala.Tuple2 array because extrautilities links against it, so the registry still stores tuples internally. readIDMap moves from scala.collection.Seq to java.util.List, which no jar references; the one in-repo caller moved from mkString to String.join. That clears one of the five Scala-typed descriptors the inventory identified. Three removals, all verified unreferenced: the mangled public accessors Scala emitted so its closure classes could reach private state, IMicroMaterial$class, and the MissingMicroMaterial forwarders for the two members it does not override. The last of those was caught by the characterization failing to compile, not by inspection. IMicroMaterial's loadIcons, canRenderInPass and isSolid become real Java defaults, so implementors can inherit rather than restate them. Eleven anonfun classes are gone. Validated with 73 plain-JVM tests passing against both the Scala baseline and the port, a clean build, and the Java 8 Forge dedicated-server suite, which exercises setupIDMap and calcMaxCuttingStrength during real startup. --- JAVA_MIGRATION_DIVERGENCES.md | 70 +++++ .../microblock/MicroMaterialRegistry$.java | 100 ++++++ .../microblock/MicroMaterialRegistry.java | 285 ++++++++++++++++++ .../microblock/MicroMaterialRegistry.scala | 255 ---------------- .../microblock/handler/packethandlers.scala | 2 +- ...oMaterialRegistryCharacterizationTest.java | 12 +- 6 files changed, 463 insertions(+), 261 deletions(-) create mode 100644 src/main/scala/codechicken/microblock/MicroMaterialRegistry$.java create mode 100644 src/main/scala/codechicken/microblock/MicroMaterialRegistry.java delete mode 100644 src/main/scala/codechicken/microblock/MicroMaterialRegistry.scala diff --git a/JAVA_MIGRATION_DIVERGENCES.md b/JAVA_MIGRATION_DIVERGENCES.md index 77c4e8b..86390f4 100644 --- a/JAVA_MIGRATION_DIVERGENCES.md +++ b/JAVA_MIGRATION_DIVERGENCES.md @@ -489,3 +489,73 @@ and deliberately ignore overrides. Both behaviors are preserved as found and are - Complete plain-JVM suite: 65 tests, 0 failures, 0 errors. - Clean `spotlessApply checkstyleTest build`: passing. - Java 8 Forge dedicated-server suite: 3 tests, 0 failures, 0 errors. + +## 2026-08-14 — MicroMaterialRegistry Java port + +The first stateful registry converted, and the widest surface so far: ten jars reference the type and three more reach +it reflectively. Covers `MicroMaterialRegistry`, `MicroMaterialRegistry$` and the two nested interfaces. + +### Observable behavior + +No known divergence. `setupIDMap` still sorts the type map by name into the id array so ids are indexes into it, +`materialID` and `materialName` still round trip, `remapName` still resolves on both `getMaterial(String)` and +`materialID`, `getMissingId` still fails loudly when the placeholder is absent rather than falling back to zero, ids +still round trip through the shared `IDWriter`, and a highlight renderer that claims the highlight still short-circuits +the default renderer. + +`calcMaxCuttingStrength` still throws when no saw is registered. The reference reached that through `max` on an empty +collection; the port throws `UnsupportedOperationException` explicitly to keep the same failure rather than silently +leaving the field at zero. + +### Changed API: readIDMap + +Accepted divergence: `readIDMap` returns `java.util.List` instead of `scala.collection.Seq`. No jar in +the pack references it, and the only caller is the in-repo material registration packet handler, which was updated +from `mkString` to `String.join`. This removes one of the five Scala-typed descriptors the ABI inventory identified. + +`getIdMap()[Lscala/Tuple2;` is deliberately **not** changed, because extrautilities links against it. The registry +therefore still stores `scala.Tuple2` internally rather than converting on every call. + +### Removed API + +- The three mangled accessors Scala emitted as public so its closure classes could reach private state: + `codechicken$microblock$MicroMaterialRegistry$$idMap()`, `$$typeMap()` and `$$nameMap()`. They are compiler + artifacts, not API, and no jar references them. +- `MicroMaterialRegistry$IMicroMaterial$class`, along with its four statics. No jar references it. All ten + implementors reach `IMicroMaterial` through `BlockMicroMaterial`, which is in-repo, so nothing external carries + forwarders to the helper. +- `MissingMicroMaterial.canRenderInPass(int)` and `MissingMicroMaterial.isSolid()` static forwarders, plus the + matching instance methods on `MissingMicroMaterial$`. That object overrides neither, so with the members now being + Java interface defaults Scala emits no forwarder and therefore no static forwarder either. Nothing in the pack + references `MissingMicroMaterial` at all. This is the same class of change as `ItemSaw` in the `Saw` port, and the + characterization caught it by failing to compile. + +### Added API + +`setupIDMap`, `calcMaxCuttingStrength` and `loadIcons` gain static forwarders on `MicroMaterialRegistry`. They were +`private[microblock]` in Scala, which is public on the JVM but produces no static forwarder. Additive. + +### IMicroMaterial defaults + +`loadIcons`, `canRenderInPass` and `isSolid` become real Java defaults. Neither nested interface has a superclass to +lose to, and both in-repo implementors, `BlockMicroMaterial` and `MissingMicroMaterial`, extend nothing else. Java +implementors can now inherit the three instead of restating them; both nested interfaces are descriptor-identical to +the reference. + +### Compiler artifacts + +Accepted divergence: all eleven `MicroMaterialRegistry$$anonfun$*` classes are removed. The Java loops produce no +replacement classes. + +### Validation + +- `MicroMaterialRegistryCharacterizationTest`: 7 tests, 0 failures, 0 errors, passing against both the Scala baseline + and the port. +- `MicroMaterialRegistryBinaryCompatibilityTest`: 1 test, 0 failures, 0 errors, driving a reference-compiled Scala + consumer through `MODULE$` and the raw `scala.Tuple2` array. +- Complete plain-JVM suite: 73 tests, 0 failures, 0 errors. +- Clean `spotlessApply checkstyleTest build`: passing. +- Java 8 Forge dedicated-server suite: 3 tests, 0 failures, 0 errors. This exercises the real path, since server + startup calls `setupIDMap`, `calcMaxCuttingStrength` and the default content registration. +- Error paths remain uncovered by tests: they call the microblock logger, which is null until `MicroblockProxy.preInit` + runs, so they cannot execute headless. They are unchanged from the reference. diff --git a/src/main/scala/codechicken/microblock/MicroMaterialRegistry$.java b/src/main/scala/codechicken/microblock/MicroMaterialRegistry$.java new file mode 100644 index 0000000..b540b2e --- /dev/null +++ b/src/main/scala/codechicken/microblock/MicroMaterialRegistry$.java @@ -0,0 +1,100 @@ +package codechicken.microblock; + +import java.util.List; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.MovingObjectPosition; + +import codechicken.lib.data.MCDataInput; +import codechicken.lib.data.MCDataOutput; +import codechicken.lib.packet.PacketCustom; +import codechicken.microblock.MicroMaterialRegistry.IMicroHighlightRenderer; +import codechicken.microblock.MicroMaterialRegistry.IMicroMaterial; +import scala.Tuple2; + +/** + * Scala companion singleton. Retained because compiled Scala consumers read MODULE$ and call these instance methods. + */ +public final class MicroMaterialRegistry$ { + + public static final MicroMaterialRegistry$ MODULE$ = new MicroMaterialRegistry$(); + + private MicroMaterialRegistry$() {} + + public void registerMaterial(IMicroMaterial material, String name) { + MicroMaterialRegistry.registerMaterial(material, name); + } + + public void replaceMaterial(IMicroMaterial material, String name) { + MicroMaterialRegistry.replaceMaterial(material, name); + } + + public void registerHighlightRenderer(IMicroHighlightRenderer handler) { + MicroMaterialRegistry.registerHighlightRenderer(handler); + } + + public void remapName(String oldName, String newName) { + MicroMaterialRegistry.remapName(oldName, newName); + } + + public void setupIDMap() { + MicroMaterialRegistry.setupIDMap(); + } + + public int getMissingId() { + return MicroMaterialRegistry.getMissingId(); + } + + public void calcMaxCuttingStrength() { + MicroMaterialRegistry.calcMaxCuttingStrength(); + } + + public void loadIcons() { + MicroMaterialRegistry.loadIcons(); + } + + public int getMaxCuttingStrength() { + return MicroMaterialRegistry.getMaxCuttingStrength(); + } + + public void writeIDMap(PacketCustom packet) { + MicroMaterialRegistry.writeIDMap(packet); + } + + public List readIDMap(PacketCustom packet) { + return MicroMaterialRegistry.readIDMap(packet); + } + + public void writeMaterialID(MCDataOutput data, int id) { + MicroMaterialRegistry.writeMaterialID(data, id); + } + + public int readMaterialID(MCDataInput data) { + return MicroMaterialRegistry.readMaterialID(data); + } + + public String materialName(int id) { + return MicroMaterialRegistry.materialName(id); + } + + public int materialID(String name) { + return MicroMaterialRegistry.materialID(name); + } + + public IMicroMaterial getMaterial(String name) { + return MicroMaterialRegistry.getMaterial(name); + } + + public IMicroMaterial getMaterial(int id) { + return MicroMaterialRegistry.getMaterial(id); + } + + public Tuple2[] getIdMap() { + return MicroMaterialRegistry.getIdMap(); + } + + public boolean renderHighlight(EntityPlayer player, MovingObjectPosition hit, CommonMicroClass mcrClass, int size, + int material) { + return MicroMaterialRegistry.renderHighlight(player, hit, mcrClass, size, material); + } +} diff --git a/src/main/scala/codechicken/microblock/MicroMaterialRegistry.java b/src/main/scala/codechicken/microblock/MicroMaterialRegistry.java new file mode 100644 index 0000000..782fe2b --- /dev/null +++ b/src/main/scala/codechicken/microblock/MicroMaterialRegistry.java @@ -0,0 +1,285 @@ +package codechicken.microblock; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import net.minecraft.block.Block.SoundType; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.IIcon; +import net.minecraft.util.MovingObjectPosition; + +import codechicken.lib.data.MCDataInput; +import codechicken.lib.data.MCDataOutput; +import codechicken.lib.packet.PacketCustom; +import codechicken.lib.vec.Cuboid6; +import codechicken.lib.vec.Vector3; +import codechicken.microblock.handler.MicroblockProxy; +import codechicken.multipart.IDWriter; +import codechicken.multipart.MultiPartRegistry; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import scala.Tuple2; + +public final class MicroMaterialRegistry { + + /** Interface for defining a micro material. */ + public interface IMicroMaterial { + + /** The icon to be used for breaking particles on side. */ + @SideOnly(Side.CLIENT) + IIcon getBreakingIcon(int side); + + /** Callback to load icons from the underlying block/etc. */ + @SideOnly(Side.CLIENT) + default void loadIcons() {} + + /** + * This function must configure and use the CCRenderState pipeline to draw from the current vertex source. + * CCRenderState.lightMatrix will be set. + * + * @param pass The current render pass, -1 for inventory rendering + * @param bounds The cuboid bounds of the face being rendered + */ + @SideOnly(Side.CLIENT) + void renderMicroFace(Vector3 pos, int pass, Cuboid6 bounds); + + /** Get the render pass for which this material renders in. */ + @SideOnly(Side.CLIENT) + default boolean canRenderInPass(int pass) { + return pass == 0; + } + + /** Return true if this material is not opaque (glass, ice). */ + boolean isTransparent(); + + /** Return the light level emitted by this material (glowstone). */ + int getLightValue(); + + /** Return the strength of this material. */ + float getStrength(EntityPlayer player); + + /** Return the localised name of this material (normally the block name). */ + String getLocalizedName(); + + /** Get the item that this material is cut from (full block to slabs). */ + ItemStack getItem(); + + /** Get the strength of saw requried to cut this material. */ + int getCutterStrength(); + + /** Get the breaking/walking sound. */ + SoundType getSound(); + + /** Return true if this material is solid and opaque (can run wires on etc). */ + default boolean isSolid() { + return !isTransparent(); + } + + /** Get the explosion resistance of this part to an explosion caused by entity. */ + float explosionResistance(Entity entity); + } + + /** + * Interface for overriding the default micro placement highlight handler to show the effect of placement on a + * certain block/part. + */ + public interface IMicroHighlightRenderer { + + /** Return true if a custom highlight was rendered and the default should be skipped. */ + boolean renderHighlight(EntityPlayer player, MovingObjectPosition hit, CommonMicroClass mcrClass, int size, + int material); + } + + private static final Map typeMap = new HashMap<>(); + private static final Map nameMap = new HashMap<>(); + private static Tuple2[] idMap; + private static final IDWriter idWriter = new IDWriter(); + + private static final List highlightRenderers = new ArrayList<>(); + private static int maxCuttingStrength; + + private static final Map remap = new HashMap<>(); + private static int missingId; + + private MicroMaterialRegistry() {} + + /** Register a micro material with unique identifier name. */ + public static void registerMaterial(IMicroMaterial material, String name) { + if (MultiPartRegistry.loaded()) { + throw new IllegalStateException("You must register your materials in the init methods."); + } + + if (typeMap.containsKey(name)) { + MicroblockProxy.logger().error("Material with id " + name + " is already registered."); + return; + } + + typeMap.put(name, material); + } + + /** Replace a micro material with unique identifier name. */ + public static void replaceMaterial(IMicroMaterial material, String name) { + if (MultiPartRegistry.loaded()) { + throw new IllegalStateException("You must register your materials in the init methods."); + } + + if (typeMap.remove(name) == null) { + MicroblockProxy.logger().error("Material with id " + name + " was not registered."); + } + + MicroblockProxy.logger().debug("Replaced micro material: " + name); + + typeMap.put(name, material); + } + + /** Registers a highlight renderer. */ + public static void registerHighlightRenderer(IMicroHighlightRenderer handler) { + highlightRenderers.add(handler); + } + + public static void remapName(String oldName, String newName) { + remap.put(oldName, newName); + } + + @SuppressWarnings("unchecked") + public static void setupIDMap() { + List> entries = new ArrayList<>(typeMap.entrySet()); + entries.sort(Comparator.comparing(Map.Entry::getKey)); + + idMap = new Tuple2[entries.size()]; + for (int i = 0; i < entries.size(); i++) { + idMap[i] = new Tuple2<>(entries.get(i).getKey(), entries.get(i).getValue()); + } + + idWriter.setMax(idMap.length); + nameMap.clear(); + for (int i = 0; i < idMap.length; i++) { + nameMap.put(idMap[i]._1(), i); + } + + Integer missing = nameMap.get(MissingMicroMaterial.key()); + if (missing == null) { + throw new IllegalStateException( + "MissingMicroMaterial is not registered; the placeholder must never fall back to id 0."); + } + missingId = missing; + } + + public static int getMissingId() { + return missingId; + } + + public static void calcMaxCuttingStrength() { + int max = Integer.MIN_VALUE; + boolean found = false; + for (Iterator it = Item.itemRegistry.iterator(); it.hasNext();) { + Object next = it.next(); + if (next instanceof Saw) { + max = Math.max(max, ((Saw) next).getMaxCuttingStrength()); + found = true; + } + } + if (!found) { + // Matches the reference, where max on an empty collection throws. + throw new UnsupportedOperationException("empty.max"); + } + maxCuttingStrength = max; + } + + public static void loadIcons() { + if (idMap != null) { + for (Tuple2 entry : idMap) { + entry._2().loadIcons(); + } + } + } + + public static int getMaxCuttingStrength() { + return maxCuttingStrength; + } + + public static void writeIDMap(PacketCustom packet) { + packet.writeInt(idMap.length); + for (Tuple2 entry : idMap) { + packet.writeString(entry._1()); + } + } + + /** Reads the server's id map, returning the names this client has no material for. */ + @SuppressWarnings("unchecked") + public static List readIDMap(PacketCustom packet) { + int k = packet.readInt(); + idWriter.setMax(k); + idMap = new Tuple2[k]; + nameMap.clear(); + List missing = new ArrayList<>(); + for (int i = 0; i < k; i++) { + String s = packet.readString(); + IMicroMaterial v = typeMap.get(s); + if (v == null) { + missing.add(s); + } else { + idMap[i] = new Tuple2<>(s, v); + nameMap.put(s, i); + } + } + return missing; + } + + public static void writeMaterialID(MCDataOutput data, int id) { + idWriter.write(data, id); + } + + public static int readMaterialID(MCDataInput data) { + return idWriter.read(data); + } + + public static String materialName(int id) { + return idMap[id]._1(); + } + + public static int materialID(String name) { + Integer id = nameMap.get(remapped(name)); + if (id == null) { + MicroblockProxy.logger().error("Missing mapping for part with ID: " + name); + return missingId; + } + return id; + } + + public static IMicroMaterial getMaterial(String name) { + return typeMap.get(remapped(name)); + } + + public static IMicroMaterial getMaterial(int id) { + return idMap[id]._2(); + } + + public static Tuple2[] getIdMap() { + return idMap; + } + + public static boolean renderHighlight(EntityPlayer player, MovingObjectPosition hit, CommonMicroClass mcrClass, + int size, int material) { + for (IMicroHighlightRenderer renderer : highlightRenderers) { + if (renderer.renderHighlight(player, hit, mcrClass, size, material)) { + return true; + } + } + + MicroblockRender.renderHighlight(player, hit, mcrClass, size, material); + return true; + } + + private static String remapped(String name) { + String replacement = remap.get(name); + return replacement == null ? name : replacement; + } +} diff --git a/src/main/scala/codechicken/microblock/MicroMaterialRegistry.scala b/src/main/scala/codechicken/microblock/MicroMaterialRegistry.scala deleted file mode 100644 index ca9f314..0000000 --- a/src/main/scala/codechicken/microblock/MicroMaterialRegistry.scala +++ /dev/null @@ -1,255 +0,0 @@ -package codechicken.microblock - -import codechicken.multipart.IDWriter -import codechicken.lib.packet.PacketCustom -import scala.collection.mutable.HashMap -import codechicken.lib.data.MCDataOutput -import codechicken.lib.data.MCDataInput -import codechicken.multipart.MultiPartRegistry -import cpw.mods.fml.relauncher.SideOnly -import cpw.mods.fml.relauncher.Side -import codechicken.lib.vec.{Cuboid6, Vector3} -import net.minecraft.util.IIcon -import net.minecraft.entity.player.EntityPlayer -import net.minecraft.item.{Item, ItemStack} -import scala.collection.mutable.ListBuffer -import net.minecraft.util.MovingObjectPosition -import net.minecraft.entity.Entity -import scala.collection.JavaConversions._ -import java.util.{Iterator => JIterator} -import net.minecraft.block.Block.SoundType - -object MicroMaterialRegistry { - - /** Interface for defining a micro material - */ - trait IMicroMaterial { - - /** The icon to be used for breaking particles on side - */ - @SideOnly(Side.CLIENT) - def getBreakingIcon(side: Int): IIcon - - /** Callback to load icons from the underlying block/etc - */ - @SideOnly(Side.CLIENT) - def loadIcons() {} - - /** This function must configure and use the CCRenderState pipeline to draw - * from the current vertex source. CCRenderState.lightMatrix will be set. - * @param pass - * The current render pass, -1 for inventory rendering - * @param bounds - * The cuboid bounds of the face being rendered - */ - @SideOnly(Side.CLIENT) - def renderMicroFace(pos: Vector3, pass: Int, bounds: Cuboid6) - - /** Get the render pass for which this material renders in. - */ - @SideOnly(Side.CLIENT) - def canRenderInPass(pass: Int) = pass == 0 - - /** Return true if this material is not opaque (glass, ice). - */ - def isTransparent: Boolean - - /** Return the light level emitted by this material (glowstone) - */ - def getLightValue: Int - - /** Return the strength of this material - */ - def getStrength(player: EntityPlayer): Float - - /** Return the localised name of this material (normally the block name) - */ - def getLocalizedName: String - - /** Get the item that this material is cut from (full block -> slabs) - */ - def getItem: ItemStack - - /** Get the strength of saw requried to cut this material - */ - def getCutterStrength: Int - - /** Get the breaking/walking sound - */ - def getSound: SoundType - - /** Return true if this material is solid and opaque (can run wires on etc) - */ - def isSolid = !isTransparent - - /** Get the explosion resistance of this part to an explosion caused by - * entity - */ - def explosionResistance(entity: Entity): Float - } - - /** Interface for overriding the default micro placement highlight handler to - * show the effect of placement on a certain block/part - */ - trait IMicroHighlightRenderer { - - /** Return true if a custom highlight was rendered and the default should be - * skipped - */ - def renderHighlight( - player: EntityPlayer, - hit: MovingObjectPosition, - mcrClass: CommonMicroClass, - size: Int, - material: Int - ): Boolean - } - - private val typeMap = HashMap[String, IMicroMaterial]() - private val nameMap = HashMap[String, Int]() - private var idMap: Array[(String, IMicroMaterial)] = _ - private val idWriter = new IDWriter - - private val highlightRenderers = ListBuffer[IMicroHighlightRenderer]() - private var maxCuttingStrength: Int = _ - - private val remap = HashMap[String, String]() - private var missingId: Int = 0 - - /** Register a micro material with unique identifier name - */ - def registerMaterial(material: IMicroMaterial, name: String) { - if (MultiPartRegistry.loaded) - throw new IllegalStateException( - "You must register your materials in the init methods." - ) - - if (typeMap.contains(name)) { - logger.error("Material with id " + name + " is already registered.") - return - } - - typeMap.put(name, material) - } - - /** Replace a micro material with unique identifier name - */ - def replaceMaterial(material: IMicroMaterial, name: String) { - if (MultiPartRegistry.loaded) - throw new IllegalStateException( - "You must register your materials in the init methods." - ) - - if (typeMap.remove(name).isEmpty) - logger.error("Material with id " + name + " was not registered.") - - logger.debug("Replaced micro material: " + name) - - typeMap.put(name, material) - } - - /** Registers a highlight renderer - */ - def registerHighlightRenderer(handler: IMicroHighlightRenderer) { - highlightRenderers += handler - } - - def remapName(oldName: String, newName: String): Unit = - remap.put(oldName, newName) - - private[microblock] def setupIDMap() { - idMap = typeMap.toList.sortBy(_._1).toArray - idWriter.setMax(idMap.length) - nameMap.clear() - for (i <- 0 until idMap.length) - nameMap.put(idMap(i)._1, i) - missingId = nameMap.getOrElse( - MissingMicroMaterial.key, - throw new IllegalStateException( - "MissingMicroMaterial is not registered; the placeholder must never " + - "fall back to id 0." - ) - ) - } - - def getMissingId = missingId - - private[microblock] def calcMaxCuttingStrength() { - val it = Item.itemRegistry.iterator.asInstanceOf[JIterator[Item]] - maxCuttingStrength = it.flatMap { - case saw: Saw => Some(saw.getMaxCuttingStrength) - case _ => None - }.max - } - - private[microblock] def loadIcons() { - if (idMap != null) - idMap.foreach(e => e._2.loadIcons()) - } - - def getMaxCuttingStrength = maxCuttingStrength - - def writeIDMap(packet: PacketCustom) { - packet.writeInt(idMap.size) - idMap.foreach(e => packet.writeString(e._1)) - } - - def readIDMap(packet: PacketCustom): Seq[String] = { - val k = packet.readInt() - idWriter.setMax(k) - idMap = new Array(k) - nameMap.clear() - val missing = ListBuffer[String]() - for (i <- 0 until k) { - val s = packet.readString() - val v = typeMap.get(s) - if (v.isEmpty) - missing += s - else { - idMap(i) = (s, v.get) - nameMap.put(s, i) - } - } - return missing - } - - def writeMaterialID(data: MCDataOutput, id: Int) { - idWriter.write(data, id) - } - - def readMaterialID(data: MCDataInput) = idWriter.read(data) - - def materialName(id: Int) = idMap(id)._1 - - def materialID(name: String) = - nameMap.get(remap.getOrElse(name, name)) match { - case Some(v) => v - case None => - logger.error("Missing mapping for part with ID: " + name) - missingId - } - - def getMaterial(name: String) = - typeMap.getOrElse(remap.getOrElse(name, name), null) - - def getMaterial(id: Int) = idMap(id)._2 - - def getIdMap = idMap - - def renderHighlight( - player: EntityPlayer, - hit: MovingObjectPosition, - mcrClass: CommonMicroClass, - size: Int, - material: Int - ): Boolean = { - val overridden = highlightRenderers.find( - _.renderHighlight(player, hit, mcrClass, size, material) - ) - if (overridden.isDefined) - return true - - MicroblockRender.renderHighlight(player, hit, mcrClass, size, material) - return true - } -} diff --git a/src/main/scala/codechicken/microblock/handler/packethandlers.scala b/src/main/scala/codechicken/microblock/handler/packethandlers.scala index 796105f..cda3a40 100644 --- a/src/main/scala/codechicken/microblock/handler/packethandlers.scala +++ b/src/main/scala/codechicken/microblock/handler/packethandlers.scala @@ -47,7 +47,7 @@ object MicroblockCPH extends MicroblockPH with IClientPacketHandler { new S40PacketDisconnect( new ChatComponentTranslation( "microblock.missing", - missing.mkString(", ") + String.join(", ", missing) ) ) ) diff --git a/src/test/java/codechicken/microblock/MicroMaterialRegistryCharacterizationTest.java b/src/test/java/codechicken/microblock/MicroMaterialRegistryCharacterizationTest.java index 6bae44f..19b1fde 100644 --- a/src/test/java/codechicken/microblock/MicroMaterialRegistryCharacterizationTest.java +++ b/src/test/java/codechicken/microblock/MicroMaterialRegistryCharacterizationTest.java @@ -123,12 +123,14 @@ class MicroMaterialRegistryCharacterizationTest { */ @Test void materialInterfaceSuppliesRenderPassAndSolidity() { - assertTrue(MissingMicroMaterial.canRenderInPass(0)); - assertFalse(MissingMicroMaterial.canRenderInPass(1)); - assertFalse(MissingMicroMaterial.canRenderInPass(-1)); + IMicroMaterial missing = MissingMicroMaterial$.MODULE$; - assertFalse(MissingMicroMaterial.isTransparent()); - assertTrue(MissingMicroMaterial.isSolid()); + assertTrue(missing.canRenderInPass(0)); + assertFalse(missing.canRenderInPass(1)); + assertFalse(missing.canRenderInPass(-1)); + + assertFalse(missing.isTransparent()); + assertTrue(missing.isSolid()); } private static MCDataInput input(byte[] bytes) {