Skip to content

Instantly share code, notes, and snippets.

@Tictim
Created December 2, 2018 13:23
Show Gist options
  • Save Tictim/c9d1f03a021f01dba600a5bce3d78552 to your computer and use it in GitHub Desktop.
Save Tictim/c9d1f03a021f01dba600a5bce3d78552 to your computer and use it in GitHub Desktop.
public abstract class ItemScore{
public static final ItemScore SCORE_APPLE = new ItemScoreTutorial();
public static final ItemScore SCORE_CHARCOAL = new ItemScoreTutorial2();
public static final ItemScore SCORE_IRON = new ItemScoreTutorial3();
public static final ItemScore SCORE = new ItemScoreSimple();
public abstract int getScore(ItemStack stack);
/**
* 튜토리얼 전용. 이 구조는 추천하지 않음.
* 아이템이 사과인지 테스트함.
*/
public static class ItemScoreTutorial extends ItemScore{
@Override
public int getScore(ItemStack stack){
return stack.getItem()==Items.APPLE ? 1 : 0;
}
}
/**
* 튜토리얼 전용. 이 구조는 추천하지 않음.
* 아이템이 목탄인지 테스트.
* 거의 이 메소드를 이용하게 될 거임. nbt 검사 왜 해
*/
public static class ItemScoreTutorial2 extends ItemScore{
@Override
public int getScore(ItemStack stack){ // 대미지값을 검사한다
return stack.getItem()==Items.COAL&&stack.getItemDamage()==1 ? 1 : 0;
}
}
/**
* 튜토리얼 전용. 이 구조는 추천하지 않음.
* 아이템이 철인지 테스트.
*/
public static class ItemScoreTutorial3 extends ItemScore{
@Override
public int getScore(ItemStack stack){
// ore dick의 기본적인 활용방법.
// 'ingotIron' 아이템들의 샘플이 들어 있는 NonNullList를 꺼내다가 박아놓고 여기 이거 있냐고 물어본다.
// containsMatch(...) 메소드의 첫 번째 boolean은 뭐에요? 이건 strict한 검사를 켤지 끌지 여부인데, 대미지값 와일드카드(32767)의 사용을 불허(true)/허용(false)한다.
// 이 검사를 허용하면 와일드카드 아이템도 네 맞워유~ 해주고, 불허하면 와일드카드 그딴거 없이 다음아이템 부른다.
// 이것도 복잡하면 월드 안에서 자동화하다 만지는 상황에서는 strict를 true로, 레시피에서는 false로 한다고 해라
return OreDictionary.containsMatch(true, OreDictionary.getOres("ingotIron"), stack) ? 1 : 0;
}
}
/**
* 초보적인 아이템 검사 구현. 기존 Item 기반 검사와 오어딕 기반 검사를 쓰깐다.
*/
public static class ItemScoreSimple extends ItemScore{
/**
* 와! ToIntFunction! 너무어렵다! 개소리고 ItemStack 인자 하나 받아서 int쌈
* 아이템을 키 값으로 하는 이유는? List로 function들을 다 담아놓으면 스코어를 불러올때마다 list 전체를 뒤지고 function을 호출하고 지지고 볶고 지랄을 해야 하기 때문이다
* 일종의 머리쓰는 자료구조 최적화인셈
*/
private final Map<Item, ToIntFunction<ItemStack>> itemBasedScores = new HashMap<>();
/**
* 위와 비슷하지만, 키 값이 다르다. 오어딕 값을 저장하기때문
* 위 예제와 비슷하게, 만약 당신 모드의 성능이 바닥을 뚫고 내핵까지 곤두박질치는걸 보고 싶으면 키값을 빼버리고 List를 써도 된다.
* 하지만 둘 다 리스트로 만든다고 해서 두 개 리스트를 쓰까버리면 안된다. 아이템 검사는 무조건 오어딕 검사보다 앞서서 벌어지길 원할 거니까.
*/
private final Map<String, ToIntFunction<ItemStack>> oreDictBasedScores = new HashMap<>();
/**
* 아이템 등록을 생성자에서 다해버리는건 추천하지 않는다. 유연성이 없다.
* 예제니깐 신경안씀
*/
public ItemScoreSimple(){
// 람다식도 볼줄알아야지 이놈!
// 물론 모든 아이템 점수를 람다식으로 추가해버리는건 미친짓이다. 람다식은 하나하나가 전부 익명의 클래스와 비슷하게 취급된다. 즉 재활용조차 안되고 심지어 개느림
// 여기서는 예제니깐 그다지 신경을 쓰지 않겠다. 이 예제를 실전에서 쓸땐 검사하는 클래스를 만드셈
itemBasedScores.put(Items.APPLE, s -> s.getItem()==Items.APPLE ? 1 : 0);
itemBasedScores.put(Items.COAL, s -> s.getItem()==Items.COAL&&s.getItemDamage()==1 ? 1 : 0);
oreDictBasedScores.put("ingotIron", s -> OreDictionary.containsMatch(true, OreDictionary.getOres("ingotIron"), s) ? 1 : 0);
}
@Override
public int getScore(ItemStack stack){
if(!stack.isEmpty()){ // 비엇다구요? 아~꺼져요 그럼
ToIntFunction<ItemStack> f = itemBasedScores.get(stack.getItem());
if(f!=null){
int v = f.applyAsInt(stack);
if(v>0) return v*stack.getCount();
}
for(int oreId : OreDictionary.getOreIDs(stack)){
// 이건 나도몰랏네,, ItemStack에서 바로 String형태로 뽑을수 있는줄알앗음
// 이렇게 되면 oreDictBasedScores 맵의 키값을 Integer로 해서 바로 value를 뽑아버릴수도 있겠음. 그게낫겠다
String oreName = OreDictionary.getOreName(oreId);
// 카더라로 들엇고 실험은 안해봣는데, 로컬 필드는 재활용하는거보다 그냥 새로 만드는게 연산이 빠르다고 함
// 필드에 뒤집어씌우면 final필드로 인정이 안되니까 거기서 차이가 발생해서 그런건가???나도모르겟음
// 굳이안해도됨
ToIntFunction<ItemStack> f2 = oreDictBasedScores.get(oreName);
if(f2!=null){
int v = f2.applyAsInt(stack);
if(v>0) return v*stack.getCount();
}
}
}
return 0;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment