/*
* Copyright (C) 2015 iZc
*
* 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 .
*/
package de.nplusc.izc.logblockheatmapper;
import ar.com.hjg.pngj.ImageInfo;
import ar.com.hjg.pngj.ImageLineHelper;
import ar.com.hjg.pngj.ImageLineInt;
import ar.com.hjg.pngj.PngWriter;
import ar.com.hjg.pngj.chunks.PngChunkTextVar;
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.*;
import javax.imageio.ImageIO;
/**
*
* @author iZc
*/
enum BlockState
{
NONE,
BUFFER,
ACTIVITY,
BUFFER_PURGED,
ACTIVITY_PURGED,
WORKBENCH_FORCED,
WORKBENCH_FORCED_BUFFER,
}
enum RegionState
{
REMOVE,
CORE,
KEEP,
WATERIZE,
DROPPED
}
class CoordHolder
{
public final int x;
public final int y;
public final int z;
public final String blocktype;
CoordHolder(int x, int y, int z, String blocktype) {
this.x = x;
this.y = y;
this.z = z;
this.blocktype = blocktype;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CoordHolder that = (CoordHolder) o;
return x == that.x &&
y == that.y &&
z == that.z &&
Objects.equals(blocktype, that.blocktype);
}
@Override
public int hashCode() {
return Objects.hash(x, y, z, blocktype);
}
}
public class LogBlockHeatmapperRegionTrimmer
{
static final int treshold = 100;
static final int buffer = 30;
static final int workbenchbuffer = 50;
static final List blocktypes = Arrays.asList(
"minecraft:crafting_table",
"minecraft:furnace",
"minecraft:barrel",
"minecraft:ender_chest",
"minecraft:shulker_box",
"minecraft:black_shulker_box",
"minecraft:gray_shulker_box",
"minecraft:white_shulker_box",
"minecraft:light_gray_shulker_box",
"minecraft:red_shulker_box",
"minecraft:pink_shulker_box",
"minecraft:purple_shulker_box",
"minecraft:magenta_shulker_box",
"minecraft:orange_shulker_box",
"minecraft:brown_shulker_box",
"minecraft:cyan_shulker_box",
"minecraft:light_blue_shulker_box",
"minecraft:yellow_shulker_box",
"minecraft:lime_shulker_box",
"minecraft:green_shulker_box",
"minecraft:blue_shulker_box",
"minecraft:hopper",
"minecraft:chest"
);
//x y
static final Color removeA = new Color(255, 127, 39);
static final Color removeB = new Color(251, 100, 0);
static final Color removeA_Dropped = new Color(255, 13, 90);
static final Color removeB_Dropped = new Color(255, 13, 120);
static final Color keepA = new Color(128, 255, 0);
static final Color keepB = new Color(0, 255, 64);
static final Color waterA = new Color(0, 128, 192);
static final Color waterB = new Color(0, 128, 255);
static final Color keepCoreA = new Color(0, 64, 0);
static final Color keepCoreB = new Color(0, 106, 0);
static final Color activity = new Color(87, 87, 87);
static final Color activityBuffer = new Color(157, 157, 157);
static final Color activityPurged = new Color(230, 230, 230);
static final Color activityBufferPurged = new Color(255, 255, 255);
static final Color workbench_keep = new Color(255, 255, 0);
static final Color workbench_keep_buffer = new Color(128, 128, 0);
static final Color coreEdge = new Color(255, 0, 0);
static int[ ][ ] dataField ;
static Map keepRegionsIn = new TreeMap<>();
static Map keepRegions = new TreeMap<>();
static Map workbenchCalculations = new HashMap<>();
static int radius=0;
static int coreRadius=0;
static int regionRedius = 0;
static int fuckyou = 0;
private static void setRegion(int x,int y, int s)
{
int rx = (int)Math.floor((x)/512.0f);
int ry = (int)Math.floor((y)/512.0f);
keepRegionsIn.putIfAbsent(("r."+rx+"."+ry+".mca"),0);
keepRegionsIn.put(("r."+rx+"."+ry+".mca"),keepRegionsIn.get(("r."+rx+"."+ry+".mca"))+s);
}
private static void setRegionFinal(int x,int y, RegionState s)
{
int rx = (int)Math.floor((x)/512.0f);
int ry = (int)Math.floor((y)/512.0f);
keepRegions.put(("r."+rx+"."+ry+".mca"),s);
}
/**
* @param args the command line arguments
* @throws java.lang.Exception
*/
public static void main(String[] args)throws Exception
{
if(args.length<3)
{
throw new UnsupportedOperationException("not enough parameters");
}
/*
if(args.length>2)
{
targetBlockID = Integer.valueOf(args[2]);
if(args.length>3)
{
removalsOnly = Boolean.valueOf(args[3]);
}
}*/
radius = Integer.valueOf(args[1]);
dataField = new int[radius*2][radius*2];
int regionBase = radius/512;
int regionRemainder = radius%512;
if(regionRemainder>0)
{
regionBase++;
}
coreRadius = Integer.valueOf(args[2]);
int coreBase = coreRadius/512;
int coreRemainder = coreRadius%512;
if(coreRemainder>0)
{
coreBase++;
}
regionRedius = regionBase;
for(int i=0;i
{
//4 als 5 und nen bisschen arithmetik gibt seitwärts-schnittansicht
//id_0 oldblox_1 newblox_2 newdv_3 X_4 height_5 y_6
//10 5 0 0 -1373 27 4008
xx = xx.replace("\"", "");
xx = xx.replace(",", "\t");
String[] xes = xx.split("\\t");
int l = Integer.parseInt(xes[0]);
boolean register=false;
String to = xes[2].intern();
String from = xes[3].intern(); //richtigrum, verfickt und zugenäht
int x= Integer.parseInt(xes[4])+radius,y= Integer.parseInt(xes[6])+radius;
int z = Integer.parseInt(xes[5]);
if(blocktypes.contains(from)||blocktypes.contains(to))
{
if(from!=to) // yes, this works since i interned the strings beforehand :P
{
fuckyou++;
lmaa.println(xx);
if(blocktypes.contains(from))
{
CoordHolder location = new CoordHolder(x,y,z,from);
if(!workbenchCalculations.containsKey(location))
{
workbenchCalculations.put(location,-1);
}
else
{
workbenchCalculations.put(location,workbenchCalculations.get(location)-1);
}
}
if(blocktypes.contains(to))
{
CoordHolder location = new CoordHolder(x,y,z,to);
if(!workbenchCalculations.containsKey(location))
{
workbenchCalculations.put(location,1);
}
else
{
workbenchCalculations.put(location,workbenchCalculations.get(location)+1);
}
}
}
else
{
//System.out.print("Skipped Transaction due to from and to being equal");
}
}
else
{
//-y=up
if(x=0&&y=0)
{
for(int i=-buffer;i0)
{
for(int j=-buffer;j<+1;j++)
{
if((y+j)<(radius*2)&&(y+j)>0)
{
//only switching NONE to BUFFER
if(dataField[y+j][x+i]==BlockState.NONE.ordinal())
{
dataField[y+j][x+i]=BlockState.BUFFER_PURGED.ordinal();
// setRegion(x+i-radius, y+i-radius, 1);
// propagating buffer markers in second pass... buffer rendering handled in same pass
}
}
}
}
}
dataField[y][x]=BlockState.ACTIVITY.ordinal();
setRegion(x-radius, y-radius, 1);
}
}
if(l%10000==0)
{
System.out.print(l+"changes so far\r");
}
});
System.out.println("\n");
System.out.println(fuckyou);
System.out.println("\nDatabase crunched to 100%\n");
System.out.print("\nCalculating Workbenches("+workbenchCalculations.size()+") \n");
lmaa.close();
workbenchCalculations.forEach((c,i) ->
{
if(i>0)
{
System.out.println("workbench at"+c.x+"|"+c.y);
if(c.x<0||c.y<0||c.x>=dataField.length||c.y>=dataField.length)
{
return;
}
System.out.println("workbench kept at"+c.x+"|"+c.y+"| cnt = "+i);
setRegion(c.x-radius,c.y-radius,3*treshold); // force keep
dataField[c.y][c.x]=BlockState.WORKBENCH_FORCED.ordinal();
}
if(i<-1)
{
System.out.println("DAFUQ at"+c.x+"|"+c.y+"| as "+i);
}
});
System.out.println("\nWorkbenches calculated\n");
for(int i=-regionBase;i<=regionBase;i++)
{
for(int j=-regionBase;j<=regionBase;j++)
{
int current=keepRegionsIn.getOrDefault(("r."+(i)+"."+(j)+".mca"),-1);
System.out.println("Processing r."+(i)+"."+(j)+".mca; ("+i+"/"+regionBase+"|"+j+"/"+regionBase);
if(current0) // no activity inside so no need to search for activity spots
{
//highlighgt actively dropped ones differently...
if(((old)!=RegionState.CORE)&&(old!=RegionState.KEEP))
{
System.out.println("Dropping r."+(i)+"."+(j)+".mca; Is: "+old);
keepRegions.put(("r."+(i)+"."+(j)+".mca"),RegionState.DROPPED);
}
for(int pi = 0;pi<512;pi++)
{
for(int pj = 0;pj<512;pj++)
{
int kx = i*512+pi+radius+1;
int ky = j*512+pj+radius+1;
if(kx<0||ky<0||kx>=dataField.length||ky>=dataField.length)
{
continue; // coordinate not valid. can't crunch
}
BlockState k = BlockState.values()[dataField[ky][kx]];
if(k==BlockState.ACTIVITY)
{
dataField[ky][kx]=BlockState.ACTIVITY_PURGED.ordinal();
}
}
}
}
}
else
{
keepRegions.put(("r."+(i)+"."+(j)+".mca"),RegionState.KEEP);
for(int pi = 0;pi<512;pi++)
{
for(int pj = 0;pj<512;pj++)
{
int kx = i*512+pi+radius;
int ky = j*512+pj+radius;
if(kx<0||ky<0||kx>=dataField.length||ky>=dataField.length)
{
continue; // coordinate not valid. can't crunch
}
BlockState k = BlockState.values()[dataField[ky][kx]];
if(k==BlockState.ACTIVITY)
{
if(pimax&&pj>max)
{
keepRegions.put(("r."+(i+1)+"."+(j+1)+".mca"),RegionState.KEEP);
}
if(pi>max)
{
keepRegions.put(("r."+(i+1)+"."+(j)+".mca"),RegionState.KEEP);
}
if (pj>max)
{
keepRegions.put(("r."+(i)+"."+(j+1)+".mca"),RegionState.KEEP);
}
//propagating buffers
int kxmin = Math.max(0,kx-(buffer+1));
int kymin = Math.max(0,ky-(buffer+1));
int kxmax = Math.min(dataField.length,kx+buffer+1);
int kymax = Math.min(dataField.length,ky+buffer+1);
for(int ki = kxmin;kimax&&pj>max)
{
keepRegions.put(("r."+(i+1)+"."+(j+1)+".mca"),RegionState.KEEP);
}
if(pi>max)
{
keepRegions.put(("r."+(i+1)+"."+(j)+".mca"),RegionState.KEEP);
}
if (pj>max)
{
keepRegions.put(("r."+(i)+"."+(j+1)+".mca"),RegionState.KEEP);
}
//propagating buffers
int kxmin = Math.max(0,kx-(workbenchbuffer+1));
int kymin = Math.max(0,ky-(workbenchbuffer+1));
int kxmax = Math.min(dataField.length,kx+(workbenchbuffer+1));
int kymax = Math.min(dataField.length,ky+(workbenchbuffer+1));
for(int ki = kxmin;ki
{
switch(v)
{
case REMOVE:
case DROPPED:
fileActions.println("mv "+k+" oldChunks/");
System.out.println("mv "+k+" oldChunks/");
break;
case CORE:
fileActions.println("echo "+k+" is keepCore");
System.out.println("echo "+k+" is keepCore");
break;
case KEEP:
fileActions.println("echo "+k+" is keep");
System.out.println("echo "+k+" is keep");
break;
case WATERIZE:
fileActions.println("mv "+k+" oldChunksWaterize/");
System.out.println("mv "+k+" oldChunksWaterize/");
fileActions.println("mv waterize/"+k+" ./");
System.out.println("mv waterize/"+k+" ./");
break;
}
});
fileActions.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
//use mcserver;
//mysql> SELECT id,replaced,type,data,x,y,z from `lb-surv` into outfile D:\\emc2\\arca_slash\\heatmap.tsv FIELDS TERMINATED BY `\t` LINES TERMINATED BY `\n`
/*
SELECT blocks.id, blocks.id, blocks.type, blocks.replaced, blocks.x,blocks.y, blocks.z FROM `lb-players` as player, `lb-surv-blocks` as blocks
where player.playerid = blocks.playerid
AND player.UUID NOT LIKE 'l%'
INTO OUTFILE 'C:/lmaa/crunchme/survival2-oct-novirt.csv'
;
*/
/*
SELECT blocks.id, blocks.id, materials.name, materials2.name, blocks.x,blocks.y, blocks.z FROM `lb-players` as player, `lb-surv-blocks` as blocks, `lb-materials` as materials, `lb-materials` as materials2
where player.playerid = blocks.playerid
AND player.UUID NOT LIKE 'l%'
and blocks.type = materials.id
and blocks.replaced = materials2.id
INTO OUTFILE '/tmp/crunchy.csv';
* */