That is, most of the business code should not be aware that it is being compiled to multiple versions even when it heavily interacts with MC, preprocessor statements should be an escape hatch, not the norm. Similarly, code should not be forced to do `MCVer.getWindow(mc)` instead of the much more intuitive `mc.getWindow()`, and a new preprocessor (technically remap) feature makes this possible by defining "search and replace"-like patterns (but smarter in that they are type-aware) in one or more central places (the "Patterns.java" files) which then are applied all over the code base. In a way, this is another step in the automatic back-porting process where preprocessor statements are used when we cannot yet do something automatically. Previously we "merely" automatically converted between different mapping, this new feature now also allows us to automatically perform simple refactoring tasks like changing field access to a getter+setter (e.g. `mc.getWindow()`), or changing how a method is called (e.g. `BufferBuilder.begin`), or changing a method call chain (e.g. `dispatcher.camera.getYaw()`), or most other search-and-replace-like changes and any combination of those. The only major limitation is that the replacement itself is not smart, so arguments must be kept in same order (or be temporarily assigned to local variables which then can be used in any order).
182 lines
5.9 KiB
Java
182 lines
5.9 KiB
Java
package com.replaymod.render.blend;
|
|
|
|
import com.replaymod.render.blend.data.DScene;
|
|
import com.replaymod.render.blend.data.Serializer;
|
|
//#if MC>=10800
|
|
// FIXME 1.15
|
|
//#if MC<11500
|
|
//$$ import com.replaymod.render.blend.exporters.ChunkExporter;
|
|
//#endif
|
|
import com.replaymod.render.blend.exporters.EntityExporter;
|
|
import com.replaymod.render.blend.exporters.ItemExporter;
|
|
import com.replaymod.render.blend.exporters.ParticlesExporter;
|
|
import com.replaymod.render.blend.exporters.RenderState;
|
|
import com.replaymod.render.blend.exporters.TileEntityExporter;
|
|
//#endif
|
|
import net.minecraft.util.crash.CrashReport;
|
|
import net.minecraft.util.crash.CrashReportSection;
|
|
import net.minecraft.util.crash.CrashException;
|
|
import org.apache.commons.io.output.NullOutputStream;
|
|
import org.blender.utils.BlenderFactory;
|
|
import org.cakelab.blender.io.BlenderFile;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.io.PrintStream;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.NoSuchElementException;
|
|
|
|
import static com.replaymod.core.versions.MCVer.*;
|
|
import static com.replaymod.render.ReplayModRender.LOGGER;
|
|
|
|
// Note:
|
|
// - Chunk exporter currently assumes VBO are enabled and in use
|
|
public class BlendState implements Exporter {
|
|
private static BlendState currentState;
|
|
|
|
public static void setState(BlendState state) {
|
|
currentState = state;
|
|
}
|
|
|
|
public static BlendState getState() {
|
|
return currentState;
|
|
}
|
|
|
|
private final List<Exporter> exporters = new ArrayList<>();
|
|
private final BlenderFile blenderFile;
|
|
private final BlenderFactory factory;
|
|
private final DScene scene = new DScene();
|
|
private final BlendMaterials materials = new BlendMaterials();
|
|
|
|
public BlendState(File file) throws IOException {
|
|
this.blenderFile = BlenderFactory.newBlenderFile(file);
|
|
this.factory = new BlenderFactory(blenderFile);
|
|
|
|
//#if MC>=10800
|
|
RenderState renderState = new RenderState(this);
|
|
register(renderState);
|
|
// FIXME 1.15
|
|
//#if MC<11500
|
|
//$$ register(new ChunkExporter());
|
|
//#endif
|
|
register(new EntityExporter(renderState));
|
|
register(new TileEntityExporter(renderState));
|
|
register(new ParticlesExporter(renderState));
|
|
register(new ItemExporter(renderState));
|
|
//#endif
|
|
}
|
|
|
|
public void register(Exporter exporter) {
|
|
exporters.add(exporter);
|
|
}
|
|
|
|
public <T extends Exporter> T get(Class<T> clazz) {
|
|
for (Exporter exporter : exporters) {
|
|
if (clazz.isInstance(exporter)) {
|
|
return clazz.cast(exporter);
|
|
}
|
|
}
|
|
throw new NoSuchElementException("No exporter of type " + clazz);
|
|
}
|
|
|
|
@Override
|
|
public void setup() {
|
|
for (Exporter exporter : exporters) {
|
|
try {
|
|
exporter.setup();
|
|
} catch (IOException e) {
|
|
CrashReport report = CrashReport.create(e, "Setup of blend exporter");
|
|
CrashReportSection category = report.addElement("Exporter");
|
|
category.add("Exporter", exporter::toString);
|
|
throw new CrashException(report);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void tearDown() {
|
|
for (Exporter exporter : exporters) {
|
|
try {
|
|
exporter.tearDown();
|
|
} catch (IOException e) {
|
|
CrashReport report = CrashReport.create(e, "Tear down of blend exporter");
|
|
CrashReportSection category = report.addElement("Exporter");
|
|
category.add("Exporter", exporter::toString);
|
|
throw new CrashException(report);
|
|
}
|
|
}
|
|
|
|
try {
|
|
Serializer serializer = new Serializer();
|
|
this.scene.serialize(serializer);
|
|
// TODO pre-configure render settings serializer.writeMajor(new Object(), new DId(BlockCodes.ID_REND))
|
|
|
|
//noinspection UseOfSystemOutOrSystemErr
|
|
PrintStream sysout = System.out;
|
|
try {
|
|
System.setOut(new PrintStream(new NullOutputStream()));
|
|
blenderFile.write();
|
|
} finally {
|
|
System.setOut(sysout);
|
|
}
|
|
} catch (IOException e) {
|
|
LOGGER.error("Exception writing blend file: ", e);
|
|
} finally {
|
|
try {
|
|
blenderFile.close();
|
|
} catch (IOException e) {
|
|
LOGGER.error("Exception closing blend file: ", e);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void preFrame(int frame) {
|
|
for (Exporter exporter : exporters) {
|
|
try {
|
|
exporter.preFrame(frame);
|
|
} catch (IOException e) {
|
|
CrashReport report = CrashReport.create(e, "Pre frame of blend exporter");
|
|
CrashReportSection category = report.addElement("Exporter");
|
|
category.add("Exporter", exporter::toString);
|
|
category.add("Frame", () -> String.valueOf(frame));
|
|
throw new CrashException(report);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void postFrame(int frame) {
|
|
for (Exporter exporter : exporters) {
|
|
try {
|
|
exporter.postFrame(frame);
|
|
} catch (IOException e) {
|
|
CrashReport report = CrashReport.create(e, "Post frame of blend exporter");
|
|
CrashReportSection category = report.addElement("Exporter");
|
|
category.add("Exporter", exporter::toString);
|
|
category.add("Frame", () -> String.valueOf(frame));
|
|
throw new CrashException(report);
|
|
}
|
|
}
|
|
|
|
scene.endFrame = frame;
|
|
}
|
|
|
|
public BlenderFile getBlenderFile() {
|
|
return blenderFile;
|
|
}
|
|
|
|
public BlenderFactory getFactory() {
|
|
return factory;
|
|
}
|
|
|
|
public DScene getScene() {
|
|
return scene;
|
|
}
|
|
|
|
public BlendMaterials getMaterials() {
|
|
return materials;
|
|
}
|
|
}
|