11package com .robotgryphon .compactcrafting .blocks .tiles ;
22
3- import com .robotgryphon .compactcrafting .CompactCrafting ;
43import com .robotgryphon .compactcrafting .blocks .FieldProjectorBlock ;
5- import com .robotgryphon .compactcrafting .core .FieldProjectionSize ;
4+ import com .robotgryphon .compactcrafting .field .FieldProjection ;
5+ import com .robotgryphon .compactcrafting .field .FieldProjectionSize ;
66import com .robotgryphon .compactcrafting .core .Registration ;
77import com .robotgryphon .compactcrafting .crafting .CraftingHelper ;
88import net .minecraft .block .BlockState ;
99import net .minecraft .entity .item .ItemEntity ;
10- import net .minecraft .entity .player .PlayerEntity ;
1110import net .minecraft .item .Item ;
1211import net .minecraft .item .ItemStack ;
1312import net .minecraft .item .Items ;
14- import net .minecraft .particles .ParticleTypes ;
1513import net .minecraft .tileentity .ITickableTileEntity ;
1614import net .minecraft .tileentity .TileEntity ;
17- import net .minecraft .tileentity .TileEntityType ;
1815import net .minecraft .util .Direction ;
1916import net .minecraft .util .math .AxisAlignedBB ;
2017import net .minecraft .util .math .BlockPos ;
21- import net .minecraft .util .math .vector .Vector3d ;
22- import net .minecraft .util .math .vector .Vector3f ;
23- import net .minecraft .util .math .vector .Vector3i ;
24- import net .minecraftforge .items .ItemHandlerHelper ;
2518
19+ import java .time .Instant ;
2620import java .util .*;
2721import java .util .stream .Collectors ;
28- import java .util .stream .Stream ;
2922
3023public class FieldProjectorTile extends TileEntity implements ITickableTileEntity {
3124
32- private FieldProjectionSize projectionSize = FieldProjectionSize .MEDIUM ;
25+ private boolean isCrafting = false ;
26+ private Optional <FieldProjection > field = Optional .empty ();
27+ private int fieldCheckTimeout = 0 ;
3328
3429 public FieldProjectorTile () {
3530 super (Registration .FIELD_PROJECTOR_TILE .get ());
3631 }
3732
38- public Optional <BlockPos > getCenter () {
39- BlockState bs = this .getBlockState ();
40- Direction facing = bs .get (FieldProjectorBlock .FACING );
41-
42-
43- Optional <BlockPos > location = getOppositeProjector ();
44- if (location .isPresent ()) {
45- BlockPos opp = location .get ();
46- int centerOffset = opp .manhattanDistance (pos );
47-
48- BlockPos center = pos .offset (facing , centerOffset / 2 );
49- return Optional .of (center );
50- } else {
51- // No center -- no found opposite
52- return Optional .empty ();
53- }
54- }
55-
56- public Optional <FieldProjectionSize > getFieldSize () {
57- BlockState bs = this .getBlockState ();
58- Direction facing = bs .get (FieldProjectorBlock .FACING );
59-
60- Optional <FieldProjectionSize > matchedSize = Arrays
61- .stream (FieldProjectionSize .values ())
62- .sorted (Comparator .comparingInt (FieldProjectionSize ::getOffset ))
63- .filter (size -> {
64- // check block exists in offset position
65- BlockPos offsetInDirection = pos .offset (facing , size .getOffset () + 1 );
66- BlockState stateInPos = world .getBlockState (offsetInDirection );
67-
68- if (stateInPos .getBlock () instanceof FieldProjectorBlock ) {
69- // We have a field projector
70- Direction otherFpDirection = stateInPos .get (FieldProjectorBlock .FACING );
71- if (otherFpDirection == facing .getOpposite ())
72- return true ;
73- }
74-
75- return false ;
76- })
77- .findFirst ();
33+ @ Override
34+ public void remove () {
35+ super .remove ();
7836
79- return matchedSize ;
37+ // Invalidate field
38+ invalidateField ();
8039 }
8140
8241 /**
@@ -85,15 +44,16 @@ public Optional<FieldProjectionSize> getFieldSize() {
8544 * @return
8645 */
8746 public Optional <BlockPos > getOppositeProjector () {
88- Optional <FieldProjectionSize > size = getFieldSize ();
89- if (size .isPresent ()) {
90- int offset = size .get ().getOffset () + 1 ;
91- BlockPos opposite = getPos ().offset (getFacing (), offset );
47+ if (!field .isPresent ())
48+ return Optional .empty ();
9249
93- return Optional . of ( opposite );
94- }
50+ FieldProjection field = this . field . get ( );
51+ FieldProjectionSize size = field . getFieldSize ();
9552
96- return Optional .empty ();
53+ int offset = (size .getOffset () * 2 ) + 1 ;
54+ BlockPos opposite = getPos ().offset (getFacing (), offset );
55+
56+ return Optional .of (opposite );
9757 }
9858
9959 public Direction getFacing () {
@@ -115,49 +75,87 @@ public boolean isMainProjector() {
11575 return side == Direction .NORTH ;
11676 }
11777
78+ public Optional <BlockPos > getMainProjectorPosition () {
79+ if (this .isMainProjector ())
80+ return Optional .of (this .pos );
81+
82+ if (this .field .isPresent ()) {
83+ FieldProjection fp = this .field .get ();
84+ BlockPos north = fp .getProjectorInDirection (Direction .NORTH );
85+
86+ return Optional .of (north );
87+ }
88+
89+ return Optional .empty ();
90+ }
91+
92+ public void invalidateField () {
93+ this .field = Optional .empty ();
94+ this .fieldCheckTimeout = 20 ;
95+ }
96+
11897 @ Override
11998 public void tick () {
120- if (!isMainProjector ())
121- return ;
122-
123- Optional <AxisAlignedBB > fieldBounds = getFieldBounds ();
124- if (fieldBounds .isPresent ()) {
125- // TODO: Check crafting state of projection field, update that state instead of doing manual work here
126- boolean hasCatalyst = hasCatalystInBounds (fieldBounds .get (), Items .ENDER_PEARL );
127-
128- if (hasCatalyst ) {
129- List <ItemEntity > enderPearls = getCatalystsInField (fieldBounds .get (), Items .ENDER_PEARL );
130-
131- // We dropped an ender pearl in - are there any blocks in the field?
132- // If so, we'll need to check the recipes -- but for now we just use it to
133- // not delete the item if there's nothing in here
134- if (CraftingHelper .hasBlocksInField (world , fieldBounds .get ())) {
135- CraftingHelper .deleteCraftingBlocks (world , fieldBounds .get ());
136- CraftingHelper .consumeCatalystItem (enderPearls .get (0 ), 1 );
137- }
99+ // If we don't have a valid field, search again
100+ if (!field .isPresent ()) {
101+ if (fieldCheckTimeout > 0 ) {
102+ fieldCheckTimeout --;
103+ return ;
138104 }
105+
106+ // Check timeout has elapsed, run field scan
107+ doFieldCheck ();
108+
109+ // If we still don't have a valid field, get out of tick logic
110+ if (!field .isPresent ())
111+ return ;
112+ }
113+
114+ if (fieldCheckTimeout > 0 ) {
115+ fieldCheckTimeout --;
116+ } else {
117+ doFieldCheck ();
139118 }
140119 }
141120
142- private Optional <AxisAlignedBB > getFieldBounds () {
143- Optional <BlockPos > center = getCenter ();
121+ /**
122+ * Invalidates the current field projection and attempts to rebuild it from this position as an initial.
123+ */
124+ private void doFieldCheck () {
125+ Optional <FieldProjection > field = FieldProjection .tryCreateFromPosition (world , this .pos );
126+ if (field .isPresent ()) {
127+ this .field = field ;
128+ return ;
129+ }
144130
145- // No center area - no other projector present
146- if (!center .isPresent ())
147- return Optional .empty ();
131+ this .field = Optional .empty ();
148132
149- BlockPos centerPos = center .get ();
150- Optional <FieldProjectionSize > size = this .getFieldSize ();
151- if (size .isPresent ()) {
152- AxisAlignedBB bounds = new AxisAlignedBB (centerPos ).grow (size .get ().getSize ());
133+ // If we didn't find a valid field, restart timer and keep looking
134+ fieldCheckTimeout = 20 ;
135+ }
153136
154- return Optional .of (bounds );
155- }
137+ private void beginCraft () {
138+ this .isCrafting = true ;
139+ }
156140
157- // No valid field found
158- return Optional .empty ();
141+ private void tickCrafting () {
142+ FieldProjection fp = this .field .get ();
143+ Optional <AxisAlignedBB > fieldBounds = fp .getBounds ();
144+
145+ List <ItemEntity > enderPearls = getCatalystsInField (fieldBounds .get (), Items .ENDER_PEARL );
146+
147+ // We dropped an ender pearl in - are there any blocks in the field?
148+ // If so, we'll need to check the recipes -- but for now we just use it to
149+ // not delete the item if there's nothing in here
150+ if (CraftingHelper .hasBlocksInField (world , fieldBounds .get ())) {
151+ CraftingHelper .deleteCraftingBlocks (world , fieldBounds .get ());
152+ CraftingHelper .consumeCatalystItem (enderPearls .get (0 ), 1 );
153+
154+ this .isCrafting = false ;
155+ }
159156 }
160157
158+
161159 private List <ItemEntity > getCatalystsInField (AxisAlignedBB fieldBounds , Item itemFilter ) {
162160 List <ItemEntity > itemsInRange = world .getEntitiesWithinAABB (ItemEntity .class , fieldBounds );
163161 return itemsInRange .stream ()
@@ -180,7 +178,6 @@ private boolean hasCatalystInBounds(AxisAlignedBB bounds, Item itemFilter) {
180178
181179 private int collectItems (List <ItemEntity > itemsInRange ) {
182180 return itemsInRange .stream ()
183- // .filter(ise -> ise.getItem().getItem() == item)
184181 .map (ItemEntity ::getItem )
185182 .map (ItemStack ::getCount )
186183 .mapToInt (Integer ::intValue )
@@ -189,11 +186,20 @@ private int collectItems(List<ItemEntity> itemsInRange) {
189186
190187 @ Override
191188 public AxisAlignedBB getRenderBoundingBox () {
192- Optional <AxisAlignedBB > field = this .getFieldBounds ();
193- if (field .isPresent ()) {
194- return field .get ().grow (10 );
189+ // Check - if we have a valid field use the entire field plus space
190+ // Otherwise just use the super implementation
191+ if (this .field .isPresent ()) {
192+ FieldProjection fp = this .field .get ();
193+ if (!fp .getBounds ().isPresent ())
194+ return super .getRenderBoundingBox ();
195+
196+ return fp .getBounds ().get ().grow (10 );
195197 }
196198
197199 return super .getRenderBoundingBox ();
198200 }
201+
202+ public Optional <FieldProjection > getField () {
203+ return this .field ;
204+ }
199205}
0 commit comments