Recent Events Discussion (RED) Thread

  • The FTB Forum is now read-only, and is here as an archive. To participate in our community discussions, please join our Discord! https://ftb.team/discord

1SDAN

New Member
Jul 29, 2019
1,189
-15
0
But we're being serious, other than the API, there's not many reasons to upgrade versions in the near future. We might as well make an Official MC modded version
 

Eliav24

New Member
Jul 29, 2019
213
0
0
The API was always meant for mapmakers and costume resource packs. On a broader level, they are the ones who completely depend on mojang, they are the ones who expand the content of current versions and they're the ones who give feedback during the snapshots (Because they aren't busy fixing their code for the previous snapshot).
 

1SDAN

New Member
Jul 29, 2019
1,189
-15
0
The API was always meant for mapmakers and costume resource packs. On a broader level, they are the ones who completely depend on mojang, they are the ones who expand the content of current versions and they're the ones who give feedback during the snapshots (Because they aren't busy fixing their code for the previous snapshot).

So, it's not for modders? Great...
 

Celestialphoenix

Too Much Free Time
Nov 9, 2012
3,741
3,204
333
Tartarus.. I mean at work. Same thing really.
[
If they take action, so be it. I will laugh as they get screamed at by thousands upon thousands of angry fans, and even worse, piss off the YouTubers and that whole community.

I do feel we need our own game though.

What action can they viability take?
-Without inadvertently ripping down the whole modded community?

If they were going to force update; then just reprogramme forge.api to re-work the minecraft.jar a little more so all the 1.7 mods run on 1.8/1.9 ect
Mods don't update all the time- for all number of reasons; forward porting being one of them.
Heck if MFR requires some insane amount of .JSONs -then what about RotaryCraft??
*Pours one on the kerb for @Reika
 
Last edited:
  • Like
Reactions: Zenthon_127

Reika

RotaryCraft Dev
FTB Mod Dev
Sep 3, 2013
5,079
5,331
550
Toronto, Canada
sites.google.com
[


What action can they viability take?
-Without inadvertently ripping down the whole modded community?
Mods don't update all the time- for all number of reasons; forward porting being one of them.
Heck if MFR requires some insane amount of .JSONs -then what about RotaryCraft??
*Pours one on the kerb for @Reika
I assume you are talking about rendering. Most of the RC machines are a kind of renderer called a TileEntitySpecialRenderer (TESR in general conversation), whereas I strongly suspect MFR's renderers are mostly ISimpleBlockRenderingHandler (ISBRH) objects. These are the ones at risk of removal in 1.8 and the JSON system mimics. The latter are more performant, as they only rerender when the chunk does, but TESRs are required for model animations and/or other dynamic models, as they are the only ones that render anew each render tick. Additionally, only TESRs allow for models imported from Techne or other programs; ISBRHs require hand-coded vertices, and quickly become unmanageable for more complex models.


Sample code for a TESR:
Code:
GL11.glPushMatrix();
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
GL11.glTranslated(par2, par4 + 2, par6 + 1);
GL11.glScalef(1.0F, -1.0F, -1.0F);
GL11.glTranslatef(0.5F, 0.5F, 0.5F);
int var11 = 0; //used to rotate the model about metadata
modelObj.renderAll(tile, null, 0, 0);
if (tile.isInWorld())
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
GL11.glPopMatrix();
Model file:
https://github.com/ReikaKalseki/RotaryCraft/blob/master/Models/ModelDetector.java


Sample code for an ISBRH:
Code:
private void renderBase(Tessellator v5, CrystalRenderedBlock b) {
IIcon ico = b.getBaseBlock(ForgeDirection.UP).getIcon(0, 0);
int w = ico.getIconWidth();
v5.setColorOpaque(255, 255, 255);
double u = ico.getMinU();
double v = ico.getMinV();
double xu = ico.getMaxU();
double xv = ico.getMaxV();
double top = 0.125;
v5.addVertexWithUV(0, top, 1, u, xv);
v5.addVertexWithUV(1, top, 1, xu, xv);
v5.addVertexWithUV(1, top, 0, xu, v);
v5.addVertexWithUV(0, top, 0, u, v);
v5.setColorOpaque(110, 110, 110);
v5.addVertexWithUV(0, 0, 0, u, v);
v5.addVertexWithUV(1, 0, 0, xu, v);
v5.addVertexWithUV(1, 0, 1, xu, xv);
v5.addVertexWithUV(0, 0, 1, u, xv);
ico = b.getBaseBlock(ForgeDirection.EAST).getIcon(0, 0);
u = ico.getMinU();
v = ico.getMinV();
xu = ico.getMaxU();
xv = ico.getMaxV();
double vv = v+(xv-v)/(w)*2;
v5.setColorOpaque(200, 200, 200);
v5.addVertexWithUV(0, top, 0, u, vv);
v5.addVertexWithUV(1, top, 0, xu, vv);
v5.addVertexWithUV(1, 0, 0, xu, v);
v5.addVertexWithUV(0, 0, 0, u, v);
v5.setColorOpaque(170, 170, 170);
v5.addVertexWithUV(0, 0, 1, u, v);
v5.addVertexWithUV(1, 0, 1, xu, v);
v5.addVertexWithUV(1, top, 1, xu, vv);
v5.addVertexWithUV(0, top, 1, u, vv);
v5.setColorOpaque(200, 200, 200);
v5.addVertexWithUV(0, 0, 0, u, v);
v5.addVertexWithUV(0, 0, 1, xu, v);
v5.addVertexWithUV(0, top, 1, xu, vv);
v5.addVertexWithUV(0, top, 0, u, vv);
v5.setColorOpaque(170, 170, 170);
v5.addVertexWithUV(1, top, 0, u, vv);
v5.addVertexWithUV(1, top, 1, xu, vv);
v5.addVertexWithUV(1, 0, 1, xu, v);
v5.addVertexWithUV(1, 0, 0, u, v);
}
private void renderOutline(Tessellator v5) {
double core = 0.15;
double vl = 0.8;
double dd = 0.01;
double tip = 1;
double zf = 0.4;
v5.addVertexWithUV(0.5+core-dd, 0, 0.5-core, 0, 0);
v5.addVertexWithUV(0.5+core+dd, 0, 0.5-core, 0, 0);
v5.addVertexWithUV(0.5+core+dd, vl, 0.5-core, 0, 0);
v5.addVertexWithUV(0.5+core-dd, vl, 0.5-core, 0, 0);
v5.addVertexWithUV(0.5+core, 0, 0.5-core-dd, 0, 0);
v5.addVertexWithUV(0.5+core, 0, 0.5-core+dd, 0, 0);
v5.addVertexWithUV(0.5+core, vl, 0.5-core+dd, 0, 0);
v5.addVertexWithUV(0.5+core, vl, 0.5-core-dd, 0, 0);
v5.addVertexWithUV(0.5-core-dd, 0, 0.5-core, 0, 0);
v5.addVertexWithUV(0.5-core+dd, 0, 0.5-core, 0, 0);
v5.addVertexWithUV(0.5-core+dd, vl, 0.5-core, 0, 0);
v5.addVertexWithUV(0.5-core-dd, vl, 0.5-core, 0, 0);
v5.addVertexWithUV(0.5-core, 0, 0.5-core-dd, 0, 0);
v5.addVertexWithUV(0.5-core, 0, 0.5-core+dd, 0, 0);
v5.addVertexWithUV(0.5-core, vl, 0.5-core+dd, 0, 0);
v5.addVertexWithUV(0.5-core, vl, 0.5-core-dd, 0, 0);
v5.addVertexWithUV(0.5+core-dd, 0, 0.5+core, 0, 0);
v5.addVertexWithUV(0.5+core+dd, 0, 0.5+core, 0, 0);
v5.addVertexWithUV(0.5+core+dd, vl, 0.5+core, 0, 0);
v5.addVertexWithUV(0.5+core-dd, vl, 0.5+core, 0, 0);
v5.addVertexWithUV(0.5+core, 0, 0.5-core-dd, 0, 0);
v5.addVertexWithUV(0.5+core, 0, 0.5-core+dd, 0, 0);
v5.addVertexWithUV(0.5+core, vl, 0.5-core+dd, 0, 0);
v5.addVertexWithUV(0.5+core, vl, 0.5-core-dd, 0, 0);
v5.addVertexWithUV(0.5-core-dd, 0, 0.5+core, 0, 0);
v5.addVertexWithUV(0.5-core+dd, 0, 0.5+core, 0, 0);
v5.addVertexWithUV(0.5-core+dd, vl, 0.5+core, 0, 0);
v5.addVertexWithUV(0.5-core-dd, vl, 0.5+core, 0, 0);
v5.addVertexWithUV(0.5+core, 0, 0.5-core-dd, 0, 0);
v5.addVertexWithUV(0.5+core, 0, 0.5-core+dd, 0, 0);
v5.addVertexWithUV(0.5+core, vl, 0.5-core+dd, 0, 0);
v5.addVertexWithUV(0.5+core, vl, 0.5-core-dd, 0, 0);
v5.addVertexWithUV(0.5+core, vl, 0.5+core, 0, 0);
v5.addVertexWithUV(0.5+core, vl+dd, 0.5+core, 0, 0);
v5.addVertexWithUV(0.5, tip+dd, 0.5, 0, 0);
v5.addVertexWithUV(0.5, tip, 0.5, 0, 0);
v5.addVertexWithUV(0.5+core-dd*zf, vl, 0.5+core+dd*zf, 0, 0);
v5.addVertexWithUV(0.5+core+dd*zf, vl, 0.5+core-dd*zf, 0, 0);
v5.addVertexWithUV(0.5+dd*zf, tip, 0.5-dd*zf, 0, 0);
v5.addVertexWithUV(0.5-dd*zf, tip, 0.5+dd*zf, 0, 0);
v5.addVertexWithUV(0.5-core, vl, 0.5-core, 0, 0);
v5.addVertexWithUV(0.5-core, vl+dd, 0.5-core, 0, 0);
v5.addVertexWithUV(0.5, tip+dd, 0.5, 0, 0);
v5.addVertexWithUV(0.5, tip, 0.5, 0, 0);
v5.addVertexWithUV(0.5-core-dd*zf, vl, 0.5-core+dd*zf, 0, 0);
v5.addVertexWithUV(0.5-core+dd*zf, vl, 0.5-core-dd*zf, 0, 0);
v5.addVertexWithUV(0.5+dd*zf, tip, 0.5-dd*zf, 0, 0);
v5.addVertexWithUV(0.5-dd*zf, tip, 0.5+dd*zf, 0, 0);
v5.addVertexWithUV(0.5-core, vl, 0.5+core, 0, 0);
v5.addVertexWithUV(0.5-core, vl+dd, 0.5+core, 0, 0);
v5.addVertexWithUV(0.5, tip+dd, 0.5, 0, 0);
v5.addVertexWithUV(0.5, tip, 0.5, 0, 0);
v5.addVertexWithUV(0.5+core+dd, vl+dd, 0.5-core, 0, 0);
v5.addVertexWithUV(0.5+core-dd, vl+dd, 0.5-core, 0, 0);
v5.addVertexWithUV(0.5-dd, tip+dd, 0.5, 0, 0);
v5.addVertexWithUV(0.5+dd, tip+dd, 0.5, 0, 0);
v5.addVertexWithUV(0.5-core, vl, 0.5+core, 0, 0);
v5.addVertexWithUV(0.5-core, vl+dd, 0.5+core, 0, 0);
v5.addVertexWithUV(0.5, tip+dd, 0.5, 0, 0);
v5.addVertexWithUV(0.5, tip, 0.5, 0, 0);
v5.addVertexWithUV(0.5-core+dd, vl+dd, 0.5+core, 0, 0);
v5.addVertexWithUV(0.5-core-dd, vl+dd, 0.5+core, 0, 0);
v5.addVertexWithUV(0.5-dd, tip+dd, 0.5, 0, 0);
v5.addVertexWithUV(0.5+dd, tip+dd, 0.5, 0, 0);
}
private void renderSpike(Tessellator v5, double u, double v, double xu, double xv, int w) {
double core = 0.15;
double vl = 0.8;
// Top point
v5.addVertexWithUV(0.5-core, vl, 0.5-core, u, v);
v5.addVertexWithUV(0.5-core, vl, 0.5+core, xu, v);
v5.addVertexWithUV(0.5, 1, 0.5, xu, xv);
v5.addVertexWithUV(0.5, 1, 0.5, xu, xv);
v5.addVertexWithUV(0.5-core, vl, 0.5+core, u, v);
v5.addVertexWithUV(0.5+core, vl, 0.5+core, xu, v);
v5.addVertexWithUV(0.5, 1, 0.5, xu, xv);
v5.addVertexWithUV(0.5, 1, 0.5, xu, xv);
v5.addVertexWithUV(0.5, 1, 0.5, u, xv);
v5.addVertexWithUV(0.5, 1, 0.5, xu, xv);
v5.addVertexWithUV(0.5+core, vl, 0.5+core, xu, v);
v5.addVertexWithUV(0.5+core, vl, 0.5-core, u, v);
v5.addVertexWithUV(0.5, 1, 0.5, u, xv);
v5.addVertexWithUV(0.5, 1, 0.5, xu, xv);
v5.addVertexWithUV(0.5+core, vl, 0.5-core, xu, v);
v5.addVertexWithUV(0.5-core, vl, 0.5-core, u, v);
xv -= (xv-v)/w;
v += (xv-v)/(w*1.2);
u += (xu-u)/(w*2);
xu -= (xu-u)/(w*2);
//columns
v5.addVertexWithUV(0.5-core, vl, 0.5-core, u, xv);
v5.addVertexWithUV(0.5+core, vl, 0.5-core, xu, xv);
v5.addVertexWithUV(0.5+core, 0, 0.5-core, xu, v);
v5.addVertexWithUV(0.5-core, 0, 0.5-core, u, v);
v5.addVertexWithUV(0.5-core, 0, 0.5+core, u, v);
v5.addVertexWithUV(0.5+core, 0, 0.5+core, xu, v);
v5.addVertexWithUV(0.5+core, vl, 0.5+core, xu, xv);
v5.addVertexWithUV(0.5-core, vl, 0.5+core, u, xv);
v5.addVertexWithUV(0.5+core, vl, 0.5-core, u, xv);
v5.addVertexWithUV(0.5+core, vl, 0.5+core, xu, xv);
v5.addVertexWithUV(0.5+core, 0, 0.5+core, xu, v);
v5.addVertexWithUV(0.5+core, 0, 0.5-core, u, v);
v5.addVertexWithUV(0.5-core, 0, 0.5-core, u, v);
v5.addVertexWithUV(0.5-core, 0, 0.5+core, xu, v);
v5.addVertexWithUV(0.5-core, vl, 0.5+core, xu, xv);
v5.addVertexWithUV(0.5-core, vl, 0.5-core, u, xv);
//bottom
v5.addVertexWithUV(0.5+core, 0, 0.5-core, u, xv);
v5.addVertexWithUV(0.5+core, 0, 0.5+core, xu, xv);
v5.addVertexWithUV(0.5-core, 0, 0.5+core, xu, v);
v5.addVertexWithUV(0.5-core, 0, 0.5-core, u, v);
}
private void renderXAngledSpike(double u, double v, double xu, double xv, double out, int w) {
double core = 0.12;
double vl = 0.55;
double dvl = vl/6D;
double dy = -0.05;
double tout = out;
double htip = 0.1;
int dir = out > 0 ? 1 : -1;
TessellatorVertexList v5 = new TessellatorVertexList();
v5.addVertexWithUV(0.5+core*dir+out, dy+vl+dvl, 0.5+core, u, v);
v5.addVertexWithUV(0.5+core*dir+out, dy+vl+dvl, 0.5-core, xu, v);
v5.addVertexWithUV(0.5+core*dir+out+tout, dy+vl+dvl+htip, 0.5, xu, xv); //tip
v5.addVertexWithUV(0.5+core*dir+out+tout, dy+vl+dvl+htip, 0.5, xu, xv);
v5.addVertexWithUV(0.5+core*dir+out+tout, dy+vl+dvl+htip, 0.5, u, xv);
v5.addVertexWithUV(0.5+core*dir+out+tout, dy+vl+dvl+htip, 0.5, xu, xv); //tip
v5.addVertexWithUV(0.5+core*dir*3+out, dy+vl, 0.5-core, xu, v);
v5.addVertexWithUV(0.5+core*dir*3+out, dy+vl, 0.5+core, u, v);
v5.addVertexWithUV(0.5+core*dir+out+tout, dy+vl+dvl+htip, 0.5, u, xv);
v5.addVertexWithUV(0.5+core*dir+out+tout, dy+vl+dvl+htip, 0.5, xu, xv); //tip
v5.addVertexWithUV(0.5+core*dir*3+out, dy+vl, 0.5+core, xu, v);
v5.addVertexWithUV(0.5+core*dir+out, dy+vl+dvl, 0.5+core, u, v);
v5.addVertexWithUV(0.5+core*dir+out, dy+vl+dvl, 0.5-core, u, v);
v5.addVertexWithUV(0.5+core*dir*3+out, dy+vl, 0.5-core, xu, v);
v5.addVertexWithUV(0.5+core*dir+out+tout, dy+vl+dvl+htip, 0.5, xu, xv); //tip
v5.addVertexWithUV(0.5+core*dir+out+tout, dy+vl+dvl+htip, 0.5, xu, xv);
xv -= (xv-v)/w;
v += (xv-v)/(w*1.2);
u += (xu-u)/(w*2);
xu -= (xu-u)/(w*2);
//panels
v5.addVertexWithUV(0.5+core*dir, dy+dvl, 0.5-core, u, v);
v5.addVertexWithUV(0.5+core*dir*3, dy+0, 0.5-core, xu, v);
v5.addVertexWithUV(0.5+core*dir*3+out, dy+vl, 0.5-core, xu, xv);
v5.addVertexWithUV(0.5+core*dir+out, dy+vl+dvl, 0.5-core, u, xv);
v5.addVertexWithUV(0.5+core*dir+out, dy+vl+dvl, 0.5+core, u, xv);
v5.addVertexWithUV(0.5+core*dir*3+out, dy+vl, 0.5+core, xu, xv);
v5.addVertexWithUV(0.5+core*dir*3, dy+0, 0.5+core, xu, v);
v5.addVertexWithUV(0.5+core*dir, dy+dvl, 0.5+core, u, v);
v5.addVertexWithUV(0.5+core*dir+out, dy+vl+dvl, 0.5-core, u, xv);
v5.addVertexWithUV(0.5+core*dir+out, dy+vl+dvl, 0.5+core, xu, xv);
v5.addVertexWithUV(0.5+core*dir, dy+dvl, 0.5+core, xu, v);
v5.addVertexWithUV(0.5+core*dir, dy+dvl, 0.5-core, u, v);
v5.addVertexWithUV(0.5+core*dir*3, dy, 0.5-core, u, v);
v5.addVertexWithUV(0.5+core*dir*3, dy, 0.5+core, xu, v);
v5.addVertexWithUV(0.5+core*dir*3+out, dy+vl, 0.5+core, xu, xv);
v5.addVertexWithUV(0.5+core*dir*3+out, dy+vl, 0.5-core, u, xv);
//base
v5.addVertexWithUV(0.5-core*dir*3+out*2.56, dy+dvl, 0.5-core, u, xv);
v5.addVertexWithUV(0.5-core*dir*3+out*2.56, dy+dvl, 0.5+core, xu, xv);
v5.addVertexWithUV(0.5+core*dir*3, dy, 0.5+core, xu, v);
v5.addVertexWithUV(0.5+core*dir*3, dy, 0.5-core, u, v);
if (out > 0)
v5.reverse();
v5.render();
}
private void renderZAngledSpike(double u, double v, double xu, double xv, double out, int w) {
double core = 0.12;
double vl = 0.55;
double dvl = vl/6D;
double dy = -0.1;
double tout = out;//0.1875;
double htip = 0.1;
int dir = out > 0 ? 1 : -1;
TessellatorVertexList v5 = new TessellatorVertexList();
v5.addVertexWithUV(0.5+core, dy+vl+dvl, 0.5+core*dir+out, u, v);
v5.addVertexWithUV(0.5-core, dy+vl+dvl, 0.5+core*dir+out, xu, v);
v5.addVertexWithUV(0.5, dy+vl+dvl+htip, 0.5+core*dir+out+tout, xu, xv); //tip
v5.addVertexWithUV(0.5, dy+vl+dvl+htip, 0.5+core*dir+out+tout, u, xv);
v5.addVertexWithUV(0.5, dy+vl+dvl+htip, 0.5+core*dir+out+tout, xu, xv);
v5.addVertexWithUV(0.5, dy+vl+dvl+htip, 0.5+core*dir+out+tout, xu, xv); //tip
v5.addVertexWithUV(0.5-core, dy+vl, 0.5+core*dir*3+out, xu, v);
v5.addVertexWithUV(0.5+core, dy+vl, 0.5+core*dir*3+out, u, v);
v5.addVertexWithUV(0.5, dy+vl+dvl+htip, 0.5+core*dir+out+tout, xu, xv);
v5.addVertexWithUV(0.5, dy+vl+dvl+htip, 0.5+core*dir+out+tout, xu, xv); //tip
v5.addVertexWithUV(0.5+core, dy+vl, 0.5+core*dir*3+out, xu, v);
v5.addVertexWithUV(0.5+core, dy+vl+dvl, 0.5+core*dir+out, u, v);
v5.addVertexWithUV(0.5-core, dy+vl+dvl, 0.5+core*dir+out, u, v);
v5.addVertexWithUV(0.5-core, dy+vl, 0.5+core*dir*3+out, xu, v);
v5.addVertexWithUV(0.5, dy+vl+dvl+htip, 0.5+core*dir+out+tout, xu, xv); //tip
v5.addVertexWithUV(0.5, dy+vl+dvl+htip, 0.5+core*dir+out+tout, u, xv);
xv -= (xv-v)/w;
v += (xv-v)/(w*1.2);
u += (xu-u)/(w*2);
xu -= (xu-u)/(w*2);
//panels
v5.addVertexWithUV(0.5-core, dy+dvl, 0.5+core*dir, u, v);
v5.addVertexWithUV(0.5-core, dy+0, 0.5+core*dir*3, xu, v);
v5.addVertexWithUV(0.5-core, dy+vl, 0.5+core*dir*3+out, xu, xv);
v5.addVertexWithUV(0.5-core, dy+vl+dvl, 0.5+core*dir+out, u, xv);
v5.addVertexWithUV(0.5+core, dy+vl+dvl, 0.5+core*dir+out, u, xv);
v5.addVertexWithUV(0.5+core, dy+vl, 0.5+core*dir*3+out, xu, xv);
v5.addVertexWithUV(0.5+core, dy+0, 0.5+core*dir*3, xu, v);
v5.addVertexWithUV(0.5+core, dy+dvl, 0.5+core*dir, u, v);
v5.addVertexWithUV(0.5-core, dy+vl+dvl, 0.5+core*dir+out, u, xv);
v5.addVertexWithUV(0.5+core, dy+vl+dvl, 0.5+core*dir+out, xu, xv);
v5.addVertexWithUV(0.5+core, dy+dvl, 0.5+core*dir, xu, v);
v5.addVertexWithUV(0.5-core, dy+dvl, 0.5+core*dir, u, v);
v5.addVertexWithUV(0.5-core, dy, 0.5+core*dir*3, u, v);
v5.addVertexWithUV(0.5+core, dy, 0.5+core*dir*3, xu, v);
v5.addVertexWithUV(0.5+core, dy+vl, 0.5+core*dir*3+out, xu, xv);
v5.addVertexWithUV(0.5-core, dy+vl, 0.5+core*dir*3+out, u, xv);
//base
v5.addVertexWithUV(0.5-core, dy+dvl+0.0025, 0.5-core*dir*3+out*2.56, u, xv);
v5.addVertexWithUV(0.5+core, dy+dvl+0.0025, 0.5-core*dir*3+out*2.56, xu, xv);
v5.addVertexWithUV(0.5+core, dy, 0.5+core*dir*3, xu, v);
v5.addVertexWithUV(0.5-core, dy, 0.5+core*dir*3, u, v);
if (out < 0)
v5.reverse();
v5.render();
}

So, RotaryCraft is unlikely to be as badly affected as MFR in this regard.

However, I do still use ISBRHs (ChromatiCraft crystals, plants, and runes, GeoStrata vents, ReC fluorite lamps, RC pipes, deco tanks, blast glass, and others). If the ISBRH system is removed in 1.8, I will recreate it myself, as I need actual code for drawing those models, not just prefab vertex locations (dynamic loading of vertices, colors, lighting, and so on).


I see a bigger problem for 1.8, though:
sp614x;/members/sp614x;/forums/mapping-and-modding/minecraft-mods/1272953-optifine-hd-a4-fps-boost-hd-textures-aa-af-and?comment=43757 said:
Minecraft 1.8 has so many performance problems that I just don't know where to start with.

Maybe the biggest and the ugliest problem is the memory allocation. Currently the game allocates (and throws away immediately) 50 MB/sec when standing still and up to 200 MB/sec when moving. That is just crazy.

What happens when the game allocates 200 MB memory every second and discards them immediately?

1. With a default memory limit of 1GB (1000 MB) and working memory of about 200 MB Java has to make a full garbage collection every 4 seconds otherwise it would run out of memory. When running with 60 fps, one frame takes about 16 ms. In order not to be noticeable, the garbage collection should run in 10-15 ms maximum. In this minimal time it has to decide which of the several hundred thausand newly generated objects are garbage and can be discarded and which are not. This is a huge amount of work and it needs a very powerful CPU in order to finish in 10 ms.

2. Why not give it more memory?
Let's give Minecraft 4 GB of RAM to play with. This would need a PC with at least 8 GB RAM (as the real memory usage is almost double the memory visible in Java). If the VM decides to use all the memory, then it will increase the time between the garbage collections (20 sec instead of 4), but it will also increase the garbage collection time by 4, so every 20 seconds there will be one massive lag spike.

3. Why not use incremental garbage collection?
The latest version of the launcher by default enables incremental garbage collection (-XX:+CMSIncrementalMode) which in theory should replace the one big GC with many shorter incremental GCs. However the problem is that the time at which the smaller GCs happen and their duration are mostly random. Also they are not much shorter (maybe 50%) than a full scale GC. That means that the FPS starts to fluctuate up and down and there are a lot of random lag spikes. The stable FPS with a lag spike from time to time is replaced with unstable FPS and microstutter (or not very micro depending on the CPU). This strategy can only work with a powerful enough CPU so that the random lag spikes become small enough not to be noticeable.

4. How did that work in previous releases?
The previous Minecraft releases were much less memory hungry. The original Notch code (pre 1.3) was allocating about 10-20 MB/sec which was much more easy to control and optimize. The rendering itself needed only 1-2 MB/sec and was designed to minimize memory waste (reusing buffers, etc). The 200 MB/sec is pushing the limits and forcing the garbage collector to do a lot of work which takes time. If it was possible to control how and when the GC works then maybe it would be possible to distribute the GC pauses such that they are not noticeable or less disturbing. However there is no such control in the current Java VM.

5. Why is 1.8 allocating so much memory?
This is the best part - over 90% of the memory allocation is not needed at all. Most of the memory is probably allocated to make the life of the developers easier.
- There are huge amounts of objects which are allocated and discarded milliseconds later.
- All internal methods which used parameters (x, y, z) are now converted to one parameter (BlockPos) which is immutable. So if you need to check another position around the current one you have to allocate a new BlockPos or invent some object cache which will probaby be slower. This alone is a huge memory waste.
- The chunk loading is allocating a lot of memory just to pass vertex data around. The excuse is probably "mutithreading", however this is not necessary at all (see the last OptiFine for 1.7).
- the list goes on and on ...

The general trend is that the developers do not care that much about memory allocation and use "best industry practices" without understanding the consequences. The standard reasoning being "immutables are good", "allocating new memory is faster than caching", "the garbage collector is so good these days" and so on.

Allocating new memory is really faster than caching (Java is even faster than C++ when it comes to dynamic memory), but getting rid of the allocated memory is not faster and it is not predictable at all. Minecraft is a "real-time" application and to get a stable framerate it needs either minimal runtime memory allocation (pre 1.3) or controllable garbage collecting, which is just not possible with the current Java VM.

6. What can be done to fix it?
If there are 2 or 3 places which are wasting memory (bugs), then OptiFine can fix them individually. Otherwise a bigger refactoring of the Minecraft internals will be needed, which is a huge task and not possible for OptiFine.

7. Example
A sample log of GC activity with effective FPS for the GC lag spikes is available here.
- the average rendering FPS is about 50 FPS
- the GC lag spikes have effective FPS of 7-20
- there are 1-2 lag spikes per second caused by GC activity

tldr; When 1.8 is lagging and stuttering the garbage collector is working like crazy and is doing work which has nothing to do with the game itself (rendering, running the internal server, loading chunks, etc). Instead it is constantly cleaning the mess behind the code which thinks that memory allocation is "cheap".
 
Last edited:

jaquadro

New Member
Jul 29, 2019
182
-13
0
ISBRHs are only as bad as your underlying infrastructure makes them. E.g. most of my mods depend heavily on multipart rendering of box cross-sections (where said box has some depth in its walls). Pay an up-front cost once, and then rendering more complex objects is trivial.

Code:
       for (int i = 0; i < 6; i++)
            boxRenderer.setIcon(renderer.getBlockIconFromSideAndMetadata(block, i, data), i);

        boxRenderer.renderBox(renderer, block, x, y, z, 0, 14 * unit, 0, 1, 1, 1, 0, ModularBoxRenderer.CUT_YNEG | ModularBoxRenderer.CUT_YPOS);
        boxRenderer.renderBox(renderer, block, x, y, z, 1 * unit, 8 * unit, 1 * unit, 15 * unit, 16 * unit, 15 * unit, 0, ModularBoxRenderer.CUT_YPOS);

        boxRenderer.renderSolidBox(renderer, block, x, y, z, 3 * unit, 6 * unit, 3 * unit, 13 * unit, 8 * unit, 13 * unit);
        boxRenderer.renderSolidBox(renderer, block, x, y, z, 5 * unit, 3 * unit, 5 * unit, 11 * unit, 6 * unit, 11 * unit);
        boxRenderer.renderSolidBox(renderer, block, x, y, z, 2 * unit, 0 * unit, 2 * unit, 14 * unit, 3 * unit, 14 * unit);
[DOUBLEPOST=1413918241][/DOUBLEPOST]It's also worth adding that Mojang's RenderBlocks code is broken in so many ways that you may as well write it yourself anyway.
 
Last edited:

Reika

RotaryCraft Dev
FTB Mod Dev
Sep 3, 2013
5,079
5,331
550
Toronto, Canada
sites.google.com
ISBRHs are only as bad as your underlying infrastructure makes them. E.g. most of my mods depend heavily on multipart rendering of box cross-sections (where said box has some depth in its walls). Pay an up-front cost once, and then rendering more complex objects is trivial.

Code:
       for (int i = 0; i < 6; i++)
            boxRenderer.setIcon(renderer.getBlockIconFromSideAndMetadata(block, i, data), i);

        boxRenderer.renderBox(renderer, block, x, y, z, 0, 14 * unit, 0, 1, 1, 1, 0, ModularBoxRenderer.CUT_YNEG | ModularBoxRenderer.CUT_YPOS);
        boxRenderer.renderBox(renderer, block, x, y, z, 1 * unit, 8 * unit, 1 * unit, 15 * unit, 16 * unit, 15 * unit, 0, ModularBoxRenderer.CUT_YPOS);

        boxRenderer.renderSolidBox(renderer, block, x, y, z, 3 * unit, 6 * unit, 3 * unit, 13 * unit, 8 * unit, 13 * unit);
        boxRenderer.renderSolidBox(renderer, block, x, y, z, 5 * unit, 3 * unit, 5 * unit, 11 * unit, 6 * unit, 11 * unit);
        boxRenderer.renderSolidBox(renderer, block, x, y, z, 2 * unit, 0 * unit, 2 * unit, 14 * unit, 3 * unit, 14 * unit);
[DOUBLEPOST=1413918241][/DOUBLEPOST]It's also worth adding that Mojang's RenderBlocks code is broken in so many ways that you may as well write it yourself anyway.
:eek:
 

1SDAN

New Member
Jul 29, 2019
1,189
-15
0
You know, if we ever do get on bad terms with Mojang, we have the entire mainstream modding community on our side. (Except for Greg, FlowerChild and Bioxx but I believe that Greg would most probably be joining us for that one event, FC would try his hardest to do stuff if he's still around by then and Bioxx would probably be the first to jump on coding a new game) With the combo of FTB, Technic and the MCF modding section spewing support for us, we'll have a nice range of influence day one. Add to that the awareness vids, recaps, mod-heavy Tubers and the oddball insane comment troll, we'll quickly grow on Youtube. Then we've got all the Reddits and Twitter devs and lurkers and really, I think we have quite a nice deck of cards built.

Discuss.
 

Reika

RotaryCraft Dev
FTB Mod Dev
Sep 3, 2013
5,079
5,331
550
Toronto, Canada
sites.google.com
You know, if we ever do get on bad terms with Mojang, we have the entire mainstream modding community on our side. (Except for Greg, FlowerChild and Bioxx but I believe that Greg would most probably be joining us for that one event, FC would try his hardest to do stuff if he's still around by then and Bioxx would probably be the first to jump on coding a new game) With the combo of FTB, Technic and the MCF modding section spewing support for us, we'll have a nice range of influence day one. Add to that the awareness vids, recaps, mod-heavy Tubers and the oddball insane comment troll, we'll quickly grow on Youtube. Then we've got all the Reddits and Twitter devs and lurkers and really, I think we have quite a nice deck of cards built.

Discuss.
?